<!DOCTYPE html>
<html>
  <head>
    <title>Super Saber</title>
    <meta name="description" content="A free and open source clone of Beat Saber with 6000+ community songs.">
    <meta name="keywords" content="vr, webvr, beat, saber, aframe">
    <meta name="og:title" content="Super Saber">
    <meta name="og:image" content="https://supermedium.com/supersaber/site/assets/splash.jpg">
    <meta name="og:description" content="A free and open source clone of Beat Saber with 6000+ community songs.">
    <meta property="og:url" content="https://supermedium.com/supersaber/">
    <meta name="twitter:card" content="summary">
    <meta name="twitter:site" content="https://supermedium.com/supersaber">
    <meta name="twitter:creator" content="@supermediumvr">
    <meta name="twitter:title" content="Super Saber">
    <meta name="twitter:description" content="A free and open source clone of Beat Saber with 6000+ community songs.">
    <meta name="twitter:image" content="https://supermedium.com/supersaber/site/assets/splash.jpg">
    <link rel="shortcut icon" href="assets/img/favicon.png" type="image/x-icon">

    {% if DEBUG_AFRAME %}
      <script src="http://{{ HOST }}:9000/dist/aframe-master.js"></script>
    {% elif IS_PRODUCTION %}
      <script src="vendor/aframe-master.min.js"></script>
    {% else %}
      <script src="vendor/aframe-master.js"></script>
    {% endif %}
    <script src="build/build.js"></script>
  </head>
  <body>
    <audio id="introSong" src="assets/sounds/introSong.ogg" loop></audio>

    <a-scene
      mixin="gameoverAnimation bgColorAnimation tunnelColorAnimation leftLaserColorAnimation rightLaserColorAnimation textGlowColorAnimation floorColorAnimation"
      bind__beat-loader="challengeId: challenge.id; difficulty: menuSelectedChallenge.difficulty; isPlaying: isPlaying; menuSelectedChallengeId: menuSelectedChallenge.id; difficultyFiles: menuSelectedChallenge.difficultyFiles"
      bind__gameover="isGameOver: isGameOver"
      bind__intro-song="isPlaying: menuActive && !menuSelectedChallenge.id; isSearching: isSearching"
      bind__leaderboard="isVictory: isVictory; menuSelectedChallengeId: menuSelectedChallenge.id; challengeId: challenge.id"
      bind__song="challengeId: challenge.id; isPlaying: isPlaying; isBeatsPreloaded: challenge.isBeatsPreloaded; isGameOver: isGameOver; isVictory: isVictory; songUrl: menuSelectedChallenge.songUrl"
      bind__song-preview-system="challengeId: challenge.id; isSearching: isSearching; isSongLoading: isSongLoading; selectedChallengeId: menuSelectedChallenge.id; songUrl: menuSelectedChallenge.songUrl"
      animation__gameover="property: object3D.background; type: color; to: #750000; startEvents: gameover"
      console-shortcuts
      debug-beat-loader
      debug-controller
      debug-song-time
      debug-state
      hack
      gpu-preloader
      {% if DEBUG_INSPECTOR %}
        inspector="url: http://localhost:3333/dist/aframe-inspector.js"
      {% else %}
        inspector="url: https://cdn.jsdelivr.net/gh/aframevr/aframe-inspector@master/dist/aframe-inspector.min.js"
      {% endif %}
      leaderboard="apiKey: AIzaSyBCnpzND3eN37CBSu1bSYfaKQoe6yD3SnY; authDomain: supersaberrr.firebaseapp.com; databaseURL: https://supersaberrr.firebaseio.com; projectId: supersaberrr; storageBucket: supersaberrr.appspot.com; messagingSenderId: 172125624222"
      loading-screen="backgroundColor: #000;"
      pool__beat-arrow-blue="mixin: arrowBlueBeat; size: 10; container: #beatContainer"
      pool__beat-arrow-red="mixin: arrowRedBeat; size: 10; container: #beatContainer"
      pool__beat-dot-blue="mixin: dotBlueBeat; size: 10; container: #beatContainer"
      pool__beat-dot-red="mixin: dotRedBeat; size: 10; container: #beatContainer"
      pool__beat-mine="mixin: mine; size: 12; container: #beatContainer"
      pool__beatscoreok="mixin: beatScoreOk; size: 10; container: #beatContainer"
      pool__beatscoregood="mixin: beatScoreGood; size: 10; container: #beatContainer"
      pool__beatscoregreat="mixin: beatScoreGreat; size: 10; container: #beatContainer"
      pool__beatscoresuper="mixin: beatScoreSuper; size: 10; container: #beatContainer"
      pool__wall="mixin: wall; size: 10; container: #beatContainer"
      proxy-event__cleargame1="event: gamemenuexit; as: cleargame; to: a-scene"
      proxy-event__cleargame2="event: gamemenurestart; as: cleargame; to: a-scene"
      play-sound__beatwrong="sound: #beatMissSound; event: beatwrong; volume: 0.4"
      proxy-event__pausegame="event: pausegame; as: textglowoff; to: a-scene"
      proxy-event__resumegame="event: gamemenuresume; as: textglownormal; to: a-scene"
      play-sound__victory="sound: #victorySong; event: victory"
      play-sound__crescendo="sound: #crescendo; event: victory; volume: 0.75"
      search
      stage-colors="color: blue"
      stats-param
      vr-mode-ui="enterVRButton: #vrButton"
      tutorial-2d>
      <!-- fog="color: #a00; density: 0.035; type: exponential" -->

      <a-assets timeout="10000">
        {% include './assets.html' %}
      </a-assets>

      <a-entity id="beatObjTemplate" obj-model="obj: #beatObj" visible="false"></a-entity>
      <a-entity id="arrowRedObjTemplate" obj-model="obj: #arrowredObj" visible="false"></a-entity>
      <a-entity id="arrowBlueObjTemplate" obj-model="obj: #arrowblueObj" visible="false"></a-entity>
      <a-entity id="dotRedObjTemplate" obj-model="obj: #dotredObj" visible="false"></a-entity>
      <a-entity id="dotBlueObjTemplate" obj-model="obj: #dotblueObj" visible="false"></a-entity>
      <a-entity id="mineObjTemplate" obj-model="obj: #mineObj" visible="false"></a-entity>
      <a-entity id="cursorLaser" obj-model="obj: #laserObj" visible="false"></a-entity>


      {% include './templates/stage.html' %}

      <a-entity
        id="beatContainer"
        bind__pause="isPaused: !isPlaying"
        beat-hit-sound></a-entity>

      {% include './templates/loading.html' %}
      {% include './templates/score.html' %}
      {% include './templates/menu.html' %}
      {% include './templates/tutorial.html' %}
      {% include './templates/gameMenu.html' %}
      {% include './templates/victory.html' %}
      {% include './templates/leaderboard.html' %}
      {% include './templates/news.html' %}

      <!-- super cut fx rings -->
      {% for i in range(1, 5) %}
        <a-entity class="superCutFx" mixin="superCut"></a-entity>
      {% endfor %}

      <!-- Wrong + miss beat visual indicators. -->
      <a-entity id="badContainer" bind__visible="isPlaying">
        <a-entity id="wrongLeft" mixin='beatWrong'></a-entity>
        <a-entity id="wrongRight" mixin='beatWrong'></a-entity>
        <a-entity id="missLeft" mixin='beatMiss'></a-entity>
        <a-entity id="missRight" mixin='beatMiss'></a-entity>
      </a-entity>

      <a-entity
        id="saberParticles"
        particleplayer="src: #saberParticlesJSON; interpolate: true; pscale: 0.55; dur: 800; loop: false; on: explode; img: #sparkImg; count: 20%; animateScale: true; initialScale: 4 1 1; finalScale: 0.2 0.2 1"></a-entity>
      <a-entity
        id="mineParticles"
        particleplayer="src: #mineParticlesJSON; pscale: 0.5; interpolate: true; scale: 1.4; loop: false; on: explode; img: #sparkImg; count: 20%; animateScale: true; initialScale: 3 1 1; finalScale: 0.2 0.2 1"></a-entity>
      <a-entity
        id="sparkParticles"
        particleplayer="src: #sparksJSON; color: #fcc; pscale: 0.5; on: explode; scale: 0.12; loop: false; img: #spark2Img; dur: 700; count: 50%; animateScale: true; initialScale: 3 0.5 1; finalScale: 0.1 0.5 1"></a-entity>

      <a-mixin
        id="cursorMesh"
        material="shader: flat; transparent: true; src: #cursorMeshImg; depthTest: false"
        sub-object="from: #cursorLaser; name: glow"></a-mixin>

      <!-- Player. -->
      <a-entity id="cameraRig" recenter-camera>
        <a-entity id="camera" position="0 1.6 0.5" camera look-controls wasd-controls>
          <a-entity
            id="cameraCollider"
            bind__aabb-collider="enabled: isPlaying"
            aabb-collider="objects: [data-collidable-head]; interval: 50; collideNonVisible: false"
            geometry="primitive: box; width: 0.10; height: 0.10; depth: 0.10"
            proxy-event__wallhitstart="event: hitstart; to: a-scene; as: wallhitstart"
            proxy-event__wallhitend="event: hitend; to: a-scene; as: wallhitend"
            visible="false"></a-entity>
        </a-entity>
        
        <a-entity
        id="controllerRig"
        proxy-event="event: recentered; to: #cameraRig; captureBubbles: true; as: recenter">
        {% macro saber (hand, otherHand, bladeColor, beamColor) %}
          <a-entity id="{{ hand }}Hand"
            class="saber"
            mixin="raycaster"
            bind__hand-swapper="enabled: {{ otherHand }}RaycasterActive"
            bind__menu-controls="page: search.page; selectedChallengeId: menuSelectedChallenge.id"
            bind__pauser="enabled: isPlaying"
            bind__raycaster="enabled: {{ hand }}RaycasterActive"
            bind__raycaster-game="enabled: isPlaying"
            bind__saber-controls="bladeEnabled: isPlaying; isPaused: isPaused"
            bind__saber-particles="enabled: isPlaying"
            bind__trail="enabled: isPlaying"
            haptics="events: mouseenter; dur: 35; force: 0.075"
            haptics__beat="eventsFrom: #beatContainer; events: beatcollide{{ hand }}; dur: 80; force: 0.2"
            haptics__draw="events: drawblade; dur: 750; force: 0.025"
            haptics-saber
            haptics-wall
            raycaster="objects: [raycastable]; far: 5"
            raycaster__game="objects: [raycastable-game]:not(.blade{{ hand }}); far: 1; interval: 50"
            saber-particles="hand: {{ hand }}"
            saber-controls="hand: {{ hand }}"
            thumb-controls
            thumb-controls-debug="enabled: false; hand: {{ hand }}; controllerType: vive-controls"
            trail="color: {{ bladeColor }}; hand: {{ hand }}">
            <a-entity
              id="{{ hand }}Laser"
              bind__cursor-laser="enabled: !isPlaying && activeHand === '{{ hand }}'"
              geometry="primitive: cylinder; height: 1; radius: 0.005"
              material="color: {{ beamColor }}; shader: flat"
              rotation="-90 0 0"></a-entity>

            <a-entity class="saberContainer" rotation="90 0 0">
              <a-entity
                class="bladeContainer"
                bind__visible="isPlaying"
                animation="property: scale; from: 0 0 0; to: 1 1 1; dur: 750; easing: linear; startEvents: drawblade"
                scale="0.001 0.001 0.001">
                <a-entity
                  class="blade blade{{ hand }}"
                  {% if hand === 'right' %}data-saber-particles{% endif %}
                  geometry="primitive: box; height: 0.9; depth: 0.02; width: 0.02"
                  material="shader: flat; color: #fff"
                  raycastable-game
                  position="0 -0.55 0"></a-entity>
                <a-entity
                  class="saberglow"
                  obj-model="obj: #saberGlowObj"
                  material="shader: flat; color: {{ bladeColor }}; blending: additive; opacity: 0.08"
                  position="0 -0.55 0"></a-entity>
              </a-entity>
              <a-entity
                class="saberHandle"
                geometry="primitive: box; height: 0.2; depth: 0.025; width: 0.025"
                material="shader: flat; color: #151515">
                <a-entity
                  class="highlightTop"
                  geometry="primitive: box; height: 0.18; depth: 0.005; width: 0.005"
                  material="shader: flat; color: #FAFAFA"
                  position="0 0 0.0125"></a-entity>
                <a-entity
                  class="highlightBottom"
                  geometry="primitive: box; height: 0.18; depth: 0.005; width: 0.005"
                  material="shader: flat; color: #FAFAFA"
                  position="0 0 -0.0125"></a-entity>
              </a-entity>
            </a-entity>

            <a-entity
              class="fakeGlow"
              fake-glow="color: {{ hand == 'right' and COLORS.NEON_BRIGHTBLUE or COLORS.NEON_BRIGHTRED }}"
              position="0 0.01 0"
              rotation="90 0 0"
              bind__visible="!isPlaying">
            </a-entity>
          </a-entity>

          <a-entity
            id="{{ hand }}CursorMesh"
            mixin="cursorMesh"
            bind__cursor-mesh="active: {{ hand }}RaycasterActive && !isPlaying"
            cursor-mesh="cursorEl: #{{ hand }}Hand"
            material="color: {{ beamColor }}"
            scale="1.3 1.3 1.3"></a-entity>
        {% endmacro %}

        {{ saber('right', 'left', '#256c43', 'cyan') }}
        {{ saber('left', 'right', '#850e3e', 'pink') }}
      </a-entity>
      </a-entity>

      <a-entity
        id="stepback"
        obj-model="obj: #stepbackObj"
        position="0 1.6 -1.55"
        material="shader: flat; src: #atlasImg; transparent: true; opacity: 0"></a-entity>

      {% if not IS_PRODUCTION %}
        <a-entity
          id="mouseCursor"
          bind__raycaster="enabled: !inVR"
          mixin="raycaster"
          cursor="rayOrigin: mouse"
          raycaster="objects: [raycastable]"></a-entity>
        <a-entity
          id="mouseCursorMesh"
          mixin="cursorMesh"
          cursor-mesh="cursorEl: #mouseCursor"
          bind__cursor-mesh="active: menuActive"></a-entity>
      {% endif %}
    </a-scene>

    <img id="tutorial2d" data-src="assets/img/tutorial2d.png">
    <h1 id="loadingText2d" style="position: fixed; bottom: 10px; left: 0; right: 0; margin: 0 auto; text-transform: uppercase; color: #FAFAFA; text-align: center; font-family: monospace">Loading...</h1>
    <script>
      // Defer image so loading image loads first.
      const tutorial2d = document.getElementById('tutorial2d');
      tutorial2d.src = tutorial2d.dataset.src;
    </script>
    <a id="vrButton" href="#" title="Enter VR / Fullscreen"></a>

    {% include './templates/ga.html' %}
  </body>
</html>
