Browse Source

Playground - CSS theme updated

Temechon 8 years ago
parent
commit
c63ed1dce2

File diff suppressed because it is too large
+ 0 - 1109
Playground/bootstrap/css/bootstrap-responsive.css


File diff suppressed because it is too large
+ 0 - 9
Playground/bootstrap/css/bootstrap-responsive.min.css


File diff suppressed because it is too large
+ 0 - 6167
Playground/bootstrap/css/bootstrap.css


File diff suppressed because it is too large
+ 0 - 9
Playground/bootstrap/css/bootstrap.min.css


BIN
Playground/bootstrap/img/glyphicons-halflings-white.png


BIN
Playground/bootstrap/img/glyphicons-halflings.png


File diff suppressed because it is too large
+ 0 - 2280
Playground/bootstrap/js/bootstrap.js


File diff suppressed because it is too large
+ 0 - 6
Playground/bootstrap/js/bootstrap.min.js


+ 362 - 0
Playground/css/index.css

@@ -0,0 +1,362 @@
+@import url("https://fonts.googleapis.com/css?family=Montserrat:300,400");
+@import url("https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css");
+html,
+body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    overflow: hidden;
+    font-family: sans-serif;
+}
+.wrapper {
+    height: calc(100% - 60px - 30px); /* nvabar top and bottom*/
+    width: 100%;
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-direction: row;
+    flex-direction: row;
+}
+.wrapper .gutter {
+    background-color: #f7f7f7;
+    background-repeat: no-repeat;
+    background-position: 50%;
+}
+.wrapper .gutter:hover {
+    cursor: ew-resize;
+}
+.wrapper .gutter.gutter-vertical {
+    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=");
+}
+.wrapper .gutter.gutter-horizontal {
+    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
+}
+.wrapper #jsEditor {
+    height: 100%;
+}
+.wrapper #canvasZone {
+    height: 100%;
+}
+#renderCanvas {
+    width: 100%;
+    height: 100%;
+    touch-action: none;
+}
+#fpsLabel {
+    position: absolute;
+    right: 10px;
+    top: 80px;
+    cursor: default;
+    z-index:10;
+    background-color: #7283a0;
+    color:white;
+    padding:5px;
+    border-radius: 3px;
+    font-family: 'Montserrat'
+}
+.navbar {
+    height: 60px;
+    width: 100%;
+    background-color: #efefef;
+    font-family: "Montserrat";
+    font-weight: 400;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    position: relative;
+}
+.navbar .title {
+    height: 60px;
+    padding-left: 10px;
+    line-height: 60px;
+    color: #15A4FA;
+    display: inline-block;
+}
+.navbar .version {
+    height: 60px;
+    line-height: 60px;
+    display: inline-block;
+    color: #7283a0;
+    margin-right: 20px;
+}
+.navbar .category {
+    margin: 0 15px 0 15px;
+    display: inline-block;
+}
+.navbar .category.right {
+    position: absolute;
+    right: 0;
+    top: 15px;
+}
+.navbar .button {
+    display: inline-block;
+    height: 30px;
+    line-height: 30px;
+    color: white;
+    background-color: #7283a0;
+    margin: 0 2px 0 2px;
+    padding: 0 10px 0 10px;
+    font-size: 0.85em;
+    border-radius: 3px;
+}
+.navbar .button i {
+    margin-left: 10px;
+}
+.navbar .button:hover {
+    cursor: pointer;
+    background-color: #15A4FA;
+}
+.navbar .button.run {
+    height: 40px;
+    line-height: 40px;
+    background-color: #15A4FA;
+    font-size: 1.0em;
+}
+.navbar .select {
+    position: relative;
+}
+.navbar .select:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f078";
+}
+.navbar .select .toDisplay {
+    border: 1px solid #7283a0;
+    border-radius: 5px;
+    position: absolute;
+    z-index: 10;
+    left: 0;
+    top: 32px;
+    min-width: 100%;
+    display: none;
+}
+.navbar .select .toDisplay .option {
+    font-size: 0.9em;
+    height: 35px;
+    line-height: 35px;
+    padding: 0px 5px 0px 5px;
+    background-color: white;
+    text-align: center;
+    color: #15A4FA;
+}
+.navbar .select .toDisplay .option:hover {
+    cursor: pointer;
+    background-color: #d9d9d9;
+}
+
+.navbar .select .toDisplayBig {
+    border: 1px solid #7283a0;
+    border-radius: 5px;
+    position: absolute;
+    z-index: 10;
+    top: 32px;
+    width:550px;
+    max-height:350px;
+    background-color: white;
+    right:0;
+    position:absolute;
+    font-size:0.8em;
+    display: none;
+    
+}
+.navbar .select .toDisplayBig ul {
+    column-count: 3;        
+    padding:0;
+    margin:0;
+}
+
+.navbar .select .toDisplayBig ul li {
+    padding:0 5px 0 5px;
+}
+
+.navbar .select .toDisplayBig ul li:hover {
+    cursor: pointer;
+    background-color: #d9d9d9;
+}
+.navbar .select .toDisplayBig a {
+    text-decoration: none;
+    color: #15A4FA;
+}
+
+
+
+.navbar .check:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f14a";
+}
+.navbar .check.uncheck {
+    background-color: #8290aa;
+}
+.navbar .check.uncheck:after {
+    font-family: 'FontAwesome', sans-serif;
+    content: "\00a0 \00a0 \00a0 \f096";
+}
+#errorZone {
+    display:none;
+    position: absolute;
+    width: 50%;
+    left: 25%;
+    bottom: 40px;
+    background-color: #C73228;
+    padding:20px;
+    border-radius: 5px;
+    color:white;
+    font-family: 'Inconsolata';
+}
+#errorZone button {
+    position:absolute;
+    top : 3px;
+    right: 10px;
+    padding: 0;
+    cursor: pointer;
+    background: transparent;
+    border: 0;
+    -webkit-appearance: none;
+    color: #000;
+    text-shadow: 0 1px 0 #fff;
+    opacity: .4;
+    font-size: 1.8em;
+}
+
+/* Navbar bottom */
+
+.navbarBottom {
+    height:30px;
+    width:100%;
+    background-color: #efefef;
+    line-height:30px;
+    position:relative;
+    font-family: 'Montserrat';
+}
+
+.navbarBottom #statusBar {
+    line-height:30px;
+    color: #999;
+    font-family: 'Inconsolata';
+    padding-left:20px;
+}
+
+
+.navbarBottom .links {
+    position:absolute;
+    right : 0;
+    top:-1px;
+    height:30px;
+    padding-right:20px;
+}
+.navbarBottom .links .link{
+    height:30px;
+    display:inline-block;
+    color:#999;
+    padding: 0 10px 0 10px;
+    margin : 0 5px 0 5px;
+    font-size:0.8em;
+}
+.navbarBottom .links .link:hover{
+    color:#999;
+    background-color:#333;
+}
+.navbarBottom .links .link a{
+    text-decoration: none;
+    color:#999;
+    display: inline-block;
+}
+
+/* MONACO */
+
+.monaco-editor .container:before,
+.monaco-editor .row:before {
+    content: "";
+    display: inherit;
+}
+.monaco-editor .container:after,
+.monaco-editor .row:after {
+    clear: inherit;
+}
+.monaco-editor .container {
+    width: auto;
+    margin: inherit;
+    padding: inherit;
+}
+.monaco-editor .close {
+    float: none;
+    font-size: inherit;
+    font-weight: inherit;
+    line-height: inherit;
+    color: inherit;
+    text-shadow: inherit;
+    opacity: inherit;
+    filter: inherit;
+}
+.monaco-editor .row {
+    margin: inherit;
+}
+.monaco-editor .invisible {
+    visibility: visible;
+}
+.monaco-editor .view-lines {
+    font-family: 'Inconsolata' !important;
+}
+/* Save form & co */
+
+.save-message {
+    display: none;
+    position:absolute;
+    top:60px; /* navbar top */
+    width: 100%;
+    z-index:30;
+    text-align: center;
+    color: #7283a0;
+    font-size: 0.8em;
+    line-height: 2em;
+    background-color: rgba(239, 239, 239, 0.9);
+    cursor:pointer;
+}
+.save-layer {
+    display: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(120, 120, 120, .5);
+    text-align: center;
+}
+.save-layer .save-form {
+    position: absolute;
+    top: 150px;
+    left: calc(50% - 205px);
+    width: 410px;
+    height: 390px;
+    padding-top: 15px;
+    -webkit-border-radius: 6px;
+    -moz-border-radius: 6px;
+    border-radius: 6px;
+    background-color: rgba(27, 27, 27, 0.75);
+    /*#1b1b1b;*/
+    
+    background-image: -moz-linear-gradient(top, rgba(34, 34, 34, .75), rgba(17, 17, 17, .75));
+    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(34, 34, 34, .75)), to(rgba(17, 17, 17, .75)));
+    background-image: -webkit-linear-gradient(top, rgba(34, 34, 34, .75), rgba(17, 17, 17, .75));
+    background-image: -o-linear-gradient(top, rgba(34, 34, 34, .75), rgba(17, 17, 17, .75));
+    background-image: linear-gradient(to bottom, rgba(34, 34, 34, .75), rgba(17, 17, 17, .75));
+    background-repeat: repeat-x;
+    border-color: #252525;
+    color: white;
+    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-size: 14px;
+}
+.save-layer .save-form .separator {
+    width: 350px;
+    border-bottom: 1px solid #999;
+    margin: auto;
+    margin-top: -6px;
+    margin-bottom: 10px;
+}
+.save-layer .save-form .save-form-buttons {
+    margin-top: 10px;
+}
+.save-layer .save-form input,
+.save-layer .save-form textarea {
+    width: 350px;
+}

