[KeyHelp]
key = ctrl shift H
type = toggle
run = CommandListHelp

[CommandListHelp]
; The pre commands run when the F1 key is first pressed. Set the current help
; text to the full help text and run the formatting shader
pre ResourceHelp = ref ResourceHelpFull
pre ResourceParams = ref ResourceParamsFull
pre run = CustomShaderFormatText
; Setting the short help text to null disables the timeout in the present
; command list:
pre ResourceHelpShort = null
; The post commands run when the help key is pressed again. Set the current
; help text to null to disable the help shader:
post ResourceHelp = null

[Constants]
; The Constants command list is used for initialisation on application load
; time and after config reload. We set up the short help message here:
ResourceHelp = ref ResourceHelpShort
ResourceParams = ref ResourceParamsShort
global $last_window_width
global $last_window_height
global $notification_timeout

[Present]
local $bak_x = x
local $bak_y = y
if ResourceHelp !== null
	x = window_width
	y = window_height
	if window_width != $last_window_width || window_height != $last_window_height
		; Resolution changed, reformat text
		$last_window_width = window_width
		$last_window_height = window_height
		run = CustomShaderFormatText
	endif
	gs-t112 = ResourceHelpCS2GS
	gs-t113 = ResourceHelp
	gs-t114 = ResourceParams
	ps-t114 = ResourceParams
	run = CustomShaderRenderText
	gs-t112 = null
	gs-t113 = null
	gs-t114 = null
	ps-t114 = null

	; Automatically clear the short help prompt a few seconds after
	; launching the game
	if ResourceHelpShort !== null && time > 10.0
		ResourceHelpShort = null
		ResourceHelp = null
	endif
endif
if ResourceNotification !== null
	x = window_width
	y = window_height
	if window_width != $last_window_width || window_height != $last_window_height
		; Resolution changed, reformat text
		$last_window_width = window_width
		$last_window_height = window_height
		run = CustomShaderFormatText
	endif
	gs-t112 = ResourceNotificationCS2GS
	gs-t113 = ResourceNotification
	gs-t114 = ResourceNotificationParams
	ps-t114 = ResourceNotificationParams
	run = CustomShaderRenderText
	gs-t112 = null
	gs-t113 = null
	gs-t114 = null
	ps-t114 = null
	if time > $notification_timeout
		ResourceNotification = null
	endif
endif
x = $bak_x
y = $bak_y

; Custom resources that load the long and short help text from file:
[ResourceHelpFull]
type = buffer
format = R8_UINT
filename = help.txt
[ResourceHelpShort]
type = buffer
format = R8_UINT
filename = help_short.txt

; Using these parameter buffers as a way to pass in constant parameters without
; taking up any of the IniParams slots while still allowing the parameters to
; be customised on a per-message basis.
[ResourceParamsFull]
type = StructuredBuffer
array = 1
data = R32_FLOAT  -0.8 0.9 0.8 -1   1 0.7 0.15 1   0 0 0 0.75   0.01 0.01   1 1   0   1.0
;                 ^^^^Rectangle^^ | ^^^Colour^^^ | Background | ^Border^^ | ^ ^ | ^ | ^-- font scale
;                 x1   y1  x2  y2 | r g   b    a | r g b a    | horz vert |  ^  | ^------ text alignment: 0=left 1=center 2=right
;                   range -1:+1   |              | r g b a    | horz vert |  ^----------- h/v-anchor: 0=none 1=left/top 2=center 3=right/bottom
[ResourceParamsShort]
type = StructuredBuffer
array = 1
data = R32_FLOAT  -0.93 -0.9 +1 -0.9   1 0.7 0.15 1   0 0 0 0.75   0.01 0.01   1 3   1   1.0
;                 ^Bounds Rectangle^ | ^^^Colour^^^ | Background | ^Border^^ | ^ ^ | ^ | ^-- font scale
;                 x1    y1   x2 y2   | r g   b    a | r g b a    | horz vert |  ^  | ^------ text alignment: 0=left 1=center 2=right
;                    range -1:+1     |              |            |           |  ^----------- h/v-anchor: 0=none 1=left/top 2=center 3=right/bottom

; These resources hold the currently displayed help text and parameters. When
; ResourceHelp is null the shader will not be run:
[ResourceHelp]
[ResourceParams]
[ResourceNotification]
[ResourceNotificationParams]
type = StructuredBuffer
array = 1
data = R32_FLOAT  -1.00 -1.0 +1 -1.0   0.25 1 0.25 1   0 0 0 0.75   0.00 0.00   1 3   0   1.0
;                 ^Bounds Rectangle^ | ^^^Colour^^^^ | Background | ^Border^^ | ^ ^ | ^ | ^-- font scale
;                 x1    y1   x2 y2   | r    g b    a | r g b a    | horz vert |  ^  | ^------ text alignment: 0=left 1=center 2=right
;                    range -1:+1     |               |            |           |  ^----------- h/v-anchor: 0=none 1=left/top 2=center 3=right/bottom

[ResourceFont]
; Note that this font has the size of each character embedded in the unused
; space of the final character, which the geometry shader uses to render each
; character the correct width. This font was generated with gen_bm_font.py,
; then converted to DDS (because our PNG loading seems to be broken o_O):
filename = LiberationSans-Bold.dds

[ResourceHelpCS2GS]
; A buffer passed from the formatting compute shader to the geometry shader,
; indicating which shader invocation draws which text at what position.
type = StructuredBuffer
stride = 16
array = 4096
[ResourceNotificationCS2GS]
type = StructuredBuffer
stride = 16
array = 4096

[CustomShaderFormatText]
; The compute shader scans the text and breaks it up into smaller chunks for
; each geometry shader invocation to render (max 64 characters each),
; calculating the position on the screen where each chunk of text is positioned
; wrapping long lines as needed. This is only run when necessary, not every
; frame.
cs = help.hlsl

local $bak_x = x
local $bak_y = y
x = window_width
y = window_height

cs-t100 = ResourceFont
if ResourceHelp !== null
	cs-t113 = ResourceHelp
	cs-t114 = ResourceParams
	clear = ResourceHelpCS2GS
	cs-u0 = ResourceHelpCS2GS
	dispatch = 1, 1, 1
endif
if ResourceNotification !== null
	cs-t113 = ResourceNotification
	cs-t114 = ResourceNotificationParams
	clear = ResourceNotificationCS2GS
	cs-u0 = ResourceNotificationCS2GS
	dispatch = 1, 1, 1
endif

cs-u0 = null
cs-t100 = null
cs-t113 = null
cs-t114 = null
x = $bak_x
y = $bak_y

[CustomShaderRenderText]
; The vertex shader passes draw indexes to the geometry shader:
vs = help.hlsl
; The geometry shader generates the text for a given draw index:
gs = help.hlsl
; The pixel shader draws the font:
ps = help.hlsl
; Allows us to use SV_Position.z to pack a texcoord, increasing the character
; limit per geometry shader invocation:
depth_clip_enable = false
cull = none
; Enable alpha blending. To change the text colour, edit the pixel shader:
blend = add one inv_src_alpha
; Use points as the primitive from the vertex shader to the geometry shader:
topology = point_list
run = CommandListUnbindAllRenderTargets
o0 = set_viewport no_view_cache bb
; Font is passed into the pixel shader (to draw it) *and* the geometry shader
; (as the character sizes are encoded in the final character of the font):
gs-t100 = ResourceFont
ps-t100 = ResourceFont
post gs-t100 = null
post ps-t100 = null
; Change this number to limit how much text may be drawn:
draw = 4096, 0
