luv

Workshop wiki

tape.lisp

luvcraft/clim/tape.lisp

system luvcraft · 25 definitions · on GitHub

in-package#:luvcraft.clim

The tape's question: a small panel that asks for a YouTube code.

Focusing a tape (luvcraft/tape.lisp) opens this in the middle of the view, the way the legend opens: a McCLIM frame drawn into a GPU mirror and composited as a HUD overlay. Since the focus offers no command table, every key the window layer does not claim comes here: letters and digits go into the draft, RET answers, Esc and Tab put the question away unanswered.

defparameter*tape-prompt-width*560
defparameter*tape-prompt-height*178
defparameter*tape-prompt-margin*26
defparameter*tape-prompt-panel-ink*
make-rgb-color0.110.110.105
defparameter*tape-prompt-field-ink*
make-rgb-color0.060.060.058
defparameter*tape-prompt-text-ink*
make-rgb-color0.910.890.82
defparameter*tape-prompt-muted-ink*
make-rgb-color0.600.600.55
defparameter*tape-prompt-edge-ink*
make-rgb-color0.420.420.38
defparameter*tape-prompt-accent-ink*
make-rgb-color0.850.620.30
defparameter*tape-prompt-warn-ink*
make-rgb-color0.850.400.32
defclasstape-prompt-pane
application-pane
define-application-frameluvcraft-tape-prompt
session:initarg:session:readertape-prompt-session
x:initarg:x:readertape-prompt-x
y:initarg:y:readertape-prompt-y
z:initarg:z:readertape-prompt-z
draft:initform"":accessortape-prompt-draft
complaint:initformnil:accessortape-prompt-complaint:documentation"What was wrong with the last answer, or NIL."
:menu-barnil
:panes
sheet
:layouts
default
horizontallysheet
defmethodhandle-repaint
declare
ignoreregion
let*
frame
pane-framepane
draft
tape-prompt-draftframe
field-top74
field-bottom116
with-bounding-rectangle*
lefttopright-edgebottom
pane
progn
draw-rectangle*panelefttopright-edgebottom:ink*tape-prompt-panel-ink*
draw-rectangle*panelefttopright-edgebottom:fillednil:line-thickness2:ink*tape-prompt-edge-ink*
draw-text*pane"tape"margin34:align-y:center:text-size22:text-face:bold:ink*tape-prompt-text-ink*
draw-text*pane"Esc leaves it blank"right34:align-x:right:align-y:center:text-size14:ink*tape-prompt-muted-ink*
draw-text*pane"which YouTube video? a code or a link"margin58:align-y:center:text-size14:ink*tape-prompt-muted-ink*

The field.

draw-rectangle*panemarginfield-toprightfield-bottom:ink*tape-prompt-field-ink*
draw-rectangle*panemarginfield-toprightfield-bottom:fillednil:line-thickness1:ink*tape-prompt-accent-ink*
let*
text-x
+margin12
text-y
/
+field-topfield-bottom
2
width
text-sizepanedraft:text-style
make-text-stylenilnil18
draw-text*panedrafttext-xtext-y:align-y:center:text-size18:ink*tape-prompt-text-ink*

The caret, a bar after the draft.

draw-rectangle*pane
+text-xwidth2
-text-y11
+text-xwidth4
+text-y11
:ink*tape-prompt-accent-ink*
draw-text*pane
or
tape-prompt-complaintframe
"RET fetches it; the reel becomes a film when it lands"
margin:align-y:center:text-size14:ink
defunrepaint-tape-prompt
let
mirror
sheet-direct-mirror
frame-top-level-sheetframe
check-typemirrormcluv:luv-gpu-mirror
frame

--------------------------------------------------------------------- The overlay: the panel in the middle of the screen, as the legend is.

defparameter*tape-prompt-scale*1.7

How much larger than its own pixels the panel is shown: a short question in the middle of the view wants to be read from where the player stands.

defuntape-prompt-screen-state
overlay

Place the panel, scaled, in the middle of the viewport.

