Przeglądaj źródła

Merge pull request #4167 from rlouvat/master

Add the animation bar
David Catuhe 7 lat temu
rodzic
commit
db4911de84

Plik diff jest za duży
+ 5499 - 5491
dist/preview release/babylon.d.ts


Plik diff jest za duży
+ 9 - 9
dist/preview release/babylon.js


+ 20 - 0
dist/preview release/babylon.max.js

@@ -51453,6 +51453,26 @@ var BABYLON;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
+        Object.defineProperty(AnimationGroup.prototype, "from", {
+            /**
+             * Gets the first frame
+             */
+            get: function () {
+                return this._from;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(AnimationGroup.prototype, "to", {
+            /**
+             * Gets the last frame
+             */
+            get: function () {
+                return this._to;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(AnimationGroup.prototype, "isStarted", {
             /**
              * Define if the animations are started

+ 20 - 0
dist/preview release/babylon.no-module.max.js

@@ -51420,6 +51420,26 @@ var BABYLON;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
+        Object.defineProperty(AnimationGroup.prototype, "from", {
+            /**
+             * Gets the first frame
+             */
+            get: function () {
+                return this._from;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(AnimationGroup.prototype, "to", {
+            /**
+             * Gets the last frame
+             */
+            get: function () {
+                return this._to;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(AnimationGroup.prototype, "isStarted", {
             /**
              * Define if the animations are started

Plik diff jest za duży
+ 9 - 9
dist/preview release/babylon.worker.js


+ 20 - 0
dist/preview release/es6.js

@@ -51420,6 +51420,26 @@ var BABYLON;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
+        Object.defineProperty(AnimationGroup.prototype, "from", {
+            /**
+             * Gets the first frame
+             */
+            get: function () {
+                return this._from;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(AnimationGroup.prototype, "to", {
+            /**
+             * Gets the last frame
+             */
+            get: function () {
+                return this._to;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(AnimationGroup.prototype, "isStarted", {
             /**
              * Define if the animations are started

Plik diff jest za duży
+ 9 - 9
dist/preview release/viewer/babylon.viewer.js


+ 20 - 0
dist/preview release/viewer/babylon.viewer.max.js

@@ -51541,6 +51541,26 @@ var BABYLON;
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
+        Object.defineProperty(AnimationGroup.prototype, "from", {
+            /**
+             * Gets the first frame
+             */
+            get: function () {
+                return this._from;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(AnimationGroup.prototype, "to", {
+            /**
+             * Gets the last frame
+             */
+            get: function () {
+                return this._to;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(AnimationGroup.prototype, "isStarted", {
             /**
              * Define if the animations are started

BIN
sandbox/Assets/arrowUp.png


BIN
sandbox/Assets/circle.png


BIN
sandbox/Assets/pause.png


BIN
sandbox/Assets/play.png


+ 17 - 0
sandbox/index-local.html

@@ -24,6 +24,23 @@
             </a>
         </div>
     </div>
+    <div id="animationBar">
+        <div class="dropdown">
+            <div id="dropdownBtn">
+                <span id="dropdownLabel"></span>
+                <img src="Assets/arrowUp.png">
+            </div>
+            <div id="dropdownContent">
+            </div>
+        </div>
+        <div class="row">
+            <button id="playBtn" class="pause">
+                <img id="playImg" src="Assets/play.png">
+                <img id="pauseImg" src="Assets/pause.png">
+            </button>
+            <input id="slider" type="range" min="0" max="100" value="0" step="any">
+        </div>
+    </div>
     <div id="errorZone"></div>
     <script>
         BABYLONDEVTOOLS.Loader

+ 239 - 0
sandbox/index.css

@@ -221,3 +221,242 @@ a {
     opacity: .4;
     font-size: 1.8em;
 }
+
+
+/* animation bar */
+#animationBar {
+    position: absolute;
+    bottom: 0px;
+    display: none;
+    justify-content: space-around;
+    align-items: center;
+    color: white;
+    font-weight: bold;
+    width: calc(100% - 200px);
+}
+
+.row {
+    display: flex;
+    flex-direction: row;
+}
+
+#animationBar * {
+    padding: 0px;
+    margin: 0px;
+}
+
+#animationBar,
+#dropdownContent {
+    padding: 10px;
+    background-color: #3B789A;
+}
+
+#animationBar img {
+    width: 25px;
+    height: 25px;
+}
+
+.dropdown {
+    position: relative;
+    display: inline-block;
+}
+
+#dropdownBtn,
+#playBtn {
+    display: flex;
+    align-items: center;
+}
+
+#playBtn {
+    margin-left: 40px;
+    margin-right: 20px;
+    border: none;
+    background-color: inherit;
+}
+
+#dropdownLabel,
+#dropdownContent a  {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    padding: 5px;    
+}
+#dropdownLabel {
+    cursor: default;
+    width: 100px;
+}
+#dropdownContent a {
+    max-width: 1000px;
+    transition: color 0.5s;
+}
+#dropdownContent a:hover {
+    color: #162D3A;
+}
+
+#dropdownContent {
+    display: none;
+    position: absolute;
+    bottom: 100%;
+    left: -10px;
+    z-index: 1;
+    border-radius: 5px 5px 0px 0px;
+    min-width: 135px;
+}
+
+#dropdownContent a,
+#playBtn {
+    cursor: pointer;
+}
+
+#dropdownContent .active {
+    color: #2c5a74;
+}
+
+.dropdown:hover #dropdownContent {
+    display: flex;
+    flex-direction: column;
+}
+
+#playBtn.play #pauseImg,
+#playBtn.pause #playImg{
+    display: none;
+}
+
+#slider {
+    cursor: pointer;
+    -webkit-appearance: none;
+    width: 1000px;
+    outline: none;
+    border-radius: 5px;
+}
+
+/*Chrome -webkit */
+#slider::-webkit-slider-thumb {
+    -webkit-appearance: none;
+    appearance: none;
+    width: 20px;
+    height: 20px;
+    border: 0;
+    background: url('Assets/circle.png') no-repeat #3B789A;
+    background-size: 100% 100%;
+}
+#slider::-webkit-slider-runnable-track {
+    height: 10px;
+    -webkit-appearance: none;
+    color: white;
+    margin-top: -1px;
+}
+
+
+/** FireFox -moz */
+#slider::-moz-range-progress {
+  background-color: white;
+  height: 5px; 
+}
+#slider::-moz-range-thumb{
+    width: 20px;
+    height: 20px;
+    border: 0;
+    background: url('Assets/circle.png') no-repeat #3B789A;
+    background-size: 100% 100%;
+}
+
+/** IE -ms */
+#slider::-ms-fill-lower {
+    background-color: white;
+    height: 5px; 
+  }
+#slider::-ms-thumb {
+    width: 20px;
+    height: 20px;
+    border: 0;
+    background: url('Assets/circle.png') no-repeat #3B789A;
+    background-size: 100% 100%;
+}
+
+@media (min-width: 0px) {
+    #slider,
+    #dropdownLabel {
+        display: none;
+    }
+
+    #dropdownContent a {
+        max-width: 260px;
+    }
+}
+
+@media (min-width: 576px) {
+    #slider,
+    #dropdownLabel {
+        display: initial;
+    }
+    
+    #slider {
+        width: 100px;
+    }
+
+    #dropdownLabel {
+        width: 50px;
+    }
+
+    #dropdownContent a {
+        max-width: 300px;
+    }
+}
+
+@media (min-width: 768px) {
+    #slider,
+    #dropdownLabel {
+        display: initial;
+    }
+    
+    #slider {
+        width: 300px;
+    }
+
+    #dropdownLabel {
+        width: 75px;
+    }
+
+    #dropdownContent a {
+        max-width: 400px;
+    }
+}
+
+@media (min-width: 992px) {
+    #slider,
+    #dropdownLabel {
+        display: initial;
+    }
+    
+    #slider {
+        width: 400px;
+    }
+
+    #dropdownLabel {
+        width: 100px;
+    }
+
+    #dropdownContent a {
+        max-width: 600px;
+    }
+}
+
+@media (min-width: 1200px) {
+    #slider,
+    #dropdownLabel {
+        display: initial;
+    }
+    
+    #slider {
+        width: 700px;
+    }
+
+    #dropdownLabel {
+        width: 200px;
+    }
+
+    #dropdownContent a {
+        max-width: 700px;
+    }
+}