File diff suppressed because it is too large
+ 0 - 1
Playground/hand.minified-1.2.js


+ 0 - 188
Playground/index.css

@@ -1,188 +0,0 @@
-html, body {
-    overflow: hidden;
-    width: 100%;
-    height: 100%;
-    background-color: #272822;
-}
-
-x-splitbox {
-    position: absolute;
-    left: 0px;
-    top: 50px;
-    width: 100%;
-    bottom: 40px;
-    height: auto;
-}
-
-    x-splitbox > [splitter]:after {
-        display: none;
-    }
-
-
-#jsEditor {
-    min-width: 250px;
-}
-
-#canvasZone {
-    min-width: 250px;
-    height: 100%;
-}
-
-#renderCanvas {
-    width: 100%;
-    height: 100%;
-    touch-action: none;
-}
-
-ul#scriptsList {
-    overflow-y: auto;
-    height: 600px;
-    -webkit-column-count: 3;
-    -moz-column-count: 3;
-    column-count: 3;
-    padding: 10px
-}
-
-#fpsLabel {
-    position: absolute;
-    right: 10px;
-    top: 70px;
-    cursor: default;
-}
-
-#topbar {
-    padding: 5px;
-}
-
-.navbar .brand {
-    margin-left: 0px;
-}
-
-#errorZone {
-    position: absolute;
-    width: 50%;
-    left: 25%;
-    bottom: 40px;
-}
-
-#statusBar {
-    padding: 10px 15px 10px;
-    color: #999;
-}
-
-@media (max-width: 800px) {
-    .desktopOnly {
-        display: none !important;
-    }
-}
-
-@media (max-width: 1100px) {
-    .largeOnly {
-        display: none !important;
-    }
-}
-
-@media (max-width: 550px) {
-    .btn-group > .btn, .btn-group > .dropdown-menu, .btn-group > .popover {
-        font-size: 12px !important;
-    }
-}
-
-/* MONACO */
-.monaco-editor .container:before, .monaco-editor .row:before {
-    content: "";
-    display: inherit;
-}
-
-.monaco-editor .container:after, .monaco-editor .row:after {
-    clear: inherit;
-}
-
-.monaco-editor .container {
-    width: auto;
-    margin: inherit;
-    padding: inherit;
-}
-
-.monaco-editor .close {
-    float: none;
-    font-size: inherit;
-    font-weight: inherit;
-    line-height: inherit;
-    color: inherit;
-    text-shadow: inherit;
-    opacity: inherit;
-    filter: inherit;
-}
-
-.monaco-editor .row {
-    margin: inherit;
-}
-
-.monaco-editor .invisible {
-    visibility: visible;
-}
-
-
-/* Save form & co */
-
-.save-message {
-    display: none;
-    float: left;
-    width: 100%;
-    background-color: rgba(0,0,0,.5);
-    text-align: center;
-    color: white;
-    font-size: 1.1em;
-    line-height: 2em;
-}
-
-.save-layer {
-    display: none;
-    position: absolute;
-    top: 0;
-    left: 0;
-
-    width: 100%;
-    height: 100%;
-
-    background-color: rgba(120,120,120,.5);
-    text-align: center;
-}
-.save-layer .save-form {
-    position: absolute;
-    top: 150px;
-    left: calc(50% - 205px);
-
-    width: 410px;
-    height: 390px;
-    padding-top: 15px;
-    -webkit-border-radius: 6px;
-    -moz-border-radius: 6px;
-    border-radius: 6px;
-
-    background-color: rgba(27,27,27,0.75);/*#1b1b1b;*/
-    background-image: -moz-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: -webkit-gradient(linear,0 0,0 100%,from(rgba(34,34,34,.75)),to(rgba(17,17,17,.75)));
-    background-image: -webkit-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: -o-linear-gradient(top,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-image: linear-gradient(to bottom,rgba(34,34,34,.75),rgba(17,17,17,.75));
-    background-repeat: repeat-x;
-    border-color: #252525;
-    color: white;
-    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
-    font-size: 14px;
-}
-.save-layer .save-form .separator {
-    width: 350px;
-    border-bottom: 1px solid #999;
-    margin: auto;
-    margin-top: -6px;
-    margin-bottom: 10px;
-}
-.save-layer .save-form .save-form-buttons {
-    margin-top: 10px;
-}
-.save-layer .save-form input, .save-layer .save-form textarea {
-    width: 350px;
-}

+ 101 - 82
Playground/index.html

@@ -1,28 +1,27 @@
 <!DOCTYPE html>
 <html>
+
 <head>
     <title>Babylon.js Playground</title>
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
-    <!--x-tag-->
-    <script src="xtag.min.js"></script>
-    <script src="splitbox.js"></script>
-    <link href="splitbox.css" rel="stylesheet" />
+    <!--<script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>-->
+    <!--For canvas/code separator-->
+    <script src="js/libs/split.js"></script>
+
+    <!--<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>-->
     <!-- jszip -->
-    <script src="jszip.min.js"></script>
-    <script src="fileSaver.js"></script>
-    <!-- Bootstrap -->
-    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!--Monaco-->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
+    <!--<script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>-->
     <!--<script src="../babylon.js"></script>-->
     <script src="https://babylonjs.azurewebsites.net/babylon.js"></script>
     <script src="https://babylonjs.azurewebsites.net/babylon.canvas2d.js"></script>
     <script src="https://babylonjs.azurewebsites.net/babylon.inspector.bundle.js"></script>
-    
-    <script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.min.js"></script>
+
+    <!--<script src="https://babylonjs.azurewebsites.net/lib/babylon.fireMaterial.min.js"></script>
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.waterMaterial.min.js"></script>
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.lavaMaterial.min.js"></script>
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.normalMaterial.min.js"></script>
@@ -49,62 +48,81 @@
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.glTFFileLoader.js"></script>
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.objFileLoader.js"></script>
     <script src="https://babylonjs.azurewebsites.net/lib/babylon.stlFileLoader.js"></script>
-    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <link href="index.css" rel="stylesheet" />
+
+    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>-->
+    <link href="css/index.css" rel="stylesheet" />
 </head>
+
 <body>
-    <div class="navbar navbar-inverse navbar-fixed-top">
-        <div class="navbar-inner" id="topbar">
-            <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
-            <div class="btn-group">
-                <button class="btn" id="runButton">Run</button>
-                <button class="btn" id="saveButton">Save</button>
-                <button class="btn desktopOnly" id="zipButton">Get .zip</button>
-                <button class="btn desktopOnly" id="newButton">New</button>
-                <button class="btn desktopOnly" id="clearButton">Clear</button>
+    <div class="navbar">
+        <div class="title">
+            Babylon.js Playground
+        </div>
+        <div class="version" id="mainTitle">
+            v3.0-alpha
+        </div>
+
+        <div class="category">
+            <div class="button run" id="runButton">Run <i class="fa fa-play" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button" id="newButton">New<i class="fa fa-file" aria-hidden="true"></i></div>
+            <div class="button" id="clearButton">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
+        </div>
+
+        <div class="category">
+            <div class="button" id="saveButton">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
+            <div class="button" id="zipButton">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
+        </div>
+
+
+        <div class="category">
+            <div class="button select"><span id="currentFontSize">Font: 14</span>
+                <div class="toDisplay">
+                    <div class="option" onclick="setFontSize(12);">12</div>
+                    <div class="option" onclick="setFontSize(14);">14</div>
+                    <div class="option" onclick="setFontSize(16);">16</div>
+                    <div class="option" onclick="setFontSize(18);">18</div>
+                    <div class="option" onclick="setFontSize(20);">20</div>
+                    <div class="option" onclick="setFontSize(22);">22</div>
+                </div>
             </div>
-            <div class="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentFontSize">Font: 12</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="sizeList">
-                    <li><a href="#" onclick="setFontSize(12);">12</a></li>
-                    <li><a href="#" onclick="setFontSize(14);">14</a></li>
-                    <li><a href="#" onclick="setFontSize(16);">16</a></li>
-                    <li><a href="#" onclick="setFontSize(18);">18</a></li>
-                    <li><a href="#" onclick="setFontSize(20);">20</a></li>
-                    <li><a href="#" onclick="setFontSize(22);">22</a></li>
-                </ul>
+            <div class="button select">Theme
+                <div class="toDisplay">
+                    <div class="option">Dark</div>
+                    <div class="option">Light</div>
+                </div>
             </div>
-            <div class="btn-group desktopOnly">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentVersion">Version: Latest</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="versionList">
-                    <li><a href="#" onclick="setVersion('latest');">Latest</a></li>
-                    <li><a href="#" onclick="setVersion('2.5');">2.5</a></li>
-                </ul>
-            </div>            
-            <div class="btn-group">
-                <label class="btn btn-sm active">
-                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
-                </label>
-                <button class="btn btn-sm" id="metadataButton">+Meta data</button>
-                <button class="btn btn-sm" id="editorButton">-Editor</button>
-                <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+
+
+            <div class="button select">Settings
+                <div class="toDisplay">
+                    <div class="option" id='safemodeToggle'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
+                    <div class="option checked" id="editorButton">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="fullscreenButton">Fullscreen</div>
+                    <div class="option" id="metadataButton">Metadata</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <button class="btn" id="fullscreenButton">Fullscreen</button>
+
+            <div class="button check uncheck" id="debugButton">Debug layer</div>
+        </div>
+
+
+        <div class="category right">
+            <div class="button select"><span id="currentVersion">Version: Latest</span>
+                <div class="toDisplay">
+                    <div class="option" onclick="setVersion('latest');">Latest</div>
+                    <div class="option" onclick="setVersion('2.5');">2.5</div>
+                </div>
             </div>
-            <div class="btn-group pull-right">
-                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                    <span id="currentScript">Predefined scripts</span>
-                    <span class="caret"></span>
-                </a>
-                <ul class="dropdown-menu" id="scriptsList"></ul>
+            <div class="button select"> <span id="currentScript">Scenes</span>
+                <div class="toDisplayBig">
+                    <ul id="scriptsList">
+                    </ul>
+                </div>
             </div>
         </div>
         <div class="save-message" id="saveMessage">
@@ -112,31 +130,26 @@
         </div>
     </div>
 
-    <x-splitbox>
+    <div class="wrapper">
         <div id="jsEditor"></div>
-        <div splitter></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-    </x-splitbox>
+    </div>
 
     <span class="label" id="fpsLabel">FPS</span>
 
     <div id="errorZone">
     </div>
 
-    <div class="navbar navbar-inverse navbar-fixed-bottom">
-        <div class="navbar-inner">
-            <ul class="nav pull-left">
-                <li id="statusBar"></li>
-            </ul>
-            <ul class="nav pull-right">
-                <li><a href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></li>
-                <li><a href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></li>
-                <li><a href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></li>
-                <li><a href="https://doc.babylonjs.com">Documentation</a></li>
-                <li><a href="https://doc.babylonjs.com/playground">Playground Search</a></li>
-            </ul>
+    <div class="navbarBottom">
+        <div id="statusBar"></div>
+        <div class="links">
+            <div class='link'> <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></div>
+            <div class='link'><a target='_new' href="https://babylonjs.azurewebsites.net/sandbox">Sandbox</a></div>
+            <div class='link'><a target='_new' href="https://github.com/BabylonJS/Babylon.js/wiki">Wiki</a></div>
+            <div class='link'><a target='_new' href="https://doc.babylonjs.com">Documentation</a></div>
+            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Playground Search</a></div>
         </div>
     </div>
 
@@ -159,7 +172,13 @@
     </div>
 
     <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap.min.js"></script>
-    <script src="index.js"></script>
+
+    <script>
+        Split(['#jsEditor', '#canvasZone']);
+    </script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/index.js"></script>
 </body>
-</html>
+
+</html>

+ 54 - 0
Playground/js/actions.js

@@ -0,0 +1,54 @@
+(function () {
+
+    var allSelect = document.querySelectorAll('.select');
+    var allToDisplay = document.querySelectorAll('.toDisplay');
+    var allToDisplayBig = document.querySelectorAll('.toDisplayBig');
+
+    // Remove displayed options
+    window.addEventListener('click', function () {
+        for (var a of allToDisplay) {
+            if (a.style.display == 'block') {
+                a.style.display = 'none';
+            }
+        }
+        for (var b of allToDisplayBig) {
+            if (b.style.display == 'block') {
+                b.style.display = 'none';
+            }
+        }
+    });
+
+    // Handle click on select elements
+    for (var s of allSelect) {
+        // Get child called to display
+        s.addEventListener('click', function (e) {
+            var toDisplay = this.querySelector('.toDisplay');
+            if (toDisplay) {
+                if (toDisplay.style.display == 'block') {
+                    toDisplay.style.display = 'none';
+                } else {
+                    toDisplay.style.display = 'block';
+                }
+            }
+            toDisplay = this.querySelector('.toDisplayBig');
+            if (toDisplay) {
+                if (toDisplay.style.display == 'block') {
+                    toDisplay.style.display = 'none';
+                } else {
+                    toDisplay.style.display = 'block';
+                }
+            }
+            e.preventDefault();
+            e.stopPropagation();
+        });
+    }
+
+    document.querySelector('#safemodeToggle').addEventListener('click', function () {
+        this.classList.toggle('checked');
+        if (this.classList.contains('checked')) {
+            this.innerHTML = 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>';
+        } else {
+            this.innerHTML = 'Safe mode <i class="fa fa-square-o" aria-hidden="true"></i>';
+        }
+    })
+})();

+ 34 - 31
Playground/index.js

@@ -13,7 +13,7 @@
             }
 
             document.getElementById("currentScript").innerHTML = "Custom";
