github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/shell.html (about)

     1  <!doctype html>
     2  <html lang="en-us">
     3    <head>
     4      <meta charset="utf-8">
     5      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     6  
     7      <title>raylib web game</title>
     8  
     9      <meta name="title" content="raylib web game">
    10      <meta name="description" content="New raylib web videogame, developed using raylib videogames library">
    11      <meta name="keywords" content="raylib, games, html5, programming, C, C++, library, learn, videogames">
    12      <meta name="viewport" content="width=device-width">
    13  
    14      <!-- Open Graph metatags for sharing -->
    15      <meta property="og:title" content="raylib web game">
    16      <meta property="og:image:type" content="image/png">
    17      <meta property="og:image" content="https://www.raylib.com/common/img/raylib_logo.png">
    18      <meta property="og:site_name" content="raylib.com">
    19      <meta property="og:url" content="https://www.raylib.com/games.html">
    20      <meta property="og:description" content="New raylib web videogame, developed using raylib videogames library">
    21  
    22      <!-- Twitter metatags for sharing -->
    23      <meta name="twitter:card" content="summary">
    24      <meta name="twitter:site" content="@raysan5">
    25      <meta name="twitter:title" content="raylib web game">
    26      <meta name="twitter:image" content="https://www.raylib.com/common/raylib_logo.png">
    27      <meta name="twitter:url" content="https://www.raylib.com/games.html">
    28      <meta name="twitter:description" content="New raylib web game, developed using raylib videogames library">
    29  
    30      <!-- Favicon -->
    31      <link rel="shortcut icon" href="https://www.raylib.com/favicon.ico">
    32  
    33      <style>
    34        body {
    35          font-family: arial;
    36          margin: 0;
    37          padding: none;
    38        }
    39  
    40        #header {
    41          width: 100%;
    42          height: 80px;
    43          background-color: #888888;
    44        }
    45  
    46        /* NOTE: raylib logo is embedded in the page as base64 png image */
    47        #logo {
    48          width:64px;
    49          height:64px;
    50          float:left;
    51          position:relative;
    52          margin:10px;
    53          background-image:url('data:image/png;base64,\
    54  iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADs\
    55  MAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAA7JJREFUaEPtk0FyWzEMQ+37X7fZhxX4\
    56  YY3AD1OKF1nkzTRlSBCCLeVBnvl/AUdaELOunPno1kts1kixdtEZKVs+xIxebBkZsVknn/L5nFGDLR8T4zVC9fX19S/+tTFijr\
    57  YK4jUjbPUtqBHpnEE6PkZD7jQZV8n5Recw1XQKciZuPaEtR6UjNs5ENVGMsBVqpPtER0ZMOhpyp8m4YL4OjD9yxsyZxnQycfMJ\
    58  ETNSzsRE1+dihK3YMiJmpHTW3xpmXPC6BXlCHfqnBlsjY5hxf/6EVEOM2BTEi0fYCX4ONSI6Kq3Blg/prIOMq2CsRur4KQ0x64\
    59  SdjOufEDEdHZGOhmz5RDHCVqhRuQ86YsVskbc+GXchLiHnFyYH+UigQDVGnImbT8hwFkgLg2qiM8JO6Ylx1FNLa3DmYwqCTsZd\
    60  4BPqGJG7MwKzpeiWKTKxXkLMVE3MSOmsdwxLH6Rd/wCCLSNDx6djeKfJuArGeoYamRHpaEjnCBYZVy8hZqo2GI36qPjsiOiMsB\
    61  XGcev4Mx9TLGTchbgEjN/uz6jGrBvDjg+LTNx8Qp2CbG2xMKgmOiPslJ4Yxx+eSnSkzlosZNwFPiHl7FRTkLNRJm4+IeVM0ymI\
    62  H42wE/wcKalQI4MRl4EW3p6VcRWMua8F6WjIlqZDxvVPiHQ6CjVbYkV9ohhhp/Rk1wiYgpyJ78i4CsZbjkb8Qx+ihvzu3RPaKo\
    63  gZkY6GlEeMsKdPSOFIC8VoOusg44L5c+T8ouOoGhWbdWJ8tMi4egkxo4hoh2yNTGf3iIyr5Lyic4bRENXo+lvDjAt4C1Hk/OKt\
    64  UaAj0+n4dMSZ2D+hrYJsaYh2SClG2jV9kJKKzhlGQ1SsW299Mq6C8dYZHTExo8fzieI5ivipYnYy7nwJqGKmOYyRwfiUBXITfh\
    65  5qSHRGWEkfqJqURgvsdHyWYv7Ko8DnYYegk3EB00cxprdrJRzFd7YQzawu8L1GMTYS/KpPaAFTkIn1EmJmspJSs5xBzSyGhlkB\
    66  mlxfNFiP5mw4wlbMh4F5Ddxp5jNINBdCEz9zPOC1zD7Q0HBdmXndwv0TMtydEdzlWJT4VZ8Qt9Qn4/onxMIwa5ZYGJU5yufBiC\
    67  jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaBBfOTCGHM2aEbZi1+gO\
    68  1XTWVXMnzrhAn5DSOZVsiQlHnSITKzGj6DeTcZWc/3oy7h9//PF4PL4BlvsWrb6RE+oAAAAASUVORK5CYII=');
    69        }
    70  
    71        .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
    72        div.emscripten { text-align: center; }
    73        div.emscripten_border { border: 1px solid black; }
    74  
    75        /* NOTE: Canvas *must not* have any border or padding, or mouse coords will be wrong */
    76        canvas.emscripten {
    77          border: 0px none;
    78          background: black;
    79          width: 100%;
    80        }
    81  
    82        .spinner {
    83          height: 30px;
    84          width: 30px;
    85          margin: 0;
    86          margin-top: 20px;
    87          margin-left: 20px;
    88          display: inline-block;
    89          vertical-align: top;
    90          -webkit-animation: rotation .8s linear infinite;
    91          -moz-animation: rotation .8s linear infinite;
    92          -o-animation: rotation .8s linear infinite;
    93          animation: rotation 0.8s linear infinite;
    94          border-left: 5px solid black;
    95          border-right: 5px solid black;
    96          border-bottom: 5px solid black;
    97          border-top: 5px solid red;
    98          border-radius: 100%;
    99          background-color: rgb(245, 245, 245);
   100        }
   101        @-webkit-keyframes rotation {
   102          from {-webkit-transform: rotate(0deg);}
   103          to {-webkit-transform: rotate(360deg);}
   104        }
   105        @-moz-keyframes rotation {
   106          from {-moz-transform: rotate(0deg);}
   107          to {-moz-transform: rotate(360deg);}
   108        }
   109        @-o-keyframes rotation {
   110          from {-o-transform: rotate(0deg);}
   111          to {-o-transform: rotate(360deg);}
   112        }
   113        @keyframes rotation {
   114          from {transform: rotate(0deg);}
   115          to {transform: rotate(360deg);}
   116        }
   117  
   118        #status {
   119          display: inline-block;
   120          vertical-align: top;
   121          margin-top: 30px;
   122          margin-left: 20px;
   123          font-weight: bold;
   124          color: rgb(40, 40, 40);
   125        }
   126  
   127        #progress {
   128          height: 0px;
   129          width: 0px;
   130        }
   131  
   132        #controls {
   133          display: inline-block;
   134          float: right;
   135          vertical-align: top;
   136          margin-top: 15px;
   137          margin-right: 20px;
   138        }
   139  
   140        #output {
   141          width: 100%;
   142          height: 140px;
   143          margin: 0 auto;
   144          margin-top: 10px;
   145          display: block;
   146          background-color: black;
   147          color: rgb(37, 174, 38);
   148          font-family: 'Lucida Console', Monaco, monospace;
   149          outline: none;
   150        }
   151  
   152        input[type=button] {
   153          background-color: lightgray;
   154          border: 4px solid darkgray;
   155          color: black;
   156          text-decoration: none;
   157          cursor: pointer;
   158          width: 140px;
   159          height: 50px;
   160        }
   161  
   162        input[type=button]:hover {
   163          background-color: #f5f5f5ff;
   164          border-color: black;
   165        }
   166      </style>
   167    </head>
   168    <body>
   169      <div id="header">
   170          <a id="logo" href="https://www.raylib.com"></a>
   171  
   172          <div class="spinner" id='spinner'></div>
   173          <div class="emscripten" id="status">Downloading...</div>
   174  
   175          <span id='controls'>
   176            <span><input type="button" value="🖵 FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
   177            <span><input type="button" id="btn-audio" value="🔇 SUSPEND" onclick="toggleAudio()"></span>
   178          </span>
   179  
   180          <div class="emscripten">
   181            <progress value="0" max="100" id="progress" hidden=1></progress>
   182          </div>
   183      </div>
   184  
   185      <div class="emscripten_border">
   186        <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
   187      </div>
   188  
   189      <textarea id="output" rows="8"></textarea>
   190  
   191      <script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
   192      <script type='text/javascript'>
   193          function saveFileFromMEMFSToDisk(memoryFSname, localFSname)     // This can be called by C/C++ code
   194          {
   195              var isSafari = false; // Not supported, navigator.userAgent access is being restricted
   196              //var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
   197              var data = FS.readFile(memoryFSname);
   198              var blob;
   199  
   200              if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" });
   201              else blob = new Blob([data.buffer], { type: "application/octet-binary" });
   202  
   203              // NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
   204              // in Settings/Advanced/Downloads section you have a setting:
   205              // 'Ask where to save each file before downloading' - which you can set true/false.
   206              // If you enable this setting it would always ask you and bring the SaveAsDialog
   207              saveAs(blob, localFSname);
   208          }
   209      </script>
   210      <script type='text/javascript'>
   211          var statusElement = document.querySelector('#status');
   212          var progressElement = document.querySelector('#progress');
   213          var spinnerElement = document.querySelector('#spinner');
   214          var Module = {
   215              preRun: [],
   216              postRun: [],
   217              print: (function() {
   218                  var element = document.querySelector('#output');
   219  
   220                  if (element) element.value = '';    // Clear browser cache
   221  
   222                  return function(text) {
   223                      if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
   224                      // These replacements are necessary if you render to raw HTML
   225                      //text = text.replace(/&/g, "&amp;");
   226                      //text = text.replace(/</g, "&lt;");
   227                      //text = text.replace(/>/g, "&gt;");
   228                      //text = text.replace('\n', '<br>', 'g');
   229                      console.log(text);
   230  
   231                      if (element) {
   232                          element.value += text + "\n";
   233                          element.scrollTop = element.scrollHeight; // focus on bottom
   234                      }
   235                  };
   236              })(),
   237              printErr: function(text) {
   238                  if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
   239  
   240                  console.error(text);
   241              },
   242              canvas: (function() {
   243                  var canvas = document.querySelector('#canvas');
   244  
   245                  // As a default initial behavior, pop up an alert when webgl context is lost.
   246                  // To make your application robust, you may want to override this behavior before shipping!
   247                  // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
   248                  canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
   249  
   250                  return canvas;
   251              })(),
   252              setStatus: function(text) {
   253                  if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
   254                  if (text === Module.setStatus.last.text) return;
   255  
   256                  var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
   257                  var now = Date.now();
   258  
   259                  if (m && now - Module.setStatus.last.time < 30) return; // If this is a progress update, skip it if too soon
   260  
   261                  Module.setStatus.last.time = now;
   262                  Module.setStatus.last.text = text;
   263  
   264                  if (m) {
   265                      text = m[1];
   266                      progressElement.value = parseInt(m[2])*100;
   267                      progressElement.max = parseInt(m[4])*100;
   268                      progressElement.hidden = true;
   269                      spinnerElement.hidden = false;
   270                  } else {
   271                      progressElement.value = null;
   272                      progressElement.max = null;
   273                      progressElement.hidden = true;
   274                      if (!text) spinnerElement.style.display = 'none';
   275                  }
   276  
   277                  statusElement.innerHTML = text;
   278              },
   279              totalDependencies: 0,
   280              monitorRunDependencies: function(left) {
   281                  this.totalDependencies = Math.max(this.totalDependencies, left);
   282                  Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
   283              },
   284              //noInitialRun: true
   285          };
   286  
   287          Module.setStatus('Downloading...');
   288  
   289          window.onerror = function() {
   290              Module.setStatus('Exception thrown, see JavaScript console');
   291              spinnerElement.style.display = 'none';
   292              Module.setStatus = function(text) { if (text) Module.printErr('[post-exception status] ' + text); };
   293          };
   294      </script>
   295  
   296      <!-- REF: https://developers.google.com/web/updates/2018/11/web-audio-autoplay -->
   297      <script type='text/javascript'>
   298          var audioBtn = document.querySelector('#btn-audio');
   299  
   300          // An array of all contexts to resume on the page
   301          const audioContexList = [];
   302          (function() {
   303              // A proxy object to intercept AudioContexts and
   304              // add them to the array for tracking and resuming later
   305              self.AudioContext = new Proxy(self.AudioContext, {
   306                  construct(target, args) {
   307                      const result = new target(...args);
   308                      audioContexList.push(result);
   309                      if (result.state == "suspended") audioBtn.value = "🔈 RESUME";
   310                      return result;
   311                  }
   312              });
   313          })();
   314  
   315          function toggleAudio() {
   316              var resumed = false;
   317              audioContexList.forEach(ctx => {
   318                  if (ctx.state == "suspended") { ctx.resume(); resumed = true; }
   319                  else if (ctx.state == "running") ctx.suspend();
   320              });
   321  
   322              if (resumed) audioBtn.value = "🔇 SUSPEND";
   323              else audioBtn.value = "🔈 RESUME";
   324          }
   325      </script>
   326      {{{ SCRIPT }}}
   327    </body>
   328  </html>