+ 19 - 1
sandbox/index.html

@@ -29,7 +29,8 @@
 
     <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>
+    <!-- <script src="https://preview.babylonjs.com/babylon.js"></script> -->
+    <script src="../dist/preview release/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 
     <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
@@ -53,6 +54,23 @@
             </a>
         </div>
     </div>
+    <div id="animationBar">
+        <div class="dropdown">
+            <div id="dropdownBtn">
+                <span id="dropdownLabel"></span>
+                <img src="Assets/arrowUp.png">
+            </div>
+            <div id="dropdownContent">
+            </div>
+        </div>
+        <div class="row">
+            <button id="playBtn" class="pause">
+                <img id="playImg" src="Assets/play.png">
+                <img id="pauseImg" src="Assets/pause.png">
+            </button>
+            <input id="slider" type="range" min="0" max="100" value="0" step="any">
+        </div>
+    </div>
     <div id="errorZone"></div>
     <script src="index.js"></script>
 </body>

+ 115 - 0
sandbox/index.js

@@ -4,6 +4,15 @@
 var assetUrl;
 var cameraPosition;
 var kiosk;
+var currentGroup; // animation group
+var currentGroupIndex;
+var currentScene;
+// html balise
+var animationBar = document.getElementById("animationBar");
+var dropdownLabel = document.getElementById("dropdownLabel");
+var dropdownContent = document.getElementById("dropdownContent");
+var playBtn = document.getElementById("playBtn");
+var slider = document.getElementById("slider");
 
 var indexOf = location.href.indexOf("?");
 if (indexOf !== -1) {
@@ -53,6 +62,9 @@ if (BABYLON.Engine.isSupported()) {
 
     BABYLON.Engine.ShadersRepository = "/src/Shaders/";
 
+    // This is really important to tell Babylon.js to use decomposeLerp and matrix interpolation
+    BABYLON.Animation.AllowMatricesInterpolation = true;
+
     // Setting up some GLTF values
     BABYLON.GLTFFileLoader.IncrementalLoading = false;
     BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
@@ -80,6 +92,30 @@ if (BABYLON.Engine.isSupported()) {
             hideDebugLayerAndLogs();
         }
 
+        // Clear dropdown that contains animation names
+        dropdownContent.innerHTML = "";
+        animationBar.style.display = "none";
+        currentGroup = null;
+
+        if(babylonScene.animationGroups.length > 0) {
+            animationBar.style.display = "flex";
+            for (var index = 0; index < babylonScene.animationGroups.length; index++) {
+                var group = babylonScene.animationGroups[index];
+			    createDropdownLink(group,index);
+            }
+            currentGroup = babylonScene.animationGroups[0];
+            currentGroupIndex = 0;
+            document.getElementById( formatId(currentGroup.name+"-"+currentGroupIndex)).click();
+        }
+
+        // Sync the slider with the current frame
+        babylonScene.registerBeforeRender(function () {
+            
+            if (currentGroup != null && currentGroup.targetedAnimations[0].animation.runtimeAnimations[0] != null) {
+                slider.value = currentGroup.targetedAnimations[0].animation.runtimeAnimations[0].currentFrame;
+            }
+        });
+
         // Clear the error
         errorZone.style.display = 'none';
 
@@ -179,6 +215,7 @@ if (BABYLON.Engine.isSupported()) {
         var fileName = BABYLON.Tools.GetFilename(assetUrl);
         BABYLON.SceneLoader.LoadAsync(rootUrl, fileName, engine).then(function (scene) {
             sceneLoaded({ name: fileName }, scene);
+            currentScene = scene;
             scene.whenReadyAsync().then(function () {
                 engine.runRenderLoop(function ()  {
                     scene.render();
@@ -274,3 +311,81 @@ function sizeScene() {
         divInspWrapper.style['max-width'] = document.body.clientWidth + "px";
     }
 }
+
+
+// animation
+// event on the dropdown
+function formatId(name){
+    return "data-" + name.replace(/\s/g,'');
+}
+
+function createDropdownLink(group,index) {
+    var animation = document.createElement("a");
+    animation.innerHTML = group.name;
+    animation.setAttribute("id",  formatId(group.name+"-"+index));
+    animation.addEventListener("click", function() {
+        // stop the current animation group
+        currentGroup.reset();
+        currentGroup.stop();
+        document.getElementById( formatId(currentGroup.name+"-"+currentGroupIndex)).classList.remove("active");
+        playBtn.classList.remove("play");
+        playBtn.classList.add("pause");
+
+        // start the new animation group
+        currentGroup = group;
+        currentGroupIndex = index;
+        currentGroup.start(true);
+        this.classList.add("active");
+        dropdownLabel.innerHTML = currentGroup.name;
+
+        // set the slider
+        slider.setAttribute("min", currentGroup.from);
+        slider.setAttribute("max", currentGroup.to);
+        currentSliderValue = 0;
+        slider.value = 0;
+    });
+    dropdownContent.appendChild(animation);
+}
+
+// event on the play/pause button
+playBtn.addEventListener("click", function() {
+    // click on the button to run the animation
+    if( this.classList.contains("play") ) {
+        this.classList.remove("play");
+        this.classList.add("pause");
+        var currentFrame = slider.value;
+        currentGroup.play(true);
+    }
+    // click on the button to pause the animation
+    else {
+        this.classList.add("play");
+        this.classList.remove("pause");
+        currentGroup.pause();
+    }
+});
+
+// event on the slider
+slider.addEventListener("input", function() {
+    if( playBtn.classList.contains("play") ) {
+        currentGroup.play(true);
+        currentGroup.goToFrame(this.value);
+        currentGroup.pause();
+    } else {
+        currentGroup.goToFrame(this.value);
+    }
+});
+
+var sliderPause = false;
+slider.addEventListener("mousedown", function() {
+    if( playBtn.classList.contains("pause") ) {
+        sliderPause = true;
+        playBtn.click();
+    }
+});
+
+slider.addEventListener("mouseup", function() {
+    if( sliderPause ) {
+        sliderPause = false;
+        playBtn.click();
+    }
+});

+ 14 - 0
src/Animations/babylon.animationGroup.ts

@@ -23,6 +23,20 @@ module BABYLON {
         public onAnimationEndObservable = new Observable<TargetedAnimation>();
 
         /**
+         * Gets the first frame
+         */
+        public get from(): number {
+            return this._from;
+        }
+        
+        /**
+         * Gets the last frame
+         */
+        public get to(): number {
+            return this._to;
+        }
+
+        /**
          * Define if the animations are started
          */
         public get isStarted(): boolean {