-            document.getElementById('safemodeToggle').checked = true;
+            document.getElementById('safemodeToggle').classList.add('checked');
         });
 
         var snippetUrl = "https://babylonjs-api2.azurewebsites.net/snippets";
@@ -90,17 +90,15 @@
                         var ul = document.getElementById("scriptsList");
                         var index;
                         for (index = 0; index < scripts.length; index++) {
-                            var li = document.createElement("li");
+                            var option = document.createElement("li");
                             var a = document.createElement("a");
-
-                            li.class = "scriptsListEntry";
                             a.href = "#";
                             a.innerHTML = (index + 1) + " - " + scripts[index];
                             a.scriptLinkIndex = index + 1;
                             a.onclick = onScriptClick;
 
-                            li.appendChild(a);
-                            ul.appendChild(li);
+                            option.appendChild(a);
+                            ul.appendChild(option);
                         }
 
                         if (!location.hash) {
@@ -149,7 +147,7 @@
 
         var showError = function (errorMessage, errorEvent) {
             var errorContent =
-                '<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button><h4>Compilation error</h4>'
+                '<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button>';
             if (errorEvent) {
                 var regEx = /\(.+:(\d+):(\d+)\)\n/g;
 
@@ -165,10 +163,16 @@
 
             errorContent += errorMessage + '</div>';
 
+            document.getElementById("errorZone").style.display = 'block';
             document.getElementById("errorZone").innerHTML = errorContent;
+
+            // Close button error
+            document.getElementById("errorZone").querySelector('.close').addEventListener('click', function () {
+                document.getElementById("errorZone").style.display = 'none';
+            });
         }
 
-        var showNoMetadata = function() {
+        var showNoMetadata = function () {
             document.getElementById("saveFormTitle").value = '';
             document.getElementById("saveFormTitle").readOnly = false;
             document.getElementById("saveFormDescription").value = '';
@@ -179,9 +183,9 @@
             document.getElementById("saveMessage").style.display = "block";
             document.getElementById("metadataButton").style.display = "none";
         };
-        showNoMetadata();
+        // showNoMetadata();
 
-        var hideNoMetadata = function() {
+        var hideNoMetadata = function () {
             document.getElementById("saveFormTitle").readOnly = true;
             document.getElementById("saveFormDescription").readOnly = true;
             document.getElementById("saveFormTags").readOnly = true;
@@ -205,6 +209,7 @@
 
                 var canvas = document.getElementById("renderCanvas");
                 engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
+                document.getElementById("errorZone").style.display = 'none';
                 document.getElementById("errorZone").innerHTML = "";
                 document.getElementById("statusBar").innerHTML = "Loading assets...Please wait";
 
@@ -458,7 +463,7 @@
 
         // Fonts
         setFontSize = function (size) {
-            document.querySelector(".monaco-editor").style.fontSize = size + "px";
+            document.querySelector(".view-lines").style.fontSize = size + "px";
             document.getElementById("currentFontSize").innerHTML = "Font: " + size;
         };
 
@@ -473,14 +478,18 @@
             var editorButton = document.getElementById("editorButton");
             var scene = engine.scenes[0];
 
-            if (editorButton.innerHTML === "-Editor") {
-                editorButton.innerHTML = "+Editor";
+            // If the editor is present
+            if (editorButton.classList.contains('checked')) {
+                editorButton.classList.remove('checked');
                 document.getElementById("jsEditor").style.display = "none";
-                document.getElementById("canvasZone").style.flexBasis = "100%";
+                editorButton.innerHTML = 'Editor <i class="fa fa-square-o" aria-hidden="true"></i>';
+                document.getElementById("canvasZone").style.width = "100%";
             } else {
-                editorButton.innerHTML = "-Editor";
+                editorButton.classList.add('checked');
+                editorButton.innerHTML = 'Editor <i class="fa fa-check-square" aria-hidden="true"></i>';
                 document.getElementById("jsEditor").style.display = "block";
-                document.getElementById("canvasZone").style.flexBasis = undefined;
+                document.getElementById("canvasZone").style.width = "50%";
+                // document.getElementById("canvasZone").style.flexBasis = undefined;
             }
             engine.resize();
 
@@ -494,26 +503,20 @@
             var debugButton = document.getElementById("debugButton");
             var scene = engine.scenes[0];
 
-            if (debugButton.innerHTML === "+Debug layer") {
-                debugButton.innerHTML = "-Debug layer";
+            if (debugButton.classList.contains('uncheck')) {
+                debugButton.classList.remove('uncheck');
                 scene.debugLayer.show();
             } else {
-                debugButton.innerHTML = "+Debug layer";
+                debugButton.classList.add('uncheck');
                 scene.debugLayer.hide();
             }
         }
 
-        var toggleMetadata = function() {
+        var toggleMetadata = function () {
             var metadataButton = document.getElementById("metadataButton");
             var scene = engine.scenes[0];
-
-            if (metadataButton.innerHTML === "+Meta data") {
-                metadataButton.innerHTML = "-Meta data";
-                document.getElementById("saveLayer").style.display = "block";
-            } else {
-                metadataButton.innerHTML = "+Meta data";
-                document.getElementById("saveLayer").style.display = "none";
-            }
+            metadataButton.classList.add('checked');
+            document.getElementById("saveLayer").style.display = "block";
         }
 
         // UI
@@ -529,7 +532,7 @@
         //Navigation Overwrites
         var exitPrompt = function (e) {
             var safeToggle = document.getElementById("safemodeToggle");
-            if (safeToggle.checked) {
+            if (safeToggle.classList.contains('checked')) {
                 e = e || window.event;
                 var message =
                     'This page is asking you to confirm that you want to leave - data you have entered may not be saved.';
@@ -609,7 +612,7 @@
         document.getElementById("saveMessage").addEventListener("click", function () {
             document.getElementById("saveMessage").style.display = "none";
         });
-        document.getElementById("mainTitle").innerHTML = "Babylon.js v" + BABYLON.Engine.Version + " Playground";
+        document.getElementById("mainTitle").innerHTML = "v" + BABYLON.Engine.Version;
 
         var previousHash = "";
 
@@ -682,7 +685,7 @@
 
                         var hash = location.hash.substr(1);
                         currentSnippetToken = hash.split("#")[0];
-                        if(!hash.split("#")[1]) hash += "#0";
+                        if (!hash.split("#")[1]) hash += "#0";
 
 
                         xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));

Playground/fileSaver.js → Playground/js/libs/fileSaver.js


File diff suppressed because it is too large
+ 13 - 13
Playground/jszip.min.js


+ 587 - 0
Playground/js/libs/split.js

@@ -0,0 +1,587 @@
+// The programming goals of Split.js are to deliver readable, understandable and
+// maintainable code, while at the same time manually optimizing for tiny minified file size,
+// browser compatibility without additional requirements, graceful fallback (IE8 is supported)
+// and very few assumptions about the user's page layout.
+//
+// Make sure all browsers handle this JS library correctly with ES5.
+// More information here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
+'use strict';
+
+// A wrapper function that does a couple things:
+//
+// 1. Doesn't pollute the global namespace. This is important for a library.
+// 2. Allows us to mount the library in different module systems, as well as
+//    directly in the browser.
+(function() {
+
+// Save the global `this` for use later. In this case, since the library only
+// runs in the browser, it will refer to `window`. Also, figure out if we're in IE8
+// or not. IE8 will still render correctly, but will be static instead of draggable.
+//
+// Save a couple long function names that are used frequently.
+// This optimization saves around 400 bytes.
+//
+// Set a float fudging global, used when dividing and setting sizes to long floats.
+// There's a chance that sometimes the sum of the floats would end up being slightly
+// larger than 100%, breaking the layout. The float fudging value is subtracted from
+// the percentage size.
+var global = this
+  , isIE8 = global.attachEvent && !global[addEventListener]
+  , document = global.document
+  , addEventListener = 'addEventListener'
+  , removeEventListener = 'removeEventListener'
+  , getBoundingClientRect = 'getBoundingClientRect'
+  , FLOAT_FUDGING = 0.5
+
+  // This library only needs two helper functions:
+  //
+  // The first determines which prefixes of CSS calc we need.
+  // We only need to do this once on startup, when this anonymous function is called.
+  // 
+  // Tests -webkit, -moz and -o prefixes. Modified from StackOverflow:
+  // http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167
+  , calc = (function () {
+        var el
+          , prefixes = ["", "-webkit-", "-moz-", "-o-"]
+
+        for (var i = 0; i < prefixes.length; i++) {
+            el = document.createElement('div')
+            el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
+
+            if (el.style.length) {
+                return prefixes[i] + "calc"
+            }
+        }
+    })()
+
+  // The second helper function allows elements and string selectors to be used
+  // interchangeably. In either case an element is returned. This allows us to
+  // do `Split(elem1, elem2)` as well as `Split('#id1', '#id2')`.
+  , elementOrSelector = function (el) {
+        if (typeof el === 'string' || el instanceof String) {
+            return document.querySelector(el)
+        } else {
+            return el
+        }
+    }
+
+  // The main function to initialize a split. Split.js thinks about each pair
+  // of elements as an independant pair. Dragging the gutter between two elements
+  // only changes the dimensions of elements in that pair. This is key to understanding
+  // how the following functions operate, since each function is bound to a pair.
+  // 
+  // A pair object is shaped like this:
+  // 
+  // {
+  //     a: DOM element,
+  //     b: DOM element,
+  //     aMin: Number,
+  //     bMin: Number,
+  //     dragging: Boolean,
+  //     parent: DOM element,
+  //     isFirst: Boolean,
+  //     isLast: Boolean,
+  //     direction: 'horizontal' | 'vertical'
+  // }
+  //
+  // The basic sequence:
+  // 
+  // 1. Set defaults to something sane. `options` doesn't have to be passed at all.
+  // 2. Initialize a bunch of strings based on the direction we're splitting.
+  //    A lot of the behavior in the rest of the library is paramatized down to
+  //    rely on CSS strings and classes.
+  // 3. Define the dragging helper functions, and a few helpers to go with them.
+  // 4. Loop through the elements while pairing them off. Every pair gets an
+  //    `pair` object, a gutter, and special isFirst/isLast properties.
+  // 5. Actually size the pair elements, insert gutters and attach event listeners.
+  , Split = function (ids, options) {
+    var dimension
+      , i
+      , clientDimension
+      , clientAxis
+      , position
+      , gutterClass
+      , paddingA
+      , paddingB
+      , pairs = []
+
+    // 1. Set defaults to something sane. `options` doesn't have to be passed at all,
+    // so create an options object if none exists. Pixel values 10, 100 and 30 are
+    // arbitrary but feel natural.
+    options = typeof options !== 'undefined' ?  options : {}
+
+    if (typeof options.gutterSize === 'undefined') options.gutterSize = 10
+    if (typeof options.minSize === 'undefined') options.minSize = 100
+    if (typeof options.snapOffset === 'undefined') options.snapOffset = 30
+    if (typeof options.direction === 'undefined') options.direction = 'horizontal'
+    if (typeof options.elementStyle === 'undefined') options.elementStyle = function (dimension, size, gutterSize) {
+        var style = {}
+
+        if (typeof size !== 'string' && !(size instanceof String)) {
+            if (!isIE8) {
+                style[dimension] = calc + '(' + size + '% - ' + gutterSize + 'px)'
+            } else {
+                style[dimension] = size + '%'
+            }
+        } else {
+            style[dimension] = size
+        }
+
+        return style
+    }
+    if (typeof options.gutterStyle === 'undefined') options.gutterStyle = function (dimension, gutterSize) {
+        var style = {}
+
+        style[dimension] = gutterSize + 'px'
+
+        return style
+    }
+
+    // 2. Initialize a bunch of strings based on the direction we're splitting.
+    // A lot of the behavior in the rest of the library is paramatized down to
+    // rely on CSS strings and classes.
+    if (options.direction == 'horizontal') {
+        dimension = 'width'
+        clientDimension = 'clientWidth'
+        clientAxis = 'clientX'
+        position = 'left'
+        gutterClass = 'gutter gutter-horizontal'
+        paddingA = 'paddingLeft'
+        paddingB = 'paddingRight'
+        if (!options.cursor) options.cursor = 'ew-resize'
+    } else if (options.direction == 'vertical') {
+        dimension = 'height'
+        clientDimension = 'clientHeight'
+        clientAxis = 'clientY'
+        position = 'top'
+        gutterClass = 'gutter gutter-vertical'
+        paddingA = 'paddingTop'
+        paddingB = 'paddingBottom'
+        if (!options.cursor) options.cursor = 'ns-resize'
+    }
+
+    // 3. Define the dragging helper functions, and a few helpers to go with them.
+    // Each helper is bound to a pair object that contains it's metadata. This
+    // also makes it easy to store references to listeners that that will be
+    // added and removed.
+    // 
+    // Even though there are no other functions contained in them, aliasing
+    // this to self saves 50 bytes or so since it's used so frequently.
+    //
+    // The pair object saves metadata like dragging state, position and
+    // event listener references.
+    //
+    // startDragging calls `calculateSizes` to store the inital size in the pair object.
+    // It also adds event listeners for mouse/touch events,
+    // and prevents selection while dragging so avoid the selecting text.
+    var startDragging = function (e) {
+            // Alias frequently used variables to save space. 200 bytes.
+            var self = this
+              , a = self.a
+              , b = self.b
+
+            // Call the onDragStart callback.
+            if (!self.dragging && options.onDragStart) {
+                options.onDragStart()
+            }
+
+            // Don't actually drag the element. We emulate that in the drag function.
+            e.preventDefault()
+
+            // Set the dragging property of the pair object.
+            self.dragging = true
+
+            // Create two event listeners bound to the same pair object and store
+            // them in the pair object.
+            self.move = drag.bind(self)
+            self.stop = stopDragging.bind(self)
+
+            // All the binding. `window` gets the stop events in case we drag out of the elements.
+            global[addEventListener]('mouseup', self.stop)
+            global[addEventListener]('touchend', self.stop)
+            global[addEventListener]('touchcancel', self.stop)
+
+            self.parent[addEventListener]('mousemove', self.move)
+            self.parent[addEventListener]('touchmove', self.move)
+
+            // Disable selection. Disable!
+            a[addEventListener]('selectstart', noop)
+            a[addEventListener]('dragstart', noop)
+            b[addEventListener]('selectstart', noop)
+            b[addEventListener]('dragstart', noop)
+
+            a.style.userSelect = 'none'
+            a.style.webkitUserSelect = 'none'
+            a.style.MozUserSelect = 'none'
+            a.style.pointerEvents = 'none'
+
+            b.style.userSelect = 'none'
+            b.style.webkitUserSelect = 'none'
+            b.style.MozUserSelect = 'none'
+            b.style.pointerEvents = 'none'
+
+            // Set the cursor, both on the gutter and the parent element.
+            // Doing only a, b and gutter causes flickering.
+            self.gutter.style.cursor = options.cursor
+            self.parent.style.cursor = options.cursor
+
+            // Cache the initial sizes of the pair.
+            calculateSizes.call(self)
+        }
+
+      // stopDragging is very similar to startDragging in reverse.
+      , stopDragging = function () {
+            var self = this
+              , a = self.a
+              , b = self.b
+
+            if (self.dragging && options.onDragEnd) {
+                options.onDragEnd()
+            }
+
+            self.dragging = false
+
+            // Remove the stored event listeners. This is why we store them.
+            global[removeEventListener]('mouseup', self.stop)
+            global[removeEventListener]('touchend', self.stop)
+            global[removeEventListener]('touchcancel', self.stop)
+
+            self.parent[removeEventListener]('mousemove', self.move)
+            self.parent[removeEventListener]('touchmove', self.move)
+
+            // Delete them once they are removed. I think this makes a difference
+            // in memory usage with a lot of splits on one page. But I don't know for sure.
+            delete self.stop
+            delete self.move
+
+            a[removeEventListener]('selectstart', noop)
+            a[removeEventListener]('dragstart', noop)
+            b[removeEventListener]('selectstart', noop)
+            b[removeEventListener]('dragstart', noop)
+
+            a.style.userSelect = ''
+            a.style.webkitUserSelect = ''
+            a.style.MozUserSelect = ''
+            a.style.pointerEvents = ''
+
+            b.style.userSelect = ''
+            b.style.webkitUserSelect = ''
+            b.style.MozUserSelect = ''
+            b.style.pointerEvents = ''
+
+            self.gutter.style.cursor = ''
+            self.parent.style.cursor = ''
+        }
+
+      // drag, where all the magic happens. The logic is really quite simple:
+      // 
+      // 1. Ignore if the pair is not dragging.
+      // 2. Get the offset of the event.
+      // 3. Snap offset to min if within snappable range (within min + snapOffset).
+      // 4. Actually adjust each element in the pair to offset.
+      // 
+      // ---------------------------------------------------------------------
+      // |    | <- this.aMin               ||              this.bMin -> |    |
+      // |    |  | <- this.snapOffset      ||     this.snapOffset -> |  |    |
+      // |    |  |                         ||                        |  |    |
+      // |    |  |                         ||                        |  |    |
+      // ---------------------------------------------------------------------
+      // | <- this.start                                        this.size -> |
+      , drag = function (e) {
+            var offset
+
+            if (!this.dragging) return
+
+            // Get the offset of the event from the first side of the
+            // pair `this.start`. Supports touch events, but not multitouch, so only the first
+            // finger `touches[0]` is counted.
+            if ('touches' in e) {
+                offset = e.touches[0][clientAxis] - this.start
+            } else {
+                offset = e[clientAxis] - this.start
+            }
+
+            // If within snapOffset of min or max, set offset to min or max.
+            // snapOffset buffers aMin and bMin, so logic is opposite for both.
+            // Include the appropriate gutter sizes to prevent overflows.
+            if (offset <= this.aMin + options.snapOffset + this.aGutterSize) {
+                offset = this.aMin + this.aGutterSize
+            } else if (offset >= this.size - (this.bMin + options.snapOffset + this.bGutterSize)) {
+                offset = this.size - (this.bMin + this.bGutterSize)
+            }
+
+            offset = offset - FLOAT_FUDGING
+
+            // Actually adjust the size.
+            adjust.call(this, offset)
+
+            // Call the drag callback continously. Don't do anything too intensive
+            // in this callback.
+            if (options.onDrag) {
+                options.onDrag()
+            }
+        }
+
+      // Cache some important sizes when drag starts, so we don't have to do that
+      // continously:
+      // 
+      // `size`: The total size of the pair. First element + second element + first gutter + second gutter.
+      // `percentage`: The percentage between 0-100 that the pair occupies in the parent.
+      // `start`: The leading side of the first element.
+      //
+      // ------------------------------------------------ - - - - - - - - - - -
+      // |      aGutterSize -> |||                      |                     |
+      // |                     |||                      |                     |
+      // |                     |||                      |                     |
+      // |                     ||| <- bGutterSize       |                     |
+      // ------------------------------------------------ - - - - - - - - - - -
+      // | <- start                             size -> |       parentSize -> |
+      , calculateSizes = function () {
+            // Figure out the parent size minus padding.
+            var computedStyle = global.getComputedStyle(this.parent)
+              , parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
+
+            this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
+            this.percentage = Math.min(this.size / parentSize * 100, 100)
+            this.start = this.a[getBoundingClientRect]()[position]
+        }
+
+      // Actually adjust the size of elements `a` and `b` to `offset` while dragging.
+      // calc is used to allow calc(percentage + gutterpx) on the whole split instance,
+      // which allows the viewport to be resized without additional logic.
+      // Element a's size is the same as offset. b's size is total size - a size.
+      // Both sizes are calculated from the initial parent percentage, then the gutter size is subtracted.
+      , adjust = function (offset) {
+            setElementSize(this.a, (offset / this.size * this.percentage), this.aGutterSize)
+            setElementSize(this.b, (this.percentage - (offset / this.size * this.percentage)), this.bGutterSize)
+        }
+      , setElementSize = function (el, size, gutterSize) {
+            // Split.js allows setting sizes via numbers (ideally), or if you must,
+            // by string, like '300px'. This is less than ideal, because it breaks
+            // the fluid layout that `calc(% - px)` provides. You're on your own if you do that,
+            // make sure you calculate the gutter size by hand.
+            var style = options.elementStyle(dimension, size, gutterSize)
+              , props = Object.keys(style)
+
+            for (var i = 0; i < props.length; i++) {
+                el.style[props[i]] = style[props[i]]
+            }
+        }
+      , setGutterSize = function (gutter, gutterSize) {
+            var style = options.gutterStyle(dimension, gutterSize)
+              , props = Object.keys(style)
+
+            for (var i = 0; i < props.length; i++) {
+                gutter.style[props[i]] = style[props[i]]
+            }
+        }
+
+      // No-op function to prevent default. Used to prevent selection.
+      , noop = function () { return false }
+
+      // All DOM elements in the split should have a common parent. We can grab
+      // the first elements parent and hope users read the docs because the
+      // behavior will be whacky otherwise.
+      , parent = elementOrSelector(ids[0]).parentNode
+
+    // Set default options.sizes to equal percentages of the parent element.
+    if (!options.sizes) {
+        var percent = 100 / ids.length
+
+        options.sizes = []
+
+        for (i = 0; i < ids.length; i++) {
+            options.sizes.push(percent)
+        }
+    }
+
+    // Standardize minSize to an array if it isn't already. This allows minSize
+    // to be passed as a number.
+    if (!Array.isArray(options.minSize)) {
+        var minSizes = []
+
+        for (i = 0; i < ids.length; i++) {
+            minSizes.push(options.minSize)
+        }
+
+        options.minSize = minSizes
+    }
+
+    // 5. Loop through the elements while pairing them off. Every pair gets a
+    // `pair` object, a gutter, and isFirst/isLast properties.
+    //
+    // Basic logic:
+    //
+    // - Starting with the second element `i > 0`, create `pair` objects with
+    //   `a = ids[i - 1]` and `b = ids[i]`
+    // - Set gutter sizes based on the _pair_ being first/last. The first and last
+    //   pair have gutterSize / 2, since they only have one half gutter, and not two.
+    // - Create gutter elements and add event listeners.
+    // - Set the size of the elements, minus the gutter sizes.
+    //
+    // -----------------------------------------------------------------------
+    // |     i=0     |         i=1         |        i=2       |      i=3     |
+    // |             |       isFirst       |                  |     isLast   |
+    // |           pair 0                pair 1             pair 2           |
+    // |             |                     |                  |              |
+    // -----------------------------------------------------------------------
+    for (i = 0; i < ids.length; i++) {
+        var el = elementOrSelector(ids[i])
+          , isFirstPair = (i == 1)
+          , isLastPair = (i == ids.length - 1)
+          , size = options.sizes[i]
+          , gutterSize = options.gutterSize
+          , pair
+          , parentFlexDirection = window.getComputedStyle(parent).flexDirection
+          , temp
+
+        if (i > 0) {
+            // Create the pair object with it's metadata.
+            pair = {
+                a: elementOrSelector(ids[i - 1]),
+                b: el,
+                aMin: options.minSize[i - 1],
+                bMin: options.minSize[i],
+                dragging: false,
+                parent: parent,
+                isFirst: isFirstPair,
+                isLast: isLastPair,
+                direction: options.direction
+            }
+
+            // For first and last pairs, first and last gutter width is half.
+            pair.aGutterSize = options.gutterSize
+            pair.bGutterSize = options.gutterSize
+
+            if (isFirstPair) {
+                pair.aGutterSize = options.gutterSize / 2
+            }
+
+            if (isLastPair) {
+                pair.bGutterSize = options.gutterSize / 2
+            }
+
+            // if the parent has a reverse flex-direction, switch the pair elements.
+            if (parentFlexDirection === 'row-reverse' || parentFlexDirection === 'column-reverse') {
+                temp = pair.a;
+                pair.a = pair.b;
+                pair.b = temp;
+            }
+        }
+
+        // Determine the size of the current element. IE8 is supported by
+        // staticly assigning sizes without draggable gutters. Assigns a string
+        // to `size`.
+        // 
+        // IE9 and above
+        if (!isIE8) {
+            // Create gutter elements for each pair.
+            if (i > 0) {
+                var gutter = document.createElement('div')
+
+                gutter.className = gutterClass
+
+                setGutterSize(gutter, gutterSize)
+
+                gutter[addEventListener]('mousedown', startDragging.bind(pair))
+                gutter[addEventListener]('touchstart', startDragging.bind(pair))
+
+                parent.insertBefore(gutter, el)
+
+                pair.gutter = gutter
+            }
+
+            // Half-size gutters for first and last elements.
+            if (i === 0 || i == ids.length - 1) {
+                gutterSize = options.gutterSize / 2
+            }
+        }
+
+        // Set the element size to our determined size.
+        setElementSize(el, size, gutterSize)
+
+        if (i > 0) {
+            var aSize = pair.a[getBoundingClientRect]()[dimension]
+              , bSize = pair.b[getBoundingClientRect]()[dimension]
+
+            if (aSize < pair.aMin) {
+                pair.aMin = aSize
+            }
+
+            if (bSize < pair.bMin) {
+                pair.bMin = bSize
+            }
+        }
+
+        // After the first iteration, and we have a pair object, append it to the
+        // list of pairs.
+        if (i > 0) {
+            pairs.push(pair)
+        }
+    }
+
+    return {
+        setSizes: function (sizes) {
+            for (var i = 0; i < sizes.length; i++) {
+                if (i > 0) {
+                    var pair = pairs[i - 1]
+
+                    setElementSize(pair.a, sizes[i - 1], pair.aGutterSize)
+                    setElementSize(pair.b, sizes[i], pair.bGutterSize)
+                }
+            }
+        },
+        getSizes: function () {
+            var sizes = []
+
+            for (var i = 0; i < pairs.length; i++) {
+                var pair = pairs[i]
+                  , computedStyle = global.getComputedStyle(pair.parent)
+                  , parentSize = pair.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
+
+                sizes.push((pair.a[getBoundingClientRect]()[dimension] + pair.aGutterSize) / parentSize * 100)
+
+                if (i === pairs.length - 1) {
+                    sizes.push((pair.b[getBoundingClientRect]()[dimension] + pair.bGutterSize) / parentSize * 100)
+                }
+            }
+
+            return sizes
+        },
+        collapse: function (i) {
+            var pair
+
+            if (i === pairs.length) {
+                pair = pairs[i - 1]
+
+                calculateSizes.call(pair)
+                adjust.call(pair, pair.size - pair.bGutterSize)
+            } else {
+                pair = pairs[i]
+
+                calculateSizes.call(pair)
+                adjust.call(pair, pair.aGutterSize)
+            }
+        },
+        destroy: function () {
+            for (var i = 0; i < pairs.length; i++) {
+                pairs[i].parent.removeChild(pairs[i].gutter)
+                pairs[i].a.style[dimension] = ''
+                pairs[i].b.style[dimension] = ''
+            }
+        }
+    }
+}
+
+// Play nicely with module systems, and the browser too if you include it raw.
+if (typeof exports !== 'undefined') {
+    if (typeof module !== 'undefined' && module.exports) {
+        exports = module.exports = Split
+    }
+    exports.Split = Split
+} else {
+    global.Split = Split
+}
+
+// Call our wrapper function with the current global. In this case, `window`.
+}).call(window);

+ 5 - 3
Playground/package.json

@@ -1,12 +1,14 @@
 {
   "name": "babylonjsplayground",
-  "version": "2.5.0",
+  "version": "2.6.0",
   "description": "Babylon.js is a 3D engine based on webgl and javascript",
   "main": "",
-  "repository": { "url": "https://github.com/BabylonJS/Babylon.js/" },
+  "repository": {
+    "url": "https://github.com/BabylonJS/Babylon.js/"
+  },
   "readme": "https://github.com/BabylonJS/Babylon.js/blob/master/readme.md",
   "license": "(Apache-2.0)",
   "devDependencies": {
     "monaco-editor": "^0.7.0"
   }
-}
+}

+ 0 - 146
Playground/splitbox.css

@@ -1,146 +0,0 @@
-x-splitbox {
-  position: relative;
-  display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
-  display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
-  display: -ms-flexbox;      /* TWEENER - IE 10 */
-  display: -webkit-flex;     /* NEW - Chrome */
-  display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
-  height: 100%;
-  overflow: hidden;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  box-sizing: border-box;
-  -webkit-box-orient: horizontal;
-  -moz-box-orient: horizontal;
-  -ms-box-orient: horizontal;
-  box-orient: horizontal;
-  -webkit-flex-direction: row;
-  -moz-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-}
-
-x-splitbox[direction="column"] {
-  -webkit-box-orient: vertical;
-  -moz-box-orient: vertical;
-  -ms-box-orient: vertical;
-  box-orient: vertical;
-  -webkit-flex-direction: column;
-  -moz-flex-direction: column;
-  -ms-flex-direction: column;
-  flex-direction: column;
-}
-
-x-splitbox > *:not([splitter]) {
-  min-width: 0;
-  min-height: 0;
-  -webkit-box-flex: 1;
-  -moz-box-flex: 1;
-  -webkit-flex: 1;
-  flex: 1;
-  -ms-flex: auto;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  box-sizing: border-box;
-}
-
-x-splitbox[dragging], x-splitbox > [splitter] {
-  -moz-user-select: -moz-none;
-  -khtml-user-select: none;
-  -webkit-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-  -webkit-user-drag: none;
-}
-
-x-splitbox > [splitter] {
-  display: block;
-  position: relative;
-  min-width: 0px !important;
-  max-width: 0px !important;
-  cursor: ew-resize;
-  background: #fff;
-  opacity: 0.6;
-}
-
-  x-splitbox > [splitter]:before {
-    content: " ";
-    display: block;
-    position: absolute;
-    width: 0.8em;
-    height: 100%;
-    opacity: 0;
-    background: inherit;
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    -ms-box-sizing: border-box;
-    box-sizing: border-box;
-    -webkit-transform: translate(-50%, 0);
-    -ms-transform: translate(-50%, 0);
-    transform: translate(-50%, 0);
-  }
-
-  x-splitbox > [splitter]:after {
-    content: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMWVtIiB3aWR0aD0iMWVtIiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0Ij48cGF0aCBmaWxsPSJyZ2JhKDAsMCwwLDAuNzUpIiBkPSJNNzU4IDIzNGwyMzIgMjc4LTIzMiAyNzgtNjYtNTQgMTg2LTIyNC0xODYtMjI0ek00NzAgNTU0di04NGg4NHY4NGgtODR6TTcyNiA0NzB2ODRoLTg2di04NGg4NnpNMjk4IDU1NHYtODRoODZ2ODRoLTg2ek0zMzIgMjg4bC0xODYgMjI0IDE4NiAyMjQtNjYgNTQtMjMyLTI3OCAyMzItMjc4eiI+PC9wYXRoPjwvc3ZnPg==');
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    height: 1em;
-    padding: 0.05em;
-    background: inherit;
-    border-radius: 100%;
-    -webkit-box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    -ms-box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    box-shadow: 0 1px 1px 0px rgba(0,0,0,0.4);
-    -webkit-transform: translate(-50%, -50%);
-    -ms-transform: translate(-50%, -50%);
-    transform: translate(-50%, -50%);
-  }
-
-  x-splitbox[direction="column"] > [splitter] {
-    cursor: ns-resize;
-    min-width: auto !important;
-    max-width: none !important;
-    min-height: 0px !important;
-    max-height: 0px !important;
-  }
-
-  x-splitbox[direction="column"] > [splitter]:before {
-    width: 100%;
-    height: 0.8em;
-    -webkit-transform: translate(0%, -50%);
-    -ms-transform: translate(0%, -50%);
-    transform: translate(0%, -50%);
-  }
-
-  x-splitbox[direction="column"] > [splitter]:after {
-    -webkit-box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    -ms-box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    box-shadow: 1px 0 1px 0px rgba(0,0,0,0.4);
-    -webkit-transform: translate(-50%, -50%) rotate(90deg);
-    -ms-transform: translate(-50%, -50%) rotate(90deg);
-    transform: translate(-50%, -50%) rotate(90deg);
-  }
-
-  x-splitbox > [splitter]:hover, x-splitbox > [splitter][dragging] {
-    opacity: 1;
-    z-index: 2;
-  }
-
-  x-splitbox > [splitter][dragging]:before {
-    opacity: 0.3;
-  }
-
-
-@media screen and (max-device-width: 415px) {
-  x-splitbox > [splitter]:before {
-    display: block;
-  }
-
-    x-splitbox[direction="column"] > [splitter] {
-      display: block;
-    }
-}
-

+ 0 - 116
Playground/splitbox.js

@@ -1,116 +0,0 @@
-(function () {
-
-    function startDrag(node, splitter, event) {
-
-        node.setAttribute('dragging', '');
-        node.xtag.splitter = splitter;
-        splitter.setAttribute('dragging', '');
-        splitter.style.zIndex = node.xtag.splitZ = (node.xtag.splitZ || 0) + 1;
-
-        var props = getProps(node);
-        var lastCoord = event[props.page] - node[props.edge];
-        var next = splitter.nextElementSibling, next = !next.hasAttribute('splitter') && next;
-        var previous = splitter.previousElementSibling, previous = !previous.hasAttribute('splitter') && previous;
-        var startingTotal = next[props.size] + previous[props.size];
-
-        setPercents(node, props);
-
-        node.xtag.drag = xtag.addEvent(node, 'move', function (e) {
-            var delta = e[props.page] - node[props.edge] - lastCoord;
-            var nextSize = next[props.size];
-            var prevSize = previous[props.size];
-            var nextMod = nextSize - delta;
-            var prevMod = prevSize + delta;
-
-            if (delta > 0) {
-                if (nextSize > 0) {
-                    if (nextMod <= 0 || prevMod >= startingTotal || prevMod > startingTotal || nextMod > startingTotal) {
-                        prevMod = startingTotal;
-                        nextMod = 0;
-                    }
-                    setMinMax(next, props, nextMod);
-                    setMinMax(previous, props, prevMod);
-                }
-            }
-
-            else if (delta < 0) {
-                if (prevSize > 0) {
-                    if (prevMod <= 0 || nextMod >= startingTotal || prevMod > startingTotal || nextMod > startingTotal) {
-                        nextMod = startingTotal;
-                        prevMod = 0;
-                    }
-                    setMinMax(next, props, nextMod);
-                    setMinMax(previous, props, prevMod);
-                }
-            }
-
-            lastCoord = e[props.page] - node[props.edge];
-        });
-    }
-
-    function getProps(node) {
-        return node.xtag.props = (node.direction == 'column') ? {
-            page: 'pageY',
-            size: 'clientHeight',
-            edge: 'clientTop',
-            parentSize: node.clientHeight
-        } : {
-            page: 'pageX',
-            size: 'clientWidth',
-            edge: 'clientLeft',
-            parentSize: node.clientWidth
-        };
-    }
-
-    function setPercents(node, props, setup) {
-        node.xtag.panels = xtag.queryChildren(node, '*:not([splitter])').map(function (el) {
-            setMinMax(el, props, el[props.size], setup);
-            return el;
-        });
-    }
-
-    function setMinMax(panel, props, value, setup) {
-        panel.style.flex = panel.style[xtag.prefix.lowercase + 'Flex'] = (setup ? '0 0 ' : '1 1 ') + (value / props.parentSize) * 100 + '%';
-    }
-
-    function stopDrag(node) {
-        if (node.xtag.drag) {
-            xtag.removeEvent(node, node.xtag.drag);
-            node.removeAttribute('dragging');
-            node.xtag.splitter.removeAttribute('dragging');
-            node.xtag.splitter = null;
-            node.xtag.drag = null;
-        }
-    }
-
-    xtag.addEvent(window, 'tapend', function (e) {
-        xtag.query(document, 'x-splitbox[dragging]').forEach(stopDrag);
-    })
-
-    xtag.register('x-splitbox', {
-        events: {
-            'tapstart:delegate(x-splitbox > [splitter])': function (e) {
-                startDrag(e.currentTarget, this, e);
-            },
-            dragstart: function (e) {
-                if (this.hasAttribute('dragging')) {
-                    e.preventDefault();
-                    return false;
-                }
-            },
-            contextmemu: function (e) {
-                e.preventDefault();
-            }
-        },
-        accessors: {
-            direction: {
-                attribute: { def: 'row' },
-                set: function (direction) {
-                    setPercents(this, getProps(this), true);
-                }
-            }
-        }
-    });
-
-})();
-

+ 55 - 0
Playground/test.html

@@ -0,0 +1,55 @@
+<div class="navbar-inner" id="topbar">
+    <a class="brand largeOnly" href="#" id="mainTitle">Babylon.js Playground</a>
+    <div class="btn-group">
+        <button class="btn" id="runButton">Run</button>
+        <button class="btn" id="saveButton">Save</button>
+        <button class="btn desktopOnly" id="zipButton">Get .zip</button>
+        <button class="btn desktopOnly" id="newButton">New</button>
+        <button class="btn desktopOnly" id="clearButton">Clear</button>
+    </div>
+    <div class="btn-group desktopOnly">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentFontSize">Font: 12</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="sizeList">
+            <li><a href="#" onclick="setFontSize(12);">12</a></li>
+            <li><a href="#" onclick="setFontSize(14);">14</a></li>
+            <li><a href="#" onclick="setFontSize(16);">16</a></li>
+            <li><a href="#" onclick="setFontSize(18);">18</a></li>
+            <li><a href="#" onclick="setFontSize(20);">20</a></li>
+            <li><a href="#" onclick="setFontSize(22);">22</a></li>
+        </ul>
+    </div>
+    <div class="btn-group desktopOnly">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentVersion">Version: Latest</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="versionList">
+            <li><a href="#" onclick="setVersion('latest');">Latest</a></li>
+            <li><a href="#" onclick="setVersion('2.5');">2.5</a></li>
+        </ul>
+    </div>
+    <div class="btn-group">
+        <label class="btn btn-sm active">
+                    <input type="checkbox" autocomplete="off" id='safemodeToggle' style="margin-top:-0.1em;margin-right:4px">Safe Mode
+                </label>
+        <button class="btn btn-sm" id="metadataButton">+Meta data</button>
+        <button class="btn btn-sm" id="editorButton">-Editor</button>
+        <button class="btn btn-sm" id="debugButton">+Debug layer</button>
+    </div>
+    <div class="btn-group pull-right">
+        <button class="btn" id="fullscreenButton">Fullscreen</button>
+    </div>
+    <div class="btn-group pull-right">
+        <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+            <span id="currentScript">Predefined scripts</span>
+            <span class="caret"></span>
+        </a>
+        <ul class="dropdown-menu" id="scriptsList"></ul>
+    </div>
+</div>
+<div class="save-message" id="saveMessage">
+    This PG has no metadata. Click save to add them.
+</div>

File diff suppressed because it is too large
+ 0 - 2
Playground/xtag.min.js