let*
viewport-size
luv:canvas-extent
luvcraft:luvcraft-session-context
mcluv:widget-overlay-sessionoverlay
source-width
firstsource-size
source-height
secondsource-size
viewport-width
firstviewport-size
viewport-height
secondviewport-size
scale
min*tape-prompt-scale*
/
-viewport-width48.0
source-width
/
-viewport-height48.0
source-height
half-width
/
*source-widthscale
viewport-width
half-height
/
*source-heightscale
viewport-height
make-array12:element-type'single-float:initial-contents
mapcar
lambda
value
coercevalue'single-float
list0.00.00.01.0half-width0.00.00.00.0half-height0.00.0
defmethodluvcraft:luvcraft-overlay-stage
declare
ignoreoverlay
:hud
defmethodluvcraft:encode-luvcraft-overlay
sessionpasssurface-texture
declare
ignorepass
overlay

The question is asked by the tape, not by the crosshair: nothing targets the panel itself, and the camera does no more than lean in a little.

defmethodluvcraft:luvcraft-focus-score
declare
ignoreoverlaysession
nil
defunclose-tape-prompt
overlaysession
when
eqoverlay
luvcraft:luvcraft-session-modal-focussession
nil
defunanswer-tape-prompt
overlaysession

Take the draft as an answer: start the download and put the panel away, or say what is wrong with it and keep asking.

let*
frame
mcluv:widget-overlay-frameoverlay
draft
tape-prompt-draftframe
cond
zerop
length
string-trim" "draft
close-tape-promptoverlaysession
nullvideo-id
setf
tape-prompt-complaintframe
"that is not a YouTube code or link I recognise"
t
luvcraft:begin-tape-downloadsession
tape-prompt-xframe
tape-prompt-yframe
tape-prompt-zframe
video-id
close-tape-promptoverlaysession
defmethodluvcraft:handle-luvcraft-focus-event
let*
frame
mcluv:widget-overlay-frameoverlay
key
luv:canvas-key-event-key-nameevent
character
luv:canvas-key-event-characterevent
paste-p
and
eqkey:v
intersection'
:super:control
luv:canvas-key-event-modifiersevent
casekey
:escape:tab
close-tape-promptoverlaysession
:return:keypad-enter
answer-tape-promptoverlaysession
:v

Cmd-V or Ctrl-V pastes: a link is what a player has on the clipboard, and typing eleven random letters is nobody's idea of fun.

ifpaste-p
alexandria:when-let
setf
tape-prompt-draftframe
concatenate'string
tape-prompt-draftframe
string-trim'
#\Space#\Tab#\Return#\Newline
subseqtext0
position#\Newlinetext
tape-prompt-complaintframe
nil
when
andcharacter
graphic-char-pcharacter
setf
tape-prompt-draftframe
concatenate'string
tape-prompt-draftframe
stringcharacter
tape-prompt-complaintframe
nil
:backspace
let
draft
tape-prompt-draftframe
when
plusp
lengthdraft
setf
tape-prompt-draftframe
subseqdraft0
1-
lengthdraft
tape-prompt-complaintframe
nil
t
when
andcharacter
graphic-char-pcharacter
<
length
tape-prompt-draftframe
120
setf
tape-prompt-draftframe
concatenate'string
tape-prompt-draftframe
stringcharacter
tape-prompt-complaintframe
nil
t

--------------------------------------------------------------------- Opening.

defmethodluvcraft:open-tape-prompt

Create, attach, and focus the panel asking which video the tape at X,Y,Z should fetch.

let*
port
find-port:server-path'
:luv-gpu
manager
or
first
climi::frame-managersport
make-instance'mcluv:luv-frame-manager:portport
frame
let
mcluv:*embedded-mirror-target*
luvcraft:luvcraft-session-canvassession
mcluv:*embedded-mirror-context*
luvcraft:luvcraft-session-contextsession
mcluv:*embedded-mirror-device*
luvcraft:luvcraft-session-devicesession
make-application-frame'luvcraft-tape-prompt:frame-managermanager:enablet:sessionsession:xx:yy:zz
setf
frame-pretty-nameframe
"tape"
let*
mirror
sheet-direct-mirror
frame-top-level-sheetframe
overlay
make-instance'luvcraft-tape-prompt-overlay:sessionsession:frameframe:mirrormirror
setf
mcluv:mirror-compositormirror
overlay
overlay