waves/public/assets/g/fnaf2/index.html
2025-04-17 20:43:10 -05:00

1878 lines
77 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>FNAF 2</title>
<link href="project/splash.webp" rel="shortcut icon" type="image/x-icon"/>
<script type="text/javascript">
window.errors = []
if (window.addEventListener) {
window.addEventListener(
'error',
function (e) {
if (e.message) {
if (e.error && e.error.stack) {
if (e.message.indexOf('Uncaught SyntaxError') === 0) {
window.errors.push(
e.message +
' at ' +
e.filename +
':' +
e.lineno +
':' +
e.colno
)
} else {
window.errors.push(e.error.stack)
}
if (window.onNewError) window.onNewError()
}
} else {
window.errors.push(
'Problem loading ' + (e.target.src || e.target.href)
)
if (window.onNewError) window.onNewError()
}
window.onerror = null
},
true
) // true so that errors bubble up to window
window.addEventListener(
'unhandledrejection',
function (e) {
window.errors.push(
e.reason && (e.reason.stack || e.reason.message || e.reason)
)
if (window.onNewError) window.onNewError()
},
false
)
}
window.onerror = function (message, source, lineno, colno, error) {
if (colno) {
lineno += ':' + colno
}
if (error && error.stack) {
window.errors.push(error.stack)
} else {
window.errors.push(message + ' at ' + source + ':' + lineno)
}
if (window.onNewError) window.onNewError()
}
</script>
<style>
html,
body {
height: 100%;
}
body,
::backdrop {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: black;
font-size: 0;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
overflow: hidden;
background-position: center;
background-size: cover;
}
#wrapper {
display: block;
position: relative;
}
.no-cursor #wrapper {
cursor: none;
}
.loading #wrapper {
visibility: hidden;
}
.stretch-stage #wrapper {
width: 100vw;
height: 100vh;
}
/* CSS for proportional wrapper scaling is added dynamically by htmlifier.ts */
#monitors {
position: absolute;
top: 0;
left: 0;
}
#stage {
width: 100%;
height: 100%;
}
#loading-progress {
display: none;
position: fixed;
bottom: 20px;
left: 20px;
right: 20px;
border-radius: 20px;
--progress: 0%;
z-index: 100;
}
.show-loading-progress #loading-progress {
display: block;
}
#loading-progress::before {
content: attr(data-progress);
position: absolute;
bottom: 100%;
left: 0;
right: 0;
text-align: center;
font-size: 1.5rem;
margin-bottom: 15px;
}
#loading-progress::after {
content: '';
display: block;
height: 16px;
border-radius: 20px;
width: var(--progress);
}
#loading-image {
position: fixed;
max-width: 100%;
max-height: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
.stretch-loading-image #loading-image {
width: 100%;
height: 100%;
}
.buttons {
position: fixed;
top: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
border-bottom-left-radius: 12px;
}
.buttons .button,
.buttons button {
display: none;
-webkit-appearance: none;
border: none;
background: none;
width: 48px;
height: 48px;
cursor: pointer;
background-repeat: no-repeat;
background-position: center;
background-size: 24px;
}
.buttons button:disabled,
#add-sprite-file:disabled + #add-sprite-btn {
cursor: auto;
opacity: 0.5;
}
#start-btn {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"%3E%3Cpath d="M8 5v14l11-7z" fill="%23fff"/%3E%3C/svg%3E%0A');
}
.running #start-btn {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"%3E%3Cpath d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z" fill="%23fff"/%3E%3C/svg%3E');
}
#stop-btn {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"%3E%3Cpath d="M6 6h12v12H6z" fill="%23fff"/%3E%3C/svg%3E%0A');
}
#fullscreen-btn {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"%3E%3Cpath d="M14 28h-4v10h10v-4h-6v-6zm-4-8h4v-6h6v-4H10v10zm24 14h-6v4h10V28h-4v6zm-6-24v4h6v6h4V10H28z" fill="%23fff"/%3E%3C/svg%3E');
}
.fullscreen #fullscreen-btn {
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"%3E%3Cpath d="M10 32h6v6h4V28H10v4zm6-16h-6v4h10V10h-4v6zm12 22h4v-6h6v-4H28v10zm4-22v-6h-4v10h10v-4h-6z" fill="%23fff"/%3E%3C/svg%3E');
}
#download-btn {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M5,20h14v-2H5V20z M19,9h-4V3H9v6H5l7,7L19,9z'/%3E%3C/svg%3E");
}
#add-sprite-btn {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z'/%3E%3C/svg%3E");
}
#add-sprite-file {
display: none;
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
.show-start-stop-btns #start-btn,
.show-start-stop-btns #stop-btn,
.show-fullscreen-btn #fullscreen-btn,
.show-download-btn #download-btn,
.show-add-sprite-btn #add-sprite-btn,
.show-add-sprite-btn #add-sprite-file {
display: inline-block;
}
.monitor {
position: absolute;
border: 1px solid transparent;
border-radius: 0.25rem;
font-size: 0.75rem;
overflow: hidden;
padding: 3px;
white-space: pre;
}
.show-monitor-box .monitor {
border-color: rgba(0, 0, 0, 0.2);
background-color: rgba(0, 0, 0, 0.3);
}
.monitor-label {
margin: 0 5px;
font-weight: bold;
}
.monitor-value {
display: inline-block;
vertical-align: top;
min-width: 34px;
text-align: center;
border-radius: 0.25rem;
overflow: hidden;
text-overflow: ellipsis;
user-select: text;
transform: translateZ(0);
}
.default .monitor-value,
.slider .monitor-value {
margin: 0 5px;
padding: 1px 3px;
}
.show-monitor-box .default .monitor-value,
.show-monitor-box .slider .monitor-value {
background-color: rgba(0, 0, 0, 0.5);
}
.large {
padding: 0.1rem 0.25rem;
min-width: 3rem;
}
.show-monitor-box .large {
background-color: rgba(0, 0, 0, 0.6);
}
.large .monitor-label {
display: none;
}
.large .monitor-value {
font-size: 1rem;
width: 100%;
}
.list {
padding: 0;
overflow: auto;
overflow-x: hidden;
}
.list .monitor-label {
text-align: center;
padding: 3px;
width: 100%;
display: block;
margin: 0;
box-sizing: border-box;
white-space: pre-wrap;
}
.list .monitor-value {
display: block;
}
.row {
display: flex;
align-items: center;
padding: 2px;
height: 24px;
box-sizing: border-box;
transform: translateZ(0);
}
.index {
font-weight: bold;
margin: 0 3px;
flex: none;
}
.row-value {
flex: auto;
margin: 0 3px;
text-align: left;
border-radius: 0.25rem;
border: 1px solid transparent;
height: 22px;
padding: 3px 5px;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
}
.show-monitor-box .row-value {
border-color: rgba(0, 0, 0, 0.2);
background-color: rgba(0, 0, 0, 0.5);
}
.slider input {
display: block;
width: 100%;
transform: translateZ(0);
}
#asking-box {
display: none;
position: absolute;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(33, 33, 33, 0.7);
}
.asking #asking-box {
display: block;
}
#question {
display: block;
margin: 0 10px;
margin-top: 10px;
font-size: 12px;
color: white;
}
#answer {
border: none;
background: none;
width: 100%;
font: inherit;
font-size: 16px;
color: white;
padding: 10px;
box-sizing: border-box;
}
#answer:focus {
outline: none;
}
#errors {
-webkit-appearance: none;
border: none;
background: rgba(255, 0, 0, 0.7);
color: white;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
display: none;
}
</style> <style>
#loading-progress {
border: 1px solid #00ffff;
}
#loading-progress::before {
color: #00ffff;
}
#loading-progress::after {
background-color: #00ffff;
}
.monitor {
color: #ffffff;
}
</style>
</head>
<body class="loading stretch-stage show-loading-progress stretch-loading-image show-fullscreen-btn show-monitor-box">
<div id="wrapper">
<canvas id="stage"></canvas>
<div id="monitors"></div>
<div id="asking-box">
<label id="question" for="answer">Question</label>
<input type="text" id="answer" />
</div>
</div>
<div id="loading-progress" data-progress="0%"></div>
<div class="buttons">
<!--
Only support sprite files (no images) for now. See
https://github.com/SheepTester/htmlifier/issues/67#issuecomment-894746718
-->
<input
type="file"
id="add-sprite-file"
accept=".sprite2, .sprite3"
aria-label="Select a Scratch sprite to add"
multiple
/>
<label
class="button"
id="add-sprite-btn"
for="add-sprite-file"
title="Add Scratch sprite to project"
></label>
<button id="download-btn" aria-label="Download Scratch project"></button>
<button id="start-btn" aria-label="Start"></button>
<button id="stop-btn" aria-label="Stop" disabled></button>
<button id="fullscreen-btn" aria-label="Enter/exit fullscreen"></button>
</div>
<textarea id="errors" readonly></textarea>
<script src="project/vm.js"></script> <script>
const noop = () => null
window.Scratch = {
get vm () {
return window.vm
},
get renderer () {
return window.vm.runtime.renderer
},
get audioEngine () {
return window.vm.runtime.audioEngine
},
get bitmapAdapter () {
return window.vm.runtime.v2BitmapAdapter
},
get videoProvider () {
return window.vm.runtime.ioDevices.video.provider
}
}
const CLOUD_PREFIX = '\u2601 '
window.setCloud = (name, value) => {
vm.postIOData('cloud', {
varUpdate: {
name: CLOUD_PREFIX + name,
value
}
})
}
function postError (err) {
setCloud('eval error', err.toString())
}
class CloudProvider {
constructor (options) {
this._serverUrl = options.cloud.serverUrl
this._specialBehaviours = options.cloud.specialBehaviours
this._options = options
this._ws = null
this.createVariable = noop
this.renameVariable = noop
this.deleteVariable = noop
this._handleMessage = event => {
event.data.split('\n').forEach(message => {
if (message) {
const { name, value } = JSON.parse(message)
vm.postIOData('cloud', {
varUpdate: { name, value }
})
}
})
}
this._handleOpen = () => {
this._sendData({ method: 'handshake' })
}
this._handleClose = () => {
setTimeout(() => this._openConnection(), 500)
}
this.handleUrlChange = () => {
setCloud('url', window.location.href)
}
if (this._specialBehaviours) {
window.addEventListener('hashchange', this.handleUrlChange)
window.addEventListener('popstate', this.handleUrlChange)
// Paste output
window.addEventListener('paste', event => {
setCloud(
'pasted',
(event.clipboardData || window.clipboardData).getData('text')
)
})
}
if (this._serverUrl) {
this._openConnection()
}
}
_openConnection () {
try {
this._ws = new WebSocket(this._serverUrl)
} catch (error) {
console.warn(error)
return
}
this._ws.onmessage = this._handleMessage
this._ws.onopen = this._handleOpen
this._ws.onclose = this._handleClose
}
_sendData (data) {
data.user = this._options.username
data.project_id = this._options.cloud.projectId
this._ws.send(JSON.stringify(data) + '\n')
}
updateVariable (name, value) {
if (this._specialBehaviours) {
let matched = true
if (name === CLOUD_PREFIX + 'eval') {
try {
Promise.resolve(eval(value))
.then(output => {
setCloud('eval output', output)
})
.catch(postError)
} catch (error) {
postError(error)
}
} else if (name === CLOUD_PREFIX + 'open link') {
try {
window.open(value, '_blank')
} catch (error) {
postError(error)
}
} else if (name === CLOUD_PREFIX + 'redirect') {
window.location = value
} else if (name === CLOUD_PREFIX + 'set clipboard') {
try {
navigator.clipboard.writeText(value).catch(postError)
} catch (error) {
postError(error)
}
} else if (name === CLOUD_PREFIX + 'set server ip') {
this._cloudHost = value
if (this._ws) {
this._ws.onclose = noop
this._ws.close()
}
this._openConnection()
} else if (name === CLOUD_PREFIX + 'username') {
this._options.username = value
vm.postIOData('userData', { username: value })
} else {
matched = false
}
if (matched) {
return
}
}
if (
!this._serverUrl ||
(this._specialBehaviours &&
name.startsWith(CLOUD_PREFIX + 'local storage'))
) {
try {
localStorage.setItem('[s3] ' + name, value)
} catch (error) {
postError(error)
}
} else {
this._sendData({ method: 'set', name, value })
}
}
requestCloseConnection () {
if (
this._ws &&
this._ws.readyState !== WebSocket.CLOSING &&
this._ws.readyState !== WebSocket.CLOSED
) {
this._ws.onclose = noop
this._ws.close()
}
}
}
// Based on
// https://github.com/LLK/scratch-gui/blob/7b658c60c7c04055e575601a861195fe6c9933f3/src/lib/video/camera.js
// https://github.com/LLK/scratch-gui/blob/7b658c60c7c04055e575601a861195fe6c9933f3/src/lib/video/video-provider.js
class VideoProvider {
constructor (width, height) {
this._dimensions = [width, height]
this.mirror = true
this._frameCacheTimeout = 16
this._video = null
this._track = null
this._workspace = []
}
get video () {
return this._video
}
enableVideo () {
this.enabled = true
return this._setupVideo()
}
disableVideo () {
this.enabled = false
if (this._singleSetup) {
this._singleSetup
.then(this._teardown.bind(this))
.catch(err => this.onError(err))
}
}
_teardown () {
if (this.enabled === false) {
requestStack.pop()
const disableTrack = requestStack.length === 0
this._singleSetup = null
this._video = null
if (this._track && disableTrack) {
this._track.stop()
}
this._track = null
}
}
getFrame ({
dimensions = this._dimensions,
mirror = this.mirror,
format = 'image-data',
cacheTimeout = this._frameCacheTimeout
}) {
if (!this.videoReady) {
return null
}
const [width, height] = dimensions
const workspace = this._getWorkspace({
dimensions,
mirror: Boolean(mirror)
})
const { videoWidth, videoHeight } = this._video
const { canvas, context, lastUpdate, cacheData } = workspace
const now = Date.now()
if (lastUpdate + cacheTimeout < now) {
if (mirror) {
context.scale(-1, 1)
context.translate(width * -1, 0)
}
context.drawImage(
this._video,
0,
0,
videoWidth,
videoHeight,
0,
0,
width,
height
)
context.setTransform(1, 0, 0, 1, 0, 0)
workspace.lastUpdate = now
}
if (!cacheData[format]) {
cacheData[format] = { lastUpdate: 0 }
}
const formatCache = cacheData[format]
if (formatCache.lastUpdate + cacheTimeout < now) {
if (format === 'image-data') {
formatCache.lastData = context.getImageData(0, 0, width, height)
} else if (format === 'canvas') {
formatCache.lastUpdate = Infinity
formatCache.lastData = canvas
} else {
console.error(`video io error - unimplemented format ${format}`)
formatCache.lastUpdate = Infinity
formatCache.lastData = null
}
formatCache.lastUpdate = Math.max(
workspace.lastUpdate,
formatCache.lastUpdate
)
}
return formatCache.lastData
}
onError (error) {
console.error('Unhandled video io device error', error)
}
_setupVideo () {
if (this._singleSetup) {
return this._singleSetup
}
if (requestStack.length === 0) {
this._singleSetup = navigator.mediaDevices.getUserMedia({
audio: false,
video: {
width: { min: width, ideal: (480 * width) / height },
height: { min: height, ideal: 480 }
}
})
requestStack.push(streamPromise)
} else if (requestStack.length > 0) {
this._singleSetup = requestStack[0]
requestStack.push(true)
}
this._singleSetup
.then(stream => {
this._video = document.createElement('video')
try {
this._video.srcObject = stream
} catch (_error) {
this._video.src = window.URL.createObjectURL(stream)
}
this._video.play()
this._track = stream.getTracks()[0]
return this
})
.catch(error => {
this._singleSetup = null
this.onError(error)
})
return this._singleSetup
}
get videoReady () {
if (!this.enabled || !this._video || !this._track) {
return false
}
const { videoWidth, videoHeight } = this._video
return (
typeof videoWidth === 'number' &&
typeof videoHeight === 'number' &&
videoWidth > 0 &&
videoHeight > 0
)
}
_getWorkspace ({ dimensions, mirror }) {
let workspace = this._workspace.find(
space =>
space.dimensions.join('-') === dimensions.join('-') &&
space.mirror === mirror
)
if (!workspace) {
workspace = {
dimensions,
mirror,
canvas: document.createElement('canvas'),
lastUpdate: 0,
cacheData: {}
}
workspace.canvas.width = dimensions[0]
workspace.canvas.height = dimensions[1]
workspace.context = workspace.canvas.getContext('2d')
this._workspace.push(workspace)
}
return workspace
}
}
const fullscreenBtn = document.getElementById('fullscreen-btn')
const exitFullscreen =
document.exitFullscreen ||
document.msExitFullscreen ||
document.mozCancelFullScreen ||
document.webkitExitFullscreen
const requestFullscreen =
document.body.requestFullscreen ||
document.body.msRequestFullscreen ||
document.body.mozRequestFullScreen ||
document.body.webkitRequestFullscreen
function isFullscreen () {
return (
document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement
)
}
function toggleFullscreen () {
if (isFullscreen()) {
exitFullscreen.call(document)
} else {
requestFullscreen.call(document.body)
}
}
fullscreenBtn.addEventListener('click', () => {
fullscreenBtn.blur()
toggleFullscreen()
})
function handleFullscreenChange () {
if (isFullscreen()) {
document.body.classList.add('fullscreen')
} else {
document.body.classList.remove('fullscreen')
}
}
document.addEventListener('fullscreenchange', handleFullscreenChange)
document.addEventListener('mozfullscreenchange', handleFullscreenChange)
document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
document.addEventListener('msfullscreenchange', handleFullscreenChange)
window.init = async ({ width, height, ...options }) => {
window.vm = new window.NotVirtualMachine(width, height)
vm.setCompatibilityMode(options.fps)
vm.setTurboMode(options.turbo)
vm.requireLimits(options.limits, { fencing: options.fencing })
const storage = new ScratchStorage()
const AssetType = storage.AssetType
if (options.assets.project) {
storage.addWebStore([AssetType.Project], () => options.assets.project)
storage.addWebStore(
[AssetType.ImageVector, AssetType.ImageBitmap, AssetType.Sound],
({ assetId, dataFormat }) => options.assets[`${assetId}.${dataFormat}`]
)
}
const progress = document.getElementById('loading-progress')
if (options.loadingProgress) {
const _load = storage.webHelper.load
let total = 0,
complete = 0
storage.webHelper.load = function (...args) {
const result = _load.call(this, ...args)
total += 1
const percentage = (complete / total) * 100
progress.dataset.progress = percentage.toFixed(2) + '%'
progress.style.setProperty('--progress', percentage + '%')
result.then(() => {
complete += 1
const percentage = (complete / total) * 100
progress.dataset.progress = percentage.toFixed(2) + '%'
progress.style.setProperty('--progress', percentage + '%')
})
return result
}
}
vm.attachStorage(storage)
function resize () {
const rect = canvas.getBoundingClientRect()
renderer.resize(rect.width, rect.height)
if (options.stretchStage) {
monitorWrapper.style.transform = `scaleX(${rect.width /
width}) scaleY(${rect.height / height})`
} else {
monitorWrapper.style.transform = `scale(${rect.height / height})`
}
}
const monitorWrapper = document.getElementById('monitors')
const canvas = document.getElementById('stage')
const renderer = new window.ScratchRender(
canvas,
-width / 2,
width / 2,
-height / 2,
height / 2
)
resize()
vm.attachRenderer(renderer)
vm.attachAudioEngine(new window.AudioEngine())
vm.attachV2BitmapAdapter(
new ScratchSVGRenderer.BitmapAdapter(null, null, width, height)
)
vm.setVideoProvider(new VideoProvider(width, height))
vm.start()
if (options.extensionCount > 0) {
const OldWorker = window.Worker
window.Worker = class extends OldWorker {
// deno-lint-ignore constructor-super
constructor (...args) {
if (args[0].endsWith('extension-worker.js')) {
if (options.extensionWorker.url) {
super(options.extensionWorker.url, ...args.slice(1))
} else {
super(
URL.createObjectURL(
new Blob([options.extensionWorker.script], {
type: 'text/javascript'
})
),
...args.slice(1)
)
}
} else {
super(...args)
}
}
}
}
/* https://github.com/LLK/scratch-gui/blob/develop/src/containers/stage.jsx#L176-L300 */
const getEventXY = e => {
if (e.touches && e.touches[0]) {
return { x: e.touches[0].clientX, y: e.touches[0].clientY }
} else if (e.changedTouches && e.changedTouches[0]) {
return { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY }
}
return { x: e.clientX, y: e.clientY }
}
let mouseDown = false
let mouseDownPosition = null
let mouseDownTimeoutId = null
let isDragging = false
let dragId = null
let dragOffset = null
function cancelMouseDownTimeout () {
if (mouseDownTimeoutId !== null) {
clearTimeout(mouseDownTimeoutId)
}
mouseDownTimeoutId = null
}
// https://github.com/LLK/scratch-gui/blob/develop/src/containers/stage.jsx#L337-L366
function handleStartDrag () {
if (dragId || !mouseDownPosition) return
const drawableId = renderer.pick(mouseDownPosition.x, mouseDownPosition.y)
if (drawableId === null) return
const targetId = vm.getTargetIdForDrawableId(drawableId)
if (targetId === null) return
const target = vm.runtime.getTargetById(targetId)
if (!target || !target.draggable) return
target.goToFront()
const drawableData = renderer.extractDrawable(
drawableId,
mouseDownPosition.x,
mouseDownPosition.y
)
vm.startDrag(targetId)
isDragging = true
dragId = targetId
dragOffset = drawableData.scratchOffset
}
const accumulative = { x: 0, y: 0 }
function postIfPointerLocked (e, isDown) {
if (
document.pointerLockElement === canvas ||
document.mozPointerLockElement === canvas
) {
accumulative.x += e.movementX
accumulative.y += e.movementY
vm.postIOData('mouse', {
isDown,
x: accumulative.x + width / 2,
y: accumulative.y + height / 2,
canvasWidth: width,
canvasHeight: height
})
return true
} else {
return false
}
}
function postMouse (event, isDown) {
const { x, y } = getEventXY(event)
const rect = canvas.getBoundingClientRect()
const mousePosition = { x: x - rect.left, y: y - rect.top }
vm.postIOData('mouse', {
isDown,
...mousePosition,
canvasWidth: rect.width,
canvasHeight: rect.height
})
return { mousePosition, rect }
}
function handleMouseMove (event) {
if (postIfPointerLocked(event)) return
const { mousePosition, rect } = postMouse(event)
if (mouseDown && !isDragging) {
const distanceFromMouseDown = Math.hypot(
mousePosition.x - mouseDownPosition.x,
mousePosition.y - mouseDownPosition.y
)
if (distanceFromMouseDown > 3) {
cancelMouseDownTimeout()
handleStartDrag()
}
}
if (mouseDown && isDragging) {
const nativeSize = renderer.getNativeSize()
vm.postSpriteInfo({
x:
(nativeSize[0] / rect.width) * (mousePosition.x - rect.width / 2) +
dragOffset[0],
y: -(
(nativeSize[1] / rect.height) * (mousePosition.y - rect.height / 2) +
dragOffset[1]
),
force: true
})
}
}
function handleMouseDown (event) {
mouseDown = true
vm.postIOData('keyboard', {
key: 'Mouse' + event.which,
isDown: true
})
if (postIfPointerLocked(event, true)) return
mouseDownPosition = postMouse(event, true).mousePosition
mouseDownTimeoutId = setTimeout(handleStartDrag, 400)
event.preventDefault()
if (!document.body.classList.contains('asking')) {
window.focus()
}
}
function handleMouseUp (event) {
cancelMouseDownTimeout()
mouseDown = false
mouseDownPosition = null
if (isDragging) {
vm.stopDrag(dragId)
isDragging = false
dragOffset = null
dragId = null
}
vm.postIOData('keyboard', {
key: 'Mouse' + event.which,
isDown: false
})
if (postIfPointerLocked(event, false)) return
postMouse(event, false)
}
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('touchmove', handleMouseMove)
document.addEventListener('touchend', handleMouseUp, { passive: false })
canvas.addEventListener('wheel', event => {
vm.postIOData('mouseWheel', event)
event.preventDefault()
})
window.addEventListener('resize', resize)
canvas.addEventListener('contextmenu', event => {
event.preventDefault()
})
if (options.pointerLock) {
canvas.requestPointerLock =
canvas.requestPointerLock || canvas.mozRequestPointerLock
canvas.addEventListener('click', () => {
canvas.requestPointerLock()
})
}
/**
* Maps e.key to e.code. For example, Shift -> ShiftRight. This is because the
* keyup event doesn't fire when you let go of one shift if the other shift
* key is still held down.
*/
const keyToCode = new Map()
function postKey (event, isDown) {
const key = !event.key || event.key === 'Dead' ? event.keyCode : event.key
vm.postIOData('keyboard', {
key: key,
isDown
})
vm.postIOData('keyboard', {
key: 'code_' + event.code,
isDown
})
}
document.addEventListener('keydown', event => {
if (event.target !== document && event.target !== document.body) return
const prevCode = keyToCode.get(event.key)
if (prevCode) {
if (prevCode !== event.code) {
vm.postIOData('keyboard', {
key: 'code_' + prevCode,
isDown: false
})
}
}
postKey(event, true)
keyToCode.set(event.key, event.code)
if (event.keyCode === 32 || (event.keyCode >= 37 && event.keyCode <= 40)) {
event.preventDefault()
}
if (
event.key === 'f' &&
(event.ctrlKey || event.metaKey) &&
!event.shiftKey &&
!event.altKey
) {
toggleFullscreen()
event.preventDefault()
}
})
document.addEventListener('keyup', e => {
postKey(e, false)
keyToCode.delete(e.key)
if (e.target !== document && e.target !== document.body) {
e.preventDefault()
}
})
vm.postIOData('keyboard', {
key: 'HTMLifier',
isDown: true
})
const question = document.getElementById('question')
const askBox = document.getElementById('answer')
vm.runtime.addListener('QUESTION', questionData => {
// null means the question was interrupted by stop script block
if (questionData === null) {
document.body.classList.remove('asking')
} else {
document.body.classList.add('asking')
question.textContent = questionData
askBox.value = ''
askBox.focus()
}
})
askBox.addEventListener('keydown', event => {
if (event.key === 'Enter') {
// The asking class must be removed first because the VM may start the
// next question immediately inside the .emit call
document.body.classList.remove('asking')
vm.runtime.emit('ANSWER', askBox.value)
}
})
const getVariable = (targetId, variableId) => {
const target = targetId
? vm.runtime.getTargetById(targetId)
: vm.runtime.getTargetForStage()
return target.variables[variableId]
}
const monitorStates = {}
vm.runtime.addListener('MONITORS_UPDATE', monitors => {
monitors.forEach((record, id) => {
const {
value,
visible,
mode,
x,
y,
width,
height,
params,
opcode,
spriteName,
sliderMin,
sliderMax,
isDiscrete,
targetId
} = record
if (!monitorStates[id]) {
const label = document.createElement('span')
label.className = 'monitor-label'
const name = params.VARIABLE || params.LIST || opcode
label.textContent = spriteName ? `${spriteName}: ${name}` : name
const value = document.createElement('span')
value.className = 'monitor-value'
const monitor = document.createElement('div')
monitor.className = 'monitor ' + mode
monitor.style.left = x + 'px'
monitor.style.top = y + 'px'
monitor.append(label, value)
monitorStates[id] = { monitor, valueElem: value, wasVisible: true }
if (mode === 'slider') {
const slider = document.createElement('input')
slider.type = 'range'
slider.min = sliderMin
slider.max = sliderMax
slider.step = isDiscrete ? 1 : 0.01
// Prevent tab focus, per #54, but it deviates from Scratch
slider.tabIndex = -1
slider.addEventListener('input', () => {
getVariable(targetId, id).value = slider.value
})
slider.addEventListener('change', () => {
getVariable(targetId, id).value = slider.value
})
monitorStates[id].slider = slider
monitor.append(slider)
} else if (mode === 'list') {
// If the list has never been resized, the width/height will be 0.
// Weird!
monitor.style.width = (width || 100) + 'px'
monitor.style.height = (height || 200) + 'px'
monitorStates[id].rowElems = []
}
monitorWrapper.append(monitor)
}
const {
monitor,
valueElem,
wasVisible,
lastValue = [],
slider,
rowElems
} = monitorStates[id]
if (visible) {
if (!wasVisible) {
monitor.style.display = null
}
const differed = Array.isArray(value)
? JSON.stringify(lastValue) !== JSON.stringify(value)
: lastValue !== value
if (differed) {
if (Array.isArray(value)) {
if (lastValue.length !== rowElems.length) {
console.error(
"List monitor rowElems and lastValue lengths don't match."
)
}
value.forEach((val, i) => {
if (i >= lastValue.length) {
// Could also set width to (lastValue.length + '').length + 'ch'
const index = document.createElement('div')
index.className = 'index'
index.textContent = i + 1
const value = document.createElement('div')
value.className = 'row-value'
const row = document.createElement('div')
row.className = 'row'
row.append(index, value)
valueElem.append(row)
rowElems[i] = value
}
if (lastValue[i] !== val) {
rowElems[i].textContent = val
}
})
if (value.length < lastValue.length) {
for (const toRemove of rowElems.splice(
value.length,
lastValue.length - value.length
)) {
toRemove.parentNode.remove()
}
}
} else {
// The HTMLifier used to use Number(value.toFixed(6)) but I don't
// think Scratch does that for monitors
valueElem.textContent = value
if (slider) {
slider.value = value
}
}
}
} else if (wasVisible) {
monitor.style.display = 'none'
}
monitorStates[id].wasVisible = visible
// `value` is a live array
monitorStates[id].lastValue = Array.isArray(value) ? [...value] : value
})
})
vm.postIOData('userData', { username: options.username })
for (let i = 0; i < options.extensionCount; i++) {
await vm.extensionManager.loadExtensionURL(String(i))
}
await vm.loadProject(
options.assets.file
? await fetch(options.assets.file).then(r => r.arrayBuffer())
: typeof options.assets.project === 'string'
? await storage.load(storage.AssetType.Project).then(asset => asset.data)
: // project.json was included as parsed JSON
JSON.stringify(options.assets.project)
)
const cloudProvider = new CloudProvider(options)
vm.setCloudProvider(cloudProvider)
if (options.cloud.specialBehaviours || !options.cloud.serverUrl) {
const stageVariables = vm.runtime.getTargetForStage().variables
for (const { name, isCloud } of Object.values(stageVariables)) {
if (isCloud) {
if (
options.cloud.specialBehaviours &&
options.cloud.serverUrl &&
!name.startsWith(CLOUD_PREFIX + 'local storage')
) {
continue
}
const value = localStorage.getItem('[s3] ' + name)
if (value !== null) {
vm.postIOData('cloud', { varUpdate: { name, value } })
}
}
}
}
if (options.cloud.specialBehaviours) {
cloudProvider.handleUrlChange()
}
progress.remove()
const loadingImage = document.getElementById('loading-image')
if (loadingImage) {
loadingImage.remove()
}
document.body.classList.remove('loading')
const greenFlag = document.getElementById('start-btn')
const stopSign = document.getElementById('stop-btn')
greenFlag.addEventListener('click', () => {
greenFlag.blur()
vm.greenFlag()
})
stopSign.addEventListener('click', () => {
stopSign.blur()
vm.stopAll()
})
vm.on('PROJECT_RUN_START', () => {
document.body.classList.add('running')
stopSign.disabled = false
})
vm.on('PROJECT_RUN_STOP', () => {
document.body.classList.remove('running')
stopSign.disabled = true
})
if (options.autoStart) {
vm.greenFlag()
}
document
.getElementById('download-btn')
.addEventListener('click', async () => {
download(await vm.saveProjectSb3(), document.title + '.sb3')
})
const addSpriteInput = document.getElementById('add-sprite-file')
addSpriteInput.addEventListener('change', async () => {
addSpriteInput.disabled = true
for (const file of addSpriteInput.files) {
// 1. Convert the File to an arrayBuffer. I care less about browser
// support, so I can use async/await + .arrayBuffer
// https://github.com/LLK/scratch-gui/blob/develop/src/lib/file-uploader.js#L25
const sprite = new Uint8Array(await file.arrayBuffer())
// 2. Convert a costume to a sprite (skipping for now)
// https://github.com/LLK/scratch-gui/blob/develop/src/lib/file-uploader.js#L208
// 3. Add to VM
await vm.addSprite(sprite)
}
addSpriteInput.disabled = false
addSpriteInput.value = null
})
canvas.addEventListener('mousedown', handleMouseDown)
canvas.addEventListener('touchstart', handleMouseDown, { passive: false })
}
const errorsTextarea = document.getElementById('errors')
function handleHashChange () {
// #show-errors-<Han sheep>
if (window.location.hash === '#show-errors-%E7%BE%8A') {
if (!window.onNewError) {
window.onNewError = () => {
errorsTextarea.value = `${
window.errors.length
} error(s)\n${window.errors.join('\n')}`
}
window.onNewError()
}
errorsTextarea.style.display = 'block'
} else if (window.onNewError) {
window.onNewError = null
errorsTextarea.style.display = 'none'
}
}
window.addEventListener('hashchange', handleHashChange)
handleHashChange()
// Not used by the template, but might be convenient for un-HTMLifying if I
// remember this function exists
window.download = (blob, name = 'download') => {
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = name
document.body.append(link)
link.click()
link.remove()
URL.revokeObjectURL(url)
}
</script> <script>
const GENERATED = 1648316486479
const initOptions = {
"width": 480,
"height": 360,
"stretchStage": true,
"fps": 30,
"turbo": false,
"limits": true,
"fencing": true,
"pointerLock": false,
"autoStart": true,
"username": "user",
"loadingProgress": true,
"cloud": {
"serverUrl": null,
"specialBehaviours": false,
"projectId": "276660763"
},
"extensionWorker": {
"url": "https://sheeptester.github.io/scratch-vm/16-9/extension-worker.js"
},
"extensionCount": 0,
"assets": {
"project": "project/project.json",
"f5e250886e3bafbbd9bc2398a5e321c5.png": "project/f5e250886e3bafbbd9bc2398a5e321c5.png",
"e33dc6c9e1faa45c1497fa2cd6fbf42a.svg": "project/e33dc6c9e1faa45c1497fa2cd6fbf42a.svg",
"6ef23f9f3f82cdf24fe42b8a0f06f8f5.wav": "project/6ef23f9f3f82cdf24fe42b8a0f06f8f5.wav",
"a06eec63f65cfad8dc4ecaa8b13f8c21.wav": "project/a06eec63f65cfad8dc4ecaa8b13f8c21.wav",
"d08d9c60752bcf1aaeeb5edf28dced3a.png": "project/d08d9c60752bcf1aaeeb5edf28dced3a.png",
"0517e371e0e249ba7c0c395fbc2819ae.png": "project/0517e371e0e249ba7c0c395fbc2819ae.png",
"83a9787d4cb6f3b7632b4ddfebf74367.wav": "project/83a9787d4cb6f3b7632b4ddfebf74367.wav",
"d7dee641ecbcbaa39c61ebdcc9ec9323.wav": "project/d7dee641ecbcbaa39c61ebdcc9ec9323.wav",
"f5fe1eb3dfc9fb3383439f9bb5e19811.png": "project/f5fe1eb3dfc9fb3383439f9bb5e19811.png",
"4b8d10efe3f5d5f15b926581e8d5b9fb.png": "project/4b8d10efe3f5d5f15b926581e8d5b9fb.png",
"09b3ab611d149d7ebe271af9f87a15af.png": "project/09b3ab611d149d7ebe271af9f87a15af.png",
"9f1c6b3a0ecc121e9d5e087421887e24.png": "project/9f1c6b3a0ecc121e9d5e087421887e24.png",
"63c3c27ce3217799cd3c8efc7ec067ac.png": "project/63c3c27ce3217799cd3c8efc7ec067ac.png",
"979d2ee3355add58fb7a631655400540.wav": "project/979d2ee3355add58fb7a631655400540.wav",
"e5ea1e4a9edd8ecff5ade9f61446085a.png": "project/e5ea1e4a9edd8ecff5ade9f61446085a.png",
"30ea40cb2d58264c33a36ff55457f00e.png": "project/30ea40cb2d58264c33a36ff55457f00e.png",
"47c5d6db2506468945f08b8f9a241b1c.png": "project/47c5d6db2506468945f08b8f9a241b1c.png",
"236d6a738f210c8ba3a7c264cea39c9b.png": "project/236d6a738f210c8ba3a7c264cea39c9b.png",
"d96577b806b7a78b1b0eaa5c0487189b.png": "project/d96577b806b7a78b1b0eaa5c0487189b.png",
"650ecca97291fb2f4d17d7f0a5a6359f.wav": "project/650ecca97291fb2f4d17d7f0a5a6359f.wav",
"3be3cd17e46d62366a11d8c37e0d1791.wav": "project/3be3cd17e46d62366a11d8c37e0d1791.wav",
"25a07d4abd8b7f88248b4a479f0c444a.png": "project/25a07d4abd8b7f88248b4a479f0c444a.png",
"7754c4c37324ced6ad22c06ad4b12ecd.png": "project/7754c4c37324ced6ad22c06ad4b12ecd.png",
"b88aa92412f0866007c01cea07d721ee.png": "project/b88aa92412f0866007c01cea07d721ee.png",
"3c86af368df7b90760840b263e24f6b9.png": "project/3c86af368df7b90760840b263e24f6b9.png",
"aafb0d7a08a7ffdb50872e8f7de2162d.png": "project/aafb0d7a08a7ffdb50872e8f7de2162d.png",
"df3174c3c66d033cc142f6d2b08ef6ac.png": "project/df3174c3c66d033cc142f6d2b08ef6ac.png",
"8ca0fd1b5775952e4c073927e61213eb.png": "project/8ca0fd1b5775952e4c073927e61213eb.png",
"4d9f0ed9ef92cbd5f797ff7bc5067752.png": "project/4d9f0ed9ef92cbd5f797ff7bc5067752.png",
"020e83afaeec8470236ca94d749e1995.png": "project/020e83afaeec8470236ca94d749e1995.png",
"fea1d238e9768e6b738570f720f05de6.png": "project/fea1d238e9768e6b738570f720f05de6.png",
"c38e5940b17a842476236cc0d59cf755.png": "project/c38e5940b17a842476236cc0d59cf755.png",
"d36f6603ec293d2c2198d3ea05109fe0.png": "project/d36f6603ec293d2c2198d3ea05109fe0.png",
"e53d2cba66d52070d4116e70bee2892c.wav": "project/e53d2cba66d52070d4116e70bee2892c.wav",
"62a359cd7db693d66b534c315231343c.wav": "project/62a359cd7db693d66b534c315231343c.wav",
"42853858903eb82876a96c45cd9b2d55.png": "project/42853858903eb82876a96c45cd9b2d55.png",
"80ca74a6e3a58dbf6ccac4751af0faac.png": "project/80ca74a6e3a58dbf6ccac4751af0faac.png",
"31e3ea26f3c7f333479eabdfd9b76164.svg": "project/31e3ea26f3c7f333479eabdfd9b76164.svg",
"52549ce42eeebc04330b3c46c8b3127a.svg": "project/52549ce42eeebc04330b3c46c8b3127a.svg",
"ad8b49444d655ad877c19d113019891d.svg": "project/ad8b49444d655ad877c19d113019891d.svg",
"335f13c6935f6d8d0c527d89751a5451.svg": "project/335f13c6935f6d8d0c527d89751a5451.svg",
"33cd6061f734e5b2afe54ded0a4021b0.svg": "project/33cd6061f734e5b2afe54ded0a4021b0.svg",
"3b446d05f58f7526c5e8223ff977d792.png": "project/3b446d05f58f7526c5e8223ff977d792.png",
"3d661775a03c9a5d61055be1bf0e5064.png": "project/3d661775a03c9a5d61055be1bf0e5064.png",
"1fddde29233928ac401b5f79ba09b828.png": "project/1fddde29233928ac401b5f79ba09b828.png",
"99f98c3fcaab347fc50c4d5156772a2d.png": "project/99f98c3fcaab347fc50c4d5156772a2d.png",
"43b5e21fd75ed29f1e03163e01bfcb7f.png": "project/43b5e21fd75ed29f1e03163e01bfcb7f.png",
"9cf82e47f048a8a032dc657e57abb11c.png": "project/9cf82e47f048a8a032dc657e57abb11c.png",
"df71c104bce783306ac54e7e487c7cf0.png": "project/df71c104bce783306ac54e7e487c7cf0.png",
"a82700168f4a0e8a68f9215eb417f603.png": "project/a82700168f4a0e8a68f9215eb417f603.png",
"4e1226d3f1eb9f22cba3a919ada4eb5e.png": "project/4e1226d3f1eb9f22cba3a919ada4eb5e.png",
"b49d8304e52915c34a8179ff2018b0ce.png": "project/b49d8304e52915c34a8179ff2018b0ce.png",
"17d69eea771b1d998e0e6493864ccee4.png": "project/17d69eea771b1d998e0e6493864ccee4.png",
"ab2fb08de243621fa62aabccee8b15cc.png": "project/ab2fb08de243621fa62aabccee8b15cc.png",
"a58032d5bd25c169ebf1242256c95e85.png": "project/a58032d5bd25c169ebf1242256c95e85.png",
"bd81fe1b963e6b8b40ac6e3f49e54245.png": "project/bd81fe1b963e6b8b40ac6e3f49e54245.png",
"25c19269e3747c8796154263f5d6bc05.png": "project/25c19269e3747c8796154263f5d6bc05.png",
"1f0ac5c68d382aa5182bfc58cd68b885.png": "project/1f0ac5c68d382aa5182bfc58cd68b885.png",
"d6c58e6eae85654870652e54fb34ed81.png": "project/d6c58e6eae85654870652e54fb34ed81.png",
"354344933b3b625b3c08164b35599c73.png": "project/354344933b3b625b3c08164b35599c73.png",
"b885b072e7d35eaf0c89b3616952894b.wav": "project/b885b072e7d35eaf0c89b3616952894b.wav",
"d2e43956b9f5de2c8db654a39c7dfb1e.png": "project/d2e43956b9f5de2c8db654a39c7dfb1e.png",
"904a9fc8d30239bbe7b149f95d7dde57.png": "project/904a9fc8d30239bbe7b149f95d7dde57.png",
"7a1fc2e4eaeb0285a761760e7105ae43.png": "project/7a1fc2e4eaeb0285a761760e7105ae43.png",
"aa7897d0631b4c99d5c8b3b21b7e4bce.png": "project/aa7897d0631b4c99d5c8b3b21b7e4bce.png",
"0d4081650d2b5cae2e535c35e7b71449.png": "project/0d4081650d2b5cae2e535c35e7b71449.png",
"997af6255c42f68fbb1f0048c88a351f.png": "project/997af6255c42f68fbb1f0048c88a351f.png",
"7816f366581c52106b20c570f6d21c52.png": "project/7816f366581c52106b20c570f6d21c52.png",
"8cf7dd32d56126ce9773a04798a8e56a.png": "project/8cf7dd32d56126ce9773a04798a8e56a.png",
"0f371f5806e780e7f35e3ba293152dd9.png": "project/0f371f5806e780e7f35e3ba293152dd9.png",
"9c94e735a32b068993b1529ce06b9d52.png": "project/9c94e735a32b068993b1529ce06b9d52.png",
"9b3944a2de2c7fe972a961934031497f.png": "project/9b3944a2de2c7fe972a961934031497f.png",
"bbb05d55a5a12b7e4e7519c242de083b.png": "project/bbb05d55a5a12b7e4e7519c242de083b.png",
"3079c5be34e3a0c73e02a1862063f95d.png": "project/3079c5be34e3a0c73e02a1862063f95d.png",
"369cd75e67486cfe706e9c9a08056438.png": "project/369cd75e67486cfe706e9c9a08056438.png",
"eaeda182d0ac1302fc18b599d51e90fd.png": "project/eaeda182d0ac1302fc18b599d51e90fd.png",
"c57a87e4681c4c5c5ac2876299769710.png": "project/c57a87e4681c4c5c5ac2876299769710.png",
"a03b9352751cf7203708976be3b36bb1.png": "project/a03b9352751cf7203708976be3b36bb1.png",
"901e840cbc160157d8781acf0156926a.png": "project/901e840cbc160157d8781acf0156926a.png",
"d0f7cc9778c2ae1e018f4235f4ff36da.png": "project/d0f7cc9778c2ae1e018f4235f4ff36da.png",
"d2e125ae309344174ef4c891ee88e5c6.png": "project/d2e125ae309344174ef4c891ee88e5c6.png",
"99eefe09f8a41fa5f8517a5cc8cbb8c1.png": "project/99eefe09f8a41fa5f8517a5cc8cbb8c1.png",
"a1c11bdb35f2fe1f16d4828abba0776e.png": "project/a1c11bdb35f2fe1f16d4828abba0776e.png",
"72a8ed2034aa30ff869afb242430414c.png": "project/72a8ed2034aa30ff869afb242430414c.png",
"b90667e1e775cba02ef1a435573dc543.png": "project/b90667e1e775cba02ef1a435573dc543.png",
"9712315c8c9a3d07b81421d7d2f45ca5.png": "project/9712315c8c9a3d07b81421d7d2f45ca5.png",
"e4c1caef4943dcca6ddb4904720b2a36.png": "project/e4c1caef4943dcca6ddb4904720b2a36.png",
"8e9064811bcc21070d9a3f555a03488f.png": "project/8e9064811bcc21070d9a3f555a03488f.png",
"425d51ab9b6d9929f236905fd7a8f167.png": "project/425d51ab9b6d9929f236905fd7a8f167.png",
"0df81dfc4bb38e2831107e47f44bbdd5.png": "project/0df81dfc4bb38e2831107e47f44bbdd5.png",
"829dbf602064cd34276aa130beec465e.png": "project/829dbf602064cd34276aa130beec465e.png",
"d225fbad390a4461f09c18d80542afe0.wav": "project/d225fbad390a4461f09c18d80542afe0.wav",
"2bdd4ebf5970bd3bd9c699c75537000b.wav": "project/2bdd4ebf5970bd3bd9c699c75537000b.wav",
"fc1ad549d61f730442277569ccf6fdb9.png": "project/fc1ad549d61f730442277569ccf6fdb9.png",
"3e93c65c6b7ff282ed50967960148570.png": "project/3e93c65c6b7ff282ed50967960148570.png",
"5b3b95113bc05a450a9fcb31692cfaef.png": "project/5b3b95113bc05a450a9fcb31692cfaef.png",
"29c5de45b0f5ea7b2e09cc167e133bc7.png": "project/29c5de45b0f5ea7b2e09cc167e133bc7.png",
"5c99f757615745b8ac8ea7bc913438f6.png": "project/5c99f757615745b8ac8ea7bc913438f6.png",
"41c520609b76b8ba189a0f58d5676307.png": "project/41c520609b76b8ba189a0f58d5676307.png",
"19abefc665ae71efbfd1d67179bb1e1a.png": "project/19abefc665ae71efbfd1d67179bb1e1a.png",
"86179709cb6182b2d55e762311f03820.png": "project/86179709cb6182b2d55e762311f03820.png",
"54e321257880148f317ec6b7ca3f2e1a.png": "project/54e321257880148f317ec6b7ca3f2e1a.png",
"a880c2c61911e2592e6659ea1b952dee.png": "project/a880c2c61911e2592e6659ea1b952dee.png",
"ed7d252484f7455b8c4c86dcd35b84a3.png": "project/ed7d252484f7455b8c4c86dcd35b84a3.png",
"6b49b31201e3f799fe6cb48ad9344b28.wav": "project/6b49b31201e3f799fe6cb48ad9344b28.wav",
"97cce5137718d7a3db9309420b38b800.png": "project/97cce5137718d7a3db9309420b38b800.png",
"587b36a9a9ccdafb98b07aef1a7b60b3.png": "project/587b36a9a9ccdafb98b07aef1a7b60b3.png",
"a530f8186a0a0cc039e81da5a9a6887b.png": "project/a530f8186a0a0cc039e81da5a9a6887b.png",
"4ee79f70b1c405c99e3c4916c69cfece.png": "project/4ee79f70b1c405c99e3c4916c69cfece.png",
"4cff6f5bec774667d8eaf58744438c63.png": "project/4cff6f5bec774667d8eaf58744438c63.png",
"b51fbc7879e08440b0d010fb39896a39.wav": "project/b51fbc7879e08440b0d010fb39896a39.wav",
"284bc5478adf8a7649197863edc549a1.png": "project/284bc5478adf8a7649197863edc549a1.png",
"9e4cbcbc50c78f594202d94252d13c15.png": "project/9e4cbcbc50c78f594202d94252d13c15.png",
"425464cd32b2f390f22427e55254e9e2.png": "project/425464cd32b2f390f22427e55254e9e2.png",
"541aa5d91cc19e82b8c598c722b54e93.png": "project/541aa5d91cc19e82b8c598c722b54e93.png",
"1ce78ebe176c07598dd1725d02d87d70.png": "project/1ce78ebe176c07598dd1725d02d87d70.png",
"c55eb4c0c19a7ae9dc34488e61186b41.png": "project/c55eb4c0c19a7ae9dc34488e61186b41.png",
"6ca50796b9c0cb9b120b80d0d7aa3763.png": "project/6ca50796b9c0cb9b120b80d0d7aa3763.png",
"af6687ca0976b8f91588d962a592e26c.png": "project/af6687ca0976b8f91588d962a592e26c.png",
"4c969d4bf11b3857d9d562322049cbb4.png": "project/4c969d4bf11b3857d9d562322049cbb4.png",
"0c317edbfc3a4be6c3e55fdafb153835.png": "project/0c317edbfc3a4be6c3e55fdafb153835.png",
"63f3e8c4fcb8f4247b4e1ea1b11e9cd3.png": "project/63f3e8c4fcb8f4247b4e1ea1b11e9cd3.png",
"152275380a3598cf66755d35b0b6b679.png": "project/152275380a3598cf66755d35b0b6b679.png",
"ff0401610c1d1e4f11c3f6863c1c4fb5.png": "project/ff0401610c1d1e4f11c3f6863c1c4fb5.png",
"bf64a1461a3f4b19c59f6ac17b67f933.png": "project/bf64a1461a3f4b19c59f6ac17b67f933.png",
"8d1beb9f347f86067cdb3f01d5463b24.png": "project/8d1beb9f347f86067cdb3f01d5463b24.png",
"679b8b067981ec813d97131d951ce0b3.png": "project/679b8b067981ec813d97131d951ce0b3.png",
"5d1f595cb7aa440d1f69d041e0ac78cd.png": "project/5d1f595cb7aa440d1f69d041e0ac78cd.png",
"9ffa59b463c610fd0e74fd72f6a155ef.wav": "project/9ffa59b463c610fd0e74fd72f6a155ef.wav",
"da1355e403da1d209df7ea8030c4fbed.wav": "project/da1355e403da1d209df7ea8030c4fbed.wav",
"73c55e9348832d04a01aefd46aa69aab.png": "project/73c55e9348832d04a01aefd46aa69aab.png",
"ab8c1338bf343c42a8476d7238555107.png": "project/ab8c1338bf343c42a8476d7238555107.png",
"97d8578d857b38f3e0dd101dba7a737b.png": "project/97d8578d857b38f3e0dd101dba7a737b.png",
"a9aa091549c9be51720bd349c71db47e.png": "project/a9aa091549c9be51720bd349c71db47e.png",
"5dfa65f098f00e735a283dd3730642e0.png": "project/5dfa65f098f00e735a283dd3730642e0.png",
"04c1bce27d1faafba2545eef7708dbc7.png": "project/04c1bce27d1faafba2545eef7708dbc7.png",
"76cae91c1f19c5804a79a7a7ee2ae865.png": "project/76cae91c1f19c5804a79a7a7ee2ae865.png",
"052b296fa83549f10e8032a462d192f9.png": "project/052b296fa83549f10e8032a462d192f9.png",
"028c9cafb484a2e15bbb47026ca0431b.png": "project/028c9cafb484a2e15bbb47026ca0431b.png",
"370e43c7bacac96f6e4649616d1a585a.png": "project/370e43c7bacac96f6e4649616d1a585a.png",
"ee27805a18b9218387bd5c09787a3964.png": "project/ee27805a18b9218387bd5c09787a3964.png",
"eaf8e4dbc14d9a9d37c189e2c73e1120.png": "project/eaf8e4dbc14d9a9d37c189e2c73e1120.png",
"d0391a48c018bcef0f0bcc02ea7cca4b.png": "project/d0391a48c018bcef0f0bcc02ea7cca4b.png",
"ebef888a8b9bd86b201e696ccbd2b2fe.png": "project/ebef888a8b9bd86b201e696ccbd2b2fe.png",
"c264d16f0c8de75fda7fd25a6af85eb2.png": "project/c264d16f0c8de75fda7fd25a6af85eb2.png",
"02a6112a7ea4b0aa690ca29389b6bd52.png": "project/02a6112a7ea4b0aa690ca29389b6bd52.png",
"a19ebe464b8d0c635b91e5ec1816d99c.png": "project/a19ebe464b8d0c635b91e5ec1816d99c.png",
"9a9e7253832953885e94f21976ea61b7.png": "project/9a9e7253832953885e94f21976ea61b7.png",
"869599e81f4386f78a825157ff3c38a6.png": "project/869599e81f4386f78a825157ff3c38a6.png",
"12706e56ab9c18cd9c439e9e43d88c1e.png": "project/12706e56ab9c18cd9c439e9e43d88c1e.png",
"b010e9e67d16c84e7b5a36961c922beb.png": "project/b010e9e67d16c84e7b5a36961c922beb.png",
"369b1d190898986530be98eb09ce4415.png": "project/369b1d190898986530be98eb09ce4415.png",
"ac089f136595e71d3ece67935ea0fc7f.png": "project/ac089f136595e71d3ece67935ea0fc7f.png",
"5fc3c72d9c21d96575836727eac3f479.png": "project/5fc3c72d9c21d96575836727eac3f479.png",
"566bbee28d37338b9cc439e3f76b71a1.png": "project/566bbee28d37338b9cc439e3f76b71a1.png",
"29365bd0402de02b945a110285a3d170.png": "project/29365bd0402de02b945a110285a3d170.png",
"2d5d9248fe805b14a53a8c57cc166504.png": "project/2d5d9248fe805b14a53a8c57cc166504.png",
"769e6de76576b92d244bb7b4507df398.png": "project/769e6de76576b92d244bb7b4507df398.png",
"dae5fb1586407ed14648cbe2806b3c6a.png": "project/dae5fb1586407ed14648cbe2806b3c6a.png",
"bd91b77aa7f8bcd4b1559f6fea469332.png": "project/bd91b77aa7f8bcd4b1559f6fea469332.png",
"2cdc9b99fa19b683bf59ff3f607d8cfb.png": "project/2cdc9b99fa19b683bf59ff3f607d8cfb.png",
"6aad259c873886945631106d10a7ae9c.png": "project/6aad259c873886945631106d10a7ae9c.png",
"09a590b068bbd2cf5e747cc55f3f4b8e.png": "project/09a590b068bbd2cf5e747cc55f3f4b8e.png",
"7a3c61f09fcc697af8a2c91491c4c1de.png": "project/7a3c61f09fcc697af8a2c91491c4c1de.png",
"1affb98e375b19c977981bae12800e2d.wav": "project/1affb98e375b19c977981bae12800e2d.wav",
"e738a77eecc6de7ac3ec62fa89c6043a.png": "project/e738a77eecc6de7ac3ec62fa89c6043a.png",
"e74d5332a7daf10b5d2bdbd578fe7628.png": "project/e74d5332a7daf10b5d2bdbd578fe7628.png",
"5536eedfe2bd94c239a571d9c2aeafb7.png": "project/5536eedfe2bd94c239a571d9c2aeafb7.png",
"a71531b68ff5d6c2b50c4655be5bbce9.png": "project/a71531b68ff5d6c2b50c4655be5bbce9.png",
"c68c27df045f5868cb7d20e918ffce82.png": "project/c68c27df045f5868cb7d20e918ffce82.png",
"eeb7ea16216a3ff8fbc692666ee54eda.png": "project/eeb7ea16216a3ff8fbc692666ee54eda.png",
"febc025a79b0d1289d2aecac390f1352.png": "project/febc025a79b0d1289d2aecac390f1352.png",
"1e1ce334257aed8964e1112b5a0307b3.png": "project/1e1ce334257aed8964e1112b5a0307b3.png",
"f744d6128be3e84552922a8063b60c13.png": "project/f744d6128be3e84552922a8063b60c13.png",
"56de5b706ab18cbea00a411ec9bc2b2e.png": "project/56de5b706ab18cbea00a411ec9bc2b2e.png",
"56b44e5a5de1ff71e29f54e74908cb7b.png": "project/56b44e5a5de1ff71e29f54e74908cb7b.png",
"f4ad401ee458d9f7c825e45ba14bf104.png": "project/f4ad401ee458d9f7c825e45ba14bf104.png",
"b9c9297fd611d52cecfefedad34acfc1.png": "project/b9c9297fd611d52cecfefedad34acfc1.png",
"d6299fd3441afed2e90947d8dddac6f9.png": "project/d6299fd3441afed2e90947d8dddac6f9.png",
"3b1d300ae93ca9a0921eec34dc2f3ed3.png": "project/3b1d300ae93ca9a0921eec34dc2f3ed3.png",
"e35eb55d7f627b220c776de935d82005.png": "project/e35eb55d7f627b220c776de935d82005.png",
"5031b511898d9973130c38595fb52e12.png": "project/5031b511898d9973130c38595fb52e12.png",
"9f90bd6b3496cf43b76e862e52427c5e.png": "project/9f90bd6b3496cf43b76e862e52427c5e.png",
"08e34aa916a1d47cda83b3a93169eec0.png": "project/08e34aa916a1d47cda83b3a93169eec0.png",
"7367f4c773c9cdbf31b3ca92feabf854.wav": "project/7367f4c773c9cdbf31b3ca92feabf854.wav",
"4fe825e9bd9a6fe44478654bd9d58d1e.png": "project/4fe825e9bd9a6fe44478654bd9d58d1e.png",
"ef63c7cd7fddb19cc7625615a2ba2f10.png": "project/ef63c7cd7fddb19cc7625615a2ba2f10.png",
"e5e69cff5b94d25fabdf793e556a13e8.png": "project/e5e69cff5b94d25fabdf793e556a13e8.png",
"d7c1445aa65b0fc2d6d42d9da42574e2.png": "project/d7c1445aa65b0fc2d6d42d9da42574e2.png",
"f86107e03658f3bce9f0c01c01c8b55b.png": "project/f86107e03658f3bce9f0c01c01c8b55b.png",
"137bf16e1114f907a36439d5f7a0fd45.png": "project/137bf16e1114f907a36439d5f7a0fd45.png",
"64a2a7c364b517cd7db6e386c43e036b.png": "project/64a2a7c364b517cd7db6e386c43e036b.png",
"dafac4ac89407564eb52690153af0dc7.png": "project/dafac4ac89407564eb52690153af0dc7.png",
"5e26d963c78e54867f69ec53f34e36b7.png": "project/5e26d963c78e54867f69ec53f34e36b7.png",
"f23ca0fa9e879517752dce7ee2edf740.png": "project/f23ca0fa9e879517752dce7ee2edf740.png",
"b663aa85ecc26ecf9e7ab35f810aac07.png": "project/b663aa85ecc26ecf9e7ab35f810aac07.png",
"d3b57dc6e64a3f4e7b3dd2cfdc7d9110.png": "project/d3b57dc6e64a3f4e7b3dd2cfdc7d9110.png",
"7875272726fc5a9ba1e915e7716cfd69.png": "project/7875272726fc5a9ba1e915e7716cfd69.png",
"256404e388e742accca649b7531807b8.png": "project/256404e388e742accca649b7531807b8.png",
"4d93e949dfdfa7c42e82e862708c877c.wav": "project/4d93e949dfdfa7c42e82e862708c877c.wav",
"5255c7f879eb8739794f6466a205d898.wav": "project/5255c7f879eb8739794f6466a205d898.wav",
"9cc7270cad597ca59bf7eee9a0f37793.png": "project/9cc7270cad597ca59bf7eee9a0f37793.png",
"444482aaf59f99d64f6c208a593642b0.wav": "project/444482aaf59f99d64f6c208a593642b0.wav",
"d5cf6f4cf6d2da370a1322a1798ea77e.wav": "project/d5cf6f4cf6d2da370a1322a1798ea77e.wav",
"21fdb5b437c0f35e0aba73af9dbf7564.wav": "project/21fdb5b437c0f35e0aba73af9dbf7564.wav",
"3db694673df7cf76e1d1a7c9845fa1e2.wav": "project/3db694673df7cf76e1d1a7c9845fa1e2.wav",
"ca191894c2520662e594e106fbad6382.wav": "project/ca191894c2520662e594e106fbad6382.wav",
"ae26aa7f238fd3195941a95024c299c0.wav": "project/ae26aa7f238fd3195941a95024c299c0.wav",
"4b731f0d1b55fcb7f03281bf8556db5b.png": "project/4b731f0d1b55fcb7f03281bf8556db5b.png",
"d19736f77074577513d503d08a0e7713.png": "project/d19736f77074577513d503d08a0e7713.png",
"ad75a5af696ae02944d920e8eec3340e.png": "project/ad75a5af696ae02944d920e8eec3340e.png",
"6da0ad3aab45c965b2f3c08e50864627.png": "project/6da0ad3aab45c965b2f3c08e50864627.png",
"595f9f218308ee37f69be8e0185a8d13.wav": "project/595f9f218308ee37f69be8e0185a8d13.wav",
"a59a919fac60a3dc0c71cd61ca720c45.wav": "project/a59a919fac60a3dc0c71cd61ca720c45.wav",
"3f43170a3670d5dbc9cb6214b6a9dd86.wav": "project/3f43170a3670d5dbc9cb6214b6a9dd86.wav",
"cf0594101b9d5ecf5a250125f13db616.wav": "project/cf0594101b9d5ecf5a250125f13db616.wav",
"511ef1c607d31a858052c47dabf83533.png": "project/511ef1c607d31a858052c47dabf83533.png",
"de79a8aa75e53aa047436083db4a3fa8.png": "project/de79a8aa75e53aa047436083db4a3fa8.png",
"5c269f631582d102c8c5bb4705c0b014.png": "project/5c269f631582d102c8c5bb4705c0b014.png",
"cc466dc9915e7fcac3500284ca9db063.png": "project/cc466dc9915e7fcac3500284ca9db063.png",
"a13e2d2798e4d5a8f45fd0f0de14dcaf.png": "project/a13e2d2798e4d5a8f45fd0f0de14dcaf.png",
"788b6f2eec2a149ed6d72a8d3bcbe316.wav": "project/788b6f2eec2a149ed6d72a8d3bcbe316.wav",
"de42c654b095a90870d158530a2197db.wav": "project/de42c654b095a90870d158530a2197db.wav",
"7d04cb692095d7e42e62a83270d20800.wav": "project/7d04cb692095d7e42e62a83270d20800.wav",
"500f0e6fc5bb9e8a9470349088fc62a5.png": "project/500f0e6fc5bb9e8a9470349088fc62a5.png",
"d7c5135057458ce0472480a97d8f2fa4.png": "project/d7c5135057458ce0472480a97d8f2fa4.png",
"95091f94ccf2d8d73df31cbd8c40aefc.png": "project/95091f94ccf2d8d73df31cbd8c40aefc.png",
"42cfade672d26e99c5b341267163e320.png": "project/42cfade672d26e99c5b341267163e320.png",
"da094f9efb278d90b74b52035fa5760e.wav": "project/da094f9efb278d90b74b52035fa5760e.wav",
"983b2b6971996afec56f206a10e7c134.png": "project/983b2b6971996afec56f206a10e7c134.png",
"dfcd9ce25e2446eb0310ee473f01644b.png": "project/dfcd9ce25e2446eb0310ee473f01644b.png",
"2726a0bc807c78791d6a0bdf22776a33.png": "project/2726a0bc807c78791d6a0bdf22776a33.png",
"e38a6a652e0d81d2e5632f1f2dd70cf0.png": "project/e38a6a652e0d81d2e5632f1f2dd70cf0.png",
"f18bdf0117a5e4a86e93798c5386959b.png": "project/f18bdf0117a5e4a86e93798c5386959b.png",
"50bb720fefe3b9d37639097acb605099.png": "project/50bb720fefe3b9d37639097acb605099.png",
"90d1c756525c02de95a399304876a1ad.png": "project/90d1c756525c02de95a399304876a1ad.png",
"2c25e7deda8eea1cc5a2a1d46549ba5b.wav": "project/2c25e7deda8eea1cc5a2a1d46549ba5b.wav",
"a15e17cf3065183d9f4789e6ed92bb23.png": "project/a15e17cf3065183d9f4789e6ed92bb23.png",
"165b5300d3dde30e8cd7cce6777406bc.wav": "project/165b5300d3dde30e8cd7cce6777406bc.wav",
"dbed2edb91c21151e1c950005184c621.png": "project/dbed2edb91c21151e1c950005184c621.png",
"008052d25c18026d350da7e69c0f05d0.svg": "project/008052d25c18026d350da7e69c0f05d0.svg",
"faf7cdc6bc5dc4e689dacec3f93f899b.svg": "project/faf7cdc6bc5dc4e689dacec3f93f899b.svg",
"1a9b966d691e7ddc9015bd5296ab5329.svg": "project/1a9b966d691e7ddc9015bd5296ab5329.svg",
"a924ca2dfc10cfbbf35c639e5906f0a0.svg": "project/a924ca2dfc10cfbbf35c639e5906f0a0.svg",
"c5aa89b64eb1f2a15d647e2dc1a58477.svg": "project/c5aa89b64eb1f2a15d647e2dc1a58477.svg",
"35ead26b56626491bc4e91d5091a4d2d.wav": "project/35ead26b56626491bc4e91d5091a4d2d.wav",
"fcb0c8f48f91c91c96e85598c7eb2562.wav": "project/fcb0c8f48f91c91c96e85598c7eb2562.wav",
"5baa44341b5678da4ec4b023c287f717.svg": "project/5baa44341b5678da4ec4b023c287f717.svg",
"9913ddbb4099cd28e69e22571afd7fb4.svg": "project/9913ddbb4099cd28e69e22571afd7fb4.svg",
"90edda1fb0dfc018501c57e8885ff99a.png": "project/90edda1fb0dfc018501c57e8885ff99a.png",
"6e55f3f5f04b4ac5175acb2d1f1b8ce3.png": "project/6e55f3f5f04b4ac5175acb2d1f1b8ce3.png",
"12529e1748892bf12caf456a81281736.png": "project/12529e1748892bf12caf456a81281736.png",
"b8d265454d94c4aa84b4040b4808cfee.png": "project/b8d265454d94c4aa84b4040b4808cfee.png",
"6ff9846d810175a78d9462aed6be596e.png": "project/6ff9846d810175a78d9462aed6be596e.png",
"83408f8e4bc7c19713060f88b946e638.png": "project/83408f8e4bc7c19713060f88b946e638.png",
"709bfd5a7f0cd0e76f1d482879025cba.png": "project/709bfd5a7f0cd0e76f1d482879025cba.png",
"dc41b72aebdd5f573756ea34830c3bd0.png": "project/dc41b72aebdd5f573756ea34830c3bd0.png",
"88d3e91071e3ae785e2b8e5ea730a5a2.png": "project/88d3e91071e3ae785e2b8e5ea730a5a2.png",
"0ad57dba68e7e5bd077b695aa4ea5088.png": "project/0ad57dba68e7e5bd077b695aa4ea5088.png",
"387537489c75427b31bedc7cd64f91a1.wav": "project/387537489c75427b31bedc7cd64f91a1.wav",
"4325bab9558a30339fda61eef6274574.png": "project/4325bab9558a30339fda61eef6274574.png",
"e28773518588d21f8b1ae52a78baa2d1.png": "project/e28773518588d21f8b1ae52a78baa2d1.png",
"a4463c950f6a4eb9d910900274841ec1.png": "project/a4463c950f6a4eb9d910900274841ec1.png",
"d522c0b92aa5e7fae7de9800c19262c0.png": "project/d522c0b92aa5e7fae7de9800c19262c0.png",
"5ffd6c0928101434011acad14e0452ec.png": "project/5ffd6c0928101434011acad14e0452ec.png",
"3481d25840494b0ef0937bfee862c1b5.png": "project/3481d25840494b0ef0937bfee862c1b5.png",
"42cf8ffc00e08ca7dcb9fbd80294d168.png": "project/42cf8ffc00e08ca7dcb9fbd80294d168.png",
"4e5dda5dd33f3bd4e2503ce975fd96ab.png": "project/4e5dda5dd33f3bd4e2503ce975fd96ab.png",
"88fb2147d9abc1ace39457618c4e12e4.png": "project/88fb2147d9abc1ace39457618c4e12e4.png",
"1fe3c2e359be03b78b1697ffd6ca585f.png": "project/1fe3c2e359be03b78b1697ffd6ca585f.png",
"69767ce1bed2f8e281626a22f66be0fe.png": "project/69767ce1bed2f8e281626a22f66be0fe.png",
"47a96337f28af2f4ee341a430a90cb54.svg": "project/47a96337f28af2f4ee341a430a90cb54.svg",
"014b5a6c881499fc08a81822a7cb8229.wav": "project/014b5a6c881499fc08a81822a7cb8229.wav",
"60914d6a7c0eddece12dae082af372fc.png": "project/60914d6a7c0eddece12dae082af372fc.png",
"8151475ac081594d41ec6516829e0366.png": "project/8151475ac081594d41ec6516829e0366.png",
"571039ddb2ee02622d841406f18b5695.png": "project/571039ddb2ee02622d841406f18b5695.png",
"29a751e49b66d7bb36d24fcc2b7b551f.png": "project/29a751e49b66d7bb36d24fcc2b7b551f.png",
"a614e302fe05cd1538fc07d075a0d851.png": "project/a614e302fe05cd1538fc07d075a0d851.png",
"e1676a274470be609d2d342010d1111b.png": "project/e1676a274470be609d2d342010d1111b.png",
"c58cbddbd77429cb390ff3916a187e1d.png": "project/c58cbddbd77429cb390ff3916a187e1d.png",
"80260313b2f2134424f1ce474dd03944.png": "project/80260313b2f2134424f1ce474dd03944.png",
"b7f28f05be1160a5f6c2b3a590ed4af7.png": "project/b7f28f05be1160a5f6c2b3a590ed4af7.png",
"fe64d2522d78eeb76eb611740cee2bd8.png": "project/fe64d2522d78eeb76eb611740cee2bd8.png",
"de850e8c8840b89c0aad850cdbbfbb11.png": "project/de850e8c8840b89c0aad850cdbbfbb11.png",
"6c8f734797b1212d3cd8ec3ca808c796.png": "project/6c8f734797b1212d3cd8ec3ca808c796.png",
"99512e1cf872b8f43f955639b3e375d1.png": "project/99512e1cf872b8f43f955639b3e375d1.png",
"98e5bd833ddb52ced32386f1a5f8ad5d.png": "project/98e5bd833ddb52ced32386f1a5f8ad5d.png",
"fb94b0144f7a5733b852d7e7b14355af.png": "project/fb94b0144f7a5733b852d7e7b14355af.png",
"00fe94ccbb064ff3298fd5dc5679708c.png": "project/00fe94ccbb064ff3298fd5dc5679708c.png",
"043102a5d162bb4dd009d823eafe9ca2.png": "project/043102a5d162bb4dd009d823eafe9ca2.png",
"5340c4436113c391b8fce5d3498c43c1.png": "project/5340c4436113c391b8fce5d3498c43c1.png",
"9fd03a034d460ddd3da941e4a5d5e4c7.png": "project/9fd03a034d460ddd3da941e4a5d5e4c7.png",
"37a85470e40ee856a265b809011d9d65.png": "project/37a85470e40ee856a265b809011d9d65.png",
"8a825d3d9d48c62d9900ee51abe515c5.png": "project/8a825d3d9d48c62d9900ee51abe515c5.png",
"a581c3b92dde9d59cdf9c40afaf1b53d.png": "project/a581c3b92dde9d59cdf9c40afaf1b53d.png",
"49f89e85841f258b9e2c5a7295e79a2f.png": "project/49f89e85841f258b9e2c5a7295e79a2f.png",
"185f3576bbd485521f16ea7d4f887b51.png": "project/185f3576bbd485521f16ea7d4f887b51.png",
"58144064c3b52a8f993add0f27facbc6.png": "project/58144064c3b52a8f993add0f27facbc6.png",
"13cab66780abe8613edf1fe3fcb99f7a.png": "project/13cab66780abe8613edf1fe3fcb99f7a.png",
"f23968af3171d5d705e8196deec43279.png": "project/f23968af3171d5d705e8196deec43279.png",
"d495277b3bdf234a35afad2b910f2d51.png": "project/d495277b3bdf234a35afad2b910f2d51.png",
"b46b3f2603feb9419a12dd040eb3a2ed.png": "project/b46b3f2603feb9419a12dd040eb3a2ed.png",
"a5823d56d0b3f95fff41414a5368898c.png": "project/a5823d56d0b3f95fff41414a5368898c.png",
"bfeed39111b7ee6efa6f339490a29ef2.png": "project/bfeed39111b7ee6efa6f339490a29ef2.png",
"d8bc50c19e095d193a7a3d2e5d5afb8a.png": "project/d8bc50c19e095d193a7a3d2e5d5afb8a.png",
"8b006f82ad915b504cc91060e5976073.png": "project/8b006f82ad915b504cc91060e5976073.png",
"5abab81db02a655ab4da57e4657049a4.png": "project/5abab81db02a655ab4da57e4657049a4.png",
"7c11a7833da572745340eccf15b379c1.png": "project/7c11a7833da572745340eccf15b379c1.png",
"91a96088a5ae7565a238357302ec23e3.png": "project/91a96088a5ae7565a238357302ec23e3.png",
"acf138d6cc28d3f804adb69b8f9b775d.png": "project/acf138d6cc28d3f804adb69b8f9b775d.png",
"8f838ffbff1d129ad8ff0251b7bc768e.png": "project/8f838ffbff1d129ad8ff0251b7bc768e.png",
"d860800e1006eaae108537920adadc31.png": "project/d860800e1006eaae108537920adadc31.png",
"ef7217974f44e48739685557bfd2d454.png": "project/ef7217974f44e48739685557bfd2d454.png",
"348f4ddda6dc8d367d6da09cbc4292f1.png": "project/348f4ddda6dc8d367d6da09cbc4292f1.png",
"9b1f3bfa07079b9bdaaa93f427a69a32.png": "project/9b1f3bfa07079b9bdaaa93f427a69a32.png",
"a9c30b375fd09f55ebad11090b8b6952.png": "project/a9c30b375fd09f55ebad11090b8b6952.png",
"02a5382f5dac52c107bd9ab86f17f57a.png": "project/02a5382f5dac52c107bd9ab86f17f57a.png",
"1134d384624103d5833001f5473e92df.png": "project/1134d384624103d5833001f5473e92df.png",
"c3618fd4a2f22748ad005ac32fa67d34.png": "project/c3618fd4a2f22748ad005ac32fa67d34.png",
"b204476cb15246b04255a1b117ed8061.png": "project/b204476cb15246b04255a1b117ed8061.png",
"3eb7e370e6d7304170e0706be31d86af.png": "project/3eb7e370e6d7304170e0706be31d86af.png",
"703c2318783209c4427029601f6d48a6.png": "project/703c2318783209c4427029601f6d48a6.png",
"1e80c8ef9fceb49bb83634a7f29521a6.png": "project/1e80c8ef9fceb49bb83634a7f29521a6.png",
"9f26315e01b0b4408e76edf8fb6c5ed3.png": "project/9f26315e01b0b4408e76edf8fb6c5ed3.png",
"ad326197194d87c2e0c3c663747682c9.png": "project/ad326197194d87c2e0c3c663747682c9.png",
"4a24ba41417d0feaa1477fb5a6a8a8fb.png": "project/4a24ba41417d0feaa1477fb5a6a8a8fb.png",
"557af14fc1c941c19ce36b6971c5e761.png": "project/557af14fc1c941c19ce36b6971c5e761.png",
"d9192d3514f875bc3e4e84a26dde05f6.png": "project/d9192d3514f875bc3e4e84a26dde05f6.png",
"254528a6979dad7e5be1bde5d911b7f3.png": "project/254528a6979dad7e5be1bde5d911b7f3.png",
"2b90538f4c02bf9d2e801bc0286ee1b1.png": "project/2b90538f4c02bf9d2e801bc0286ee1b1.png",
"1dce8d9f22433e275193dfb04f6355d1.png": "project/1dce8d9f22433e275193dfb04f6355d1.png",
"3f39c30f4cbf3dcd8ecba97e660231cb.png": "project/3f39c30f4cbf3dcd8ecba97e660231cb.png",
"38d16e23aac77ec699a3b8dd8606c1c7.png": "project/38d16e23aac77ec699a3b8dd8606c1c7.png",
"3c75f0b6bd5aee825c5fd68884aafc7e.png": "project/3c75f0b6bd5aee825c5fd68884aafc7e.png",
"54a87202d9830ef9c74c45786f3a9a4d.png": "project/54a87202d9830ef9c74c45786f3a9a4d.png",
"beae8a3d48b7565a0c6c047d2ad917bc.png": "project/beae8a3d48b7565a0c6c047d2ad917bc.png",
"f582497135ddf0e2fd90b793a95bd381.png": "project/f582497135ddf0e2fd90b793a95bd381.png",
"8622a8063a45e6f34dda14394bab5c30.png": "project/8622a8063a45e6f34dda14394bab5c30.png",
"7c77dee1614f7336d59dd7891ab950df.png": "project/7c77dee1614f7336d59dd7891ab950df.png",
"697f7dff0fcb34813d05ef5c11381479.png": "project/697f7dff0fcb34813d05ef5c11381479.png",
"ce4387d710b58c7274f3e46eec94dcfa.png": "project/ce4387d710b58c7274f3e46eec94dcfa.png",
"6b00207cee5869c307c947afb599cdaf.png": "project/6b00207cee5869c307c947afb599cdaf.png",
"c83e951c281242e123ceb96e3bdda208.png": "project/c83e951c281242e123ceb96e3bdda208.png",
"390355b33856e3f7a2f3f5f00f190d31.png": "project/390355b33856e3f7a2f3f5f00f190d31.png",
"6c394f9a6c5affed5b137641e06c2017.png": "project/6c394f9a6c5affed5b137641e06c2017.png",
"24347f0e7f1f3642a106c373ee410561.png": "project/24347f0e7f1f3642a106c373ee410561.png",
"7622d1e990c5dde0a8c6bdefab15881d.png": "project/7622d1e990c5dde0a8c6bdefab15881d.png",
"4e34caa3c5d7cad1d3cca6528496f26c.png": "project/4e34caa3c5d7cad1d3cca6528496f26c.png",
"0f4c705b18ae7d4b5432f0e2e0cb8d74.png": "project/0f4c705b18ae7d4b5432f0e2e0cb8d74.png",
"588bee73ee0a649e5a02cc8c54669636.png": "project/588bee73ee0a649e5a02cc8c54669636.png",
"afcd2230227c5d299910ccac367e19db.png": "project/afcd2230227c5d299910ccac367e19db.png",
"229ee902f6a83847899ebf1312a6dbd7.png": "project/229ee902f6a83847899ebf1312a6dbd7.png",
"ce531dbd38b7f2c6a73b8a402544f8af.svg": "project/ce531dbd38b7f2c6a73b8a402544f8af.svg",
"24d07627171a70aa7c8f340a03c6e5ef.svg": "project/24d07627171a70aa7c8f340a03c6e5ef.svg",
"3e5445bfcdd0d32511687c29ff8ce6f4.svg": "project/3e5445bfcdd0d32511687c29ff8ce6f4.svg",
"0a1506680784999cb025bbb5e364fb20.wav": "project/0a1506680784999cb025bbb5e364fb20.wav",
"b2947353957f568caa2424f53c6ef2e3.wav": "project/b2947353957f568caa2424f53c6ef2e3.wav",
"957e7c09743a6b3967a599c304e9fb7e.wav": "project/957e7c09743a6b3967a599c304e9fb7e.wav",
"6cadfbcecfdad590c62d086bb2e2fbb4.png": "project/6cadfbcecfdad590c62d086bb2e2fbb4.png",
"f4448e8d587e4bf549bd8a0439c2b3c7.png": "project/f4448e8d587e4bf549bd8a0439c2b3c7.png",
"718b76fa2d53af50eb04b053cb0bc398.png": "project/718b76fa2d53af50eb04b053cb0bc398.png",
"8d3e96eb8e88aa0e23b35e468aeff0a2.png": "project/8d3e96eb8e88aa0e23b35e468aeff0a2.png",
"370dd14721b1397b42b3b739722e8081.png": "project/370dd14721b1397b42b3b739722e8081.png",
"10737043769266fecb1b1fc02b57a957.png": "project/10737043769266fecb1b1fc02b57a957.png",
"954b161b55b3d396f0754a686707de90.png": "project/954b161b55b3d396f0754a686707de90.png",
"bd8feb1a255a72f119ea3fe244774961.png": "project/bd8feb1a255a72f119ea3fe244774961.png",
"9b0e6e6a450267755680fa830458af58.png": "project/9b0e6e6a450267755680fa830458af58.png",
"fcf25b01d622e5be6866c642c3bba285.png": "project/fcf25b01d622e5be6866c642c3bba285.png",
"75acb19ff2a32b38f766a6cd0e871a4e.png": "project/75acb19ff2a32b38f766a6cd0e871a4e.png",
"fbc5271ed855778277738880343a590b.png": "project/fbc5271ed855778277738880343a590b.png",
"eea2126c99d19c75c29664151d3a188d.png": "project/eea2126c99d19c75c29664151d3a188d.png",
"02dabc1ff5743f2141b41ed1acb4c960.png": "project/02dabc1ff5743f2141b41ed1acb4c960.png",
"eb093420f1041d3a96e0fd070a74f235.png": "project/eb093420f1041d3a96e0fd070a74f235.png",
"2706c07b197339a3c8e2504cb64fce30.png": "project/2706c07b197339a3c8e2504cb64fce30.png",
"9d0b00391f3627567a046593999f995b.png": "project/9d0b00391f3627567a046593999f995b.png",
"79c34dce8307502326b5af5e0b505954.png": "project/79c34dce8307502326b5af5e0b505954.png",
"a554650a31c3c64e0a37ad25b67b5ff9.png": "project/a554650a31c3c64e0a37ad25b67b5ff9.png",
"9f30efdfb877e8ec44f129c22aef22a6.png": "project/9f30efdfb877e8ec44f129c22aef22a6.png",
"7fa7be20b90c07be0b5fab3c1a7ffda8.png": "project/7fa7be20b90c07be0b5fab3c1a7ffda8.png",
"e45d788babb91dfed26adcf3ea16649b.png": "project/e45d788babb91dfed26adcf3ea16649b.png",
"b451ef95eb2f8eae55fa143f5da238ed.png": "project/b451ef95eb2f8eae55fa143f5da238ed.png",
"a2b0feaf520b7517406ca027c0dbb201.png": "project/a2b0feaf520b7517406ca027c0dbb201.png",
"4dafb489d55cb2be799c9878992caa4b.png": "project/4dafb489d55cb2be799c9878992caa4b.png",
"36dcf3583b4bebe6540dee26ad688511.png": "project/36dcf3583b4bebe6540dee26ad688511.png",
"4a67edeb8eb54d384aeb3c811168c3af.png": "project/4a67edeb8eb54d384aeb3c811168c3af.png",
"e03342a9818c6776c9fc3f0e4ff4607c.png": "project/e03342a9818c6776c9fc3f0e4ff4607c.png",
"17b1f3aa28eefc88e4335d8d6d0048e8.png": "project/17b1f3aa28eefc88e4335d8d6d0048e8.png",
"361fc4480f3c76c1027e872867a8c85f.png": "project/361fc4480f3c76c1027e872867a8c85f.png",
"f93ab676a30e334c3ce52e998f06a805.png": "project/f93ab676a30e334c3ce52e998f06a805.png",
"5b09c75936eb023ce8c66e09cde928bd.png": "project/5b09c75936eb023ce8c66e09cde928bd.png",
"31cfd384e32a5a795f9be063bca979aa.png": "project/31cfd384e32a5a795f9be063bca979aa.png",
"a51b426c7aeffcc44cdae96befbbbd4b.png": "project/a51b426c7aeffcc44cdae96befbbbd4b.png",
"7c7a71d3bc889e792b0dbac63f9d9bba.png": "project/7c7a71d3bc889e792b0dbac63f9d9bba.png",
"0a00455629f6f2d79980cb55a37a5edc.png": "project/0a00455629f6f2d79980cb55a37a5edc.png",
"606be1d34b819f89d690c07eb64ea033.png": "project/606be1d34b819f89d690c07eb64ea033.png",
"5b3f7adb14c2988d04fb85b1b10db7d3.png": "project/5b3f7adb14c2988d04fb85b1b10db7d3.png",
"1995a37b4e518b93f2a28c8eaea4d393.png": "project/1995a37b4e518b93f2a28c8eaea4d393.png",
"d5452b6745952b5dab02d1205bd72c33.png": "project/d5452b6745952b5dab02d1205bd72c33.png",
"1d91ae2e4dbc7dffe92a59907c1b2e03.png": "project/1d91ae2e4dbc7dffe92a59907c1b2e03.png",
"f155ce4ec4a661e7c04220155fe4298b.png": "project/f155ce4ec4a661e7c04220155fe4298b.png",
"1d331a4ca464c7e7f2c2f66ba41f65a5.png": "project/1d331a4ca464c7e7f2c2f66ba41f65a5.png",
"a2eb70ad62b7f957edb15f6ab0cc8bb4.png": "project/a2eb70ad62b7f957edb15f6ab0cc8bb4.png",
"aff7fa9d5b53e9e76ff3cd55021c0859.png": "project/aff7fa9d5b53e9e76ff3cd55021c0859.png",
"cbe0c504ae63d3a7c395f2304d8332c5.png": "project/cbe0c504ae63d3a7c395f2304d8332c5.png",
"78d4b9a45226068d683ccf60d9a49a70.png": "project/78d4b9a45226068d683ccf60d9a49a70.png",
"3f45d82ec73538c87e01657a97f716d4.png": "project/3f45d82ec73538c87e01657a97f716d4.png",
"aa858392e29b13a1a418102b3b82ef81.png": "project/aa858392e29b13a1a418102b3b82ef81.png",
"079268c2108ae789c2018267d6b7aa16.png": "project/079268c2108ae789c2018267d6b7aa16.png",
"a7094aa1f75c1846eb865b2f057a469f.wav": "project/a7094aa1f75c1846eb865b2f057a469f.wav",
"56cdd826e3c0df9edfffd33a63c9ea3f.png": "project/56cdd826e3c0df9edfffd33a63c9ea3f.png",
"5f327894df436ef7420793ecb0654c86.png": "project/5f327894df436ef7420793ecb0654c86.png",
"3bdaadb1bf3125ed621616c61d445ab3.png": "project/3bdaadb1bf3125ed621616c61d445ab3.png",
"5f7908078d49e05aecbb0375a393dc43.png": "project/5f7908078d49e05aecbb0375a393dc43.png",
"297dfb14af1b74c1b345579fb5a7e11b.png": "project/297dfb14af1b74c1b345579fb5a7e11b.png",
"ea12d1cbae2ab08c40d5a2850e0ee571.png": "project/ea12d1cbae2ab08c40d5a2850e0ee571.png",
"43e8adba7a23a15ba4ad52d167048dc6.png": "project/43e8adba7a23a15ba4ad52d167048dc6.png",
"847ec8933335cd5290627aabf8c0e7f5.png": "project/847ec8933335cd5290627aabf8c0e7f5.png",
"7b4eaf66d065b5e65b60bf3ea27e826f.png": "project/7b4eaf66d065b5e65b60bf3ea27e826f.png",
"34c6e844c085b87000719272dbe42cf4.png": "project/34c6e844c085b87000719272dbe42cf4.png",
"83c36d806dc92327b9e7049a565c6bff.wav": "project/83c36d806dc92327b9e7049a565c6bff.wav",
"a2a342bcc9441e1a2d4c9dd2712a94b2.png": "project/a2a342bcc9441e1a2d4c9dd2712a94b2.png",
"dbecc41021833aeee6399867fd221f86.png": "project/dbecc41021833aeee6399867fd221f86.png",
"3e1a99b52c5c7d19c124deb8d80984af.png": "project/3e1a99b52c5c7d19c124deb8d80984af.png",
"e83b9fa86512e706e5a79b5dd0e7b12e.png": "project/e83b9fa86512e706e5a79b5dd0e7b12e.png",
"758ce3c25f5be3061e6c5c2408d71861.png": "project/758ce3c25f5be3061e6c5c2408d71861.png",
"bdd47f46b7ea0d7604fe65cd4c3974cc.png": "project/bdd47f46b7ea0d7604fe65cd4c3974cc.png",
"1b3dccc76cea2ddde9d505d9ea2f0d84.png": "project/1b3dccc76cea2ddde9d505d9ea2f0d84.png",
"704e4b8315608dbcd3f04354bf7b9e48.png": "project/704e4b8315608dbcd3f04354bf7b9e48.png",
"b9ba5725c372f3faacbf97d255d2269a.png": "project/b9ba5725c372f3faacbf97d255d2269a.png",
"7d0672a26fd85988399bc0be341f3ba9.png": "project/7d0672a26fd85988399bc0be341f3ba9.png",
"c63efedb849fe96eb0cd2a5142eecf5d.png": "project/c63efedb849fe96eb0cd2a5142eecf5d.png",
"e006c5f1242f80fc5184369f2cfd6626.png": "project/e006c5f1242f80fc5184369f2cfd6626.png",
"1319492969bda5edb7f2bb78cdb98f77.png": "project/1319492969bda5edb7f2bb78cdb98f77.png",
"e8d2eca0fc942740937409107fdb341d.png": "project/e8d2eca0fc942740937409107fdb341d.png",
"c2b0fc67dbcd856d78e318f9cc69f885.png": "project/c2b0fc67dbcd856d78e318f9cc69f885.png",
"c8f3a9b0155ca218f2bfbefca09a9dec.png": "project/c8f3a9b0155ca218f2bfbefca09a9dec.png",
"7e78bfbc53d11627202dc01989e1aa3b.png": "project/7e78bfbc53d11627202dc01989e1aa3b.png",
"b56ca6f44b03b4dc9246e127e1ea13dc.png": "project/b56ca6f44b03b4dc9246e127e1ea13dc.png",
"847b6eb8f598711efe983dc3c99c803a.svg": "project/847b6eb8f598711efe983dc3c99c803a.svg"
}
}
init(initOptions)
</script>
</body>
</html>