浏览代码

[player] Reworked generator.

badlogic 5 年之前
父节点
当前提交
a5428585e2

+ 130 - 0
spine-ts/player/example/generator/index.html

@@ -0,0 +1,130 @@
+<!doctype html>
+<html>
+<head>
+	<meta charset="utf-8">
+	<script src="jscolor.js"></script>
+	<script src="ui.js"></script>
+	<script src="loader.js"></script>
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+
+<style>
+* {
+	box-sizing: border-box;
+}
+
+body {
+	margin: 0;
+	padding: 0;
+	font-family: sans-serif;
+}
+
+#dropzone {
+	width: 100%;
+	height: 100vh;
+	background: #cccccc;
+	text-align: center;
+	line-height: 100vh;
+
+
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+
+	cursor: pointer;
+}
+
+#editor {
+	display: flex;
+	flex-direction: row-reverse;
+	width: 100%;
+	height: 100vh;
+	background: #aaaaaa;
+}
+
+#player {
+	width: 100%;
+	height: 100%;
+}
+
+#config {
+	width: 100%;
+	height: 100%;
+}
+
+</style>
+
+<body>
+	<div id="dropzone">
+		Click to choose .skel/.json, .atlas, and .png files, or drop them here.
+	</div>
+
+	<div id="editor" style="display: none">
+	</div>
+
+	<script>
+		var UI;
+		var Loader;
+
+		function showError(errorMessage) {
+			alert(errorMessage);
+		}
+
+		window.addEventListener("load", function(event) {
+			UI = spineGenerator.UI;
+			Loader = spineGenerator.Loader;
+			var dropZone = document.getElementById("dropzone");
+			new UI.DropZone(dropZone, true, ".json,.skel,.atlas,.png", function (files) {
+				spineGenerator.Loader.loadSkeletonFiles(files, function(data) {
+					console.log(`Loaded files ${data.jsonFile} ${data.skelFile} ${data.atlasFile}`);
+					console.log(`${data.version} ${data.majorVersion} ${data.minorVersion} ${data.patchVersion}`);
+
+					spine = null;
+					var cssUrl = `https://esotericsoftware.com/files/spine-player/${data.majorVersion}.${data.minorVersion}/spine-player.css`;
+					var playerUrl = `https://esotericsoftware.com/files/spine-player/${data.majorVersion}.${data.minorVersion}/spine-player.js`;
+
+					Loader.loadStyle(cssUrl, function () {
+						Loader.loadJavaScript(playerUrl, function () {
+							UI.hide(dropZone)
+							setupEditor(document.getElementById("editor"), data);
+						});
+					}, showError);
+				}, showError);
+			}, showError);
+		});
+
+		function setupEditor(editor, data) {
+			setupPlayer(editor, data, function(player) {
+				setupConfig(editor, player, data);
+				UI.show(editor, "flex");
+			}, showError)
+		}
+
+		function setupPlayer(editor, data, success, error) {
+			var playerElement = UI.createElement(editor, `<div id="player"></div>`);
+
+			var config = {
+				jsonUrl: data.jsonFile,
+				skelUrl: data.skelFile,
+				atlasUrl: data.atlasFile,
+				rawDataURIs: data.dataUrls,
+				success: success,
+				error: error,
+				alpha: true, // needed so we can emulate shizzle
+				viewport: { // needed so we can see viewport bounds
+					debugRender: true
+				}
+			};
+
+			return new spine.SpinePlayer(playerElement, config);
+		}
+
+		function setupConfig(editor, player, data) {
+			var configElement = UI.createElement(editor, `<div id="config"></div>`);
+		}
+	</script>
+</body>
+</html>

+ 186 - 0
spine-ts/player/example/generator/loader.js

@@ -0,0 +1,186 @@
+var spineGenerator;
+
+(function (spineGenerator) {
+	var Loader = (function () {
+		function Loader() {
+		}
+
+		Loader.loadSkeletonFiles = function(files, success, error) {
+			var skels = 0;
+			var skelFile = null;
+			var jsons = 0;
+			var jsonFile = null;
+			var atlases = 0;
+			var atlasFile = null;
+			var pngs = 0;
+
+			for (var i = 0; i < files.length; i++) {
+				var file = files[i].name.toLowerCase();
+				if (file.endsWith(".skel")) {
+					skels++;
+					skelFile = file;
+				}
+				if (file.endsWith(".json")) {
+					jsons++;
+					jsonFile = file;
+				}
+				if (file.endsWith(".atlas")) {
+					atlases++;
+					atlasFile = file;
+				}
+				if (file.endsWith(".png")) pngs++;
+			}
+
+			if ((skels == 0 && jsons == 0) || (skels != 0 && jsons != 0) || skels > 1 || jsons > 1) {
+				error("Please specify a single .skel or .json file.");
+				return;
+			}
+
+			if (atlases != 1) {
+				error("Please specify a single .atlas file.");
+				return;
+			}
+
+			var filesToLoad = files.length;
+			var dataUrls = {};
+			for (var i = 0; i < files.length; i++) {
+				var file = files[i];
+				var reader = new FileReader();
+				reader.onload = function(file) {
+					return function(dataUrl) {
+						console.log("Loaded " + file.name);
+						dataUrls[file.name] = dataUrl.target.result;
+						filesToLoad--;
+						if (filesToLoad == 0) {
+							var data = {
+								dataUrls: dataUrls,
+								jsonFile: jsonFile,
+								skelFile: skelFile,
+								atlasFile: atlasFile
+							};
+							var version = data.version = Loader.getSkeletonVersion(data);
+							data.majorVersion = parseInt(version.split("\.")[0]);
+							data.minorVersion = parseInt(version.split("\.")[1]);
+							data.patchVersion = parseInt(version.split("\.")[2]);
+							success(data);
+						}
+					};
+				}(file);
+				reader.onerror = function () {
+					error("Sorry, couldn't load all files.");
+				}
+				reader.readAsDataURL(file);
+			}
+		}
+
+		Loader.getSkeletonVersion = function (data) {
+			var jsonFile = data.jsonFile;
+			var skelFile = data.skelFile;
+			var dataUrls = data.dataUrls;
+			if (jsonFile) {
+				var json = JSON.parse(atob(dataUrls[jsonFile].split(',')[1]));
+				return json.skeleton.spine;
+			} else {
+				var bytes = atob(dataUrls[skelFile].split(',')[1]);
+				var array = new Uint8Array(new ArrayBuffer(bytes.length));
+				for (var i = 0; i < bytes.length; i++) {
+					array[i] = bytes.charCodeAt(i);
+				}
+
+				var input = new BinaryInput(array);
+				input.readString();
+				var version = input.readString();
+				return version;
+			}
+		}
+
+		Loader.loadJavaScript = function (url, success, error) {
+			var script = document.createElement('script');
+			script.setAttribute('src', url);
+			script.setAttribute('type', 'text/javascript');
+			script.onload = success;
+			script.onerror = error;
+			document.getElementsByTagName("head")[0].appendChild(script);
+		};
+
+		Loader.loadStyle = function(url, success, error) {
+			var style = document.createElement('link');
+			style.setAttribute('href', url);
+			style.setAttribute('rel', 'stylesheet');
+			style.onload = success;
+			style.onerror = error;
+			document.getElementsByTagName("head")[0].appendChild(style);
+		};
+
+		var BinaryInput = (function () {
+			function BinaryInput(data, strings, index, buffer) {
+				if (strings === void 0) { strings = new Array(); }
+				if (index === void 0) { index = 0; }
+				if (buffer === void 0) { buffer = new DataView(data.buffer); }
+				this.index = index;
+				this.buffer = buffer;
+			}
+
+			BinaryInput.prototype.readByte = function () {
+				return this.buffer.getInt8(this.index++);
+			};
+
+			BinaryInput.prototype.readInt = function (optimizePositive) {
+				var b = this.readByte();
+				var result = b & 0x7F;
+				if ((b & 0x80) != 0) {
+					b = this.readByte();
+					result |= (b & 0x7F) << 7;
+					if ((b & 0x80) != 0) {
+						b = this.readByte();
+						result |= (b & 0x7F) << 14;
+						if ((b & 0x80) != 0) {
+							b = this.readByte();
+							result |= (b & 0x7F) << 21;
+							if ((b & 0x80) != 0) {
+								b = this.readByte();
+								result |= (b & 0x7F) << 28;
+							}
+						}
+					}
+				}
+				return optimizePositive ? result : ((result >>> 1) ^ -(result & 1));
+			};
+
+			BinaryInput.prototype.readString = function () {
+				var byteCount = this.readInt(true);
+				switch (byteCount) {
+					case 0:
+						return null;
+					case 1:
+						return "";
+				}
+				byteCount--;
+				var chars = "";
+				var charCount = 0;
+				for (var i = 0; i < byteCount;) {
+					var b = this.readByte();
+					switch (b >> 4) {
+						case 12:
+						case 13:
+							chars += String.fromCharCode(((b & 0x1F) << 6 | this.readByte() & 0x3F));
+							i += 2;
+							break;
+						case 14:
+							chars += String.fromCharCode(((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F));
+							i += 3;
+							break;
+						default:
+							chars += String.fromCharCode(b);
+							i++;
+					}
+				}
+				return chars;
+			};
+			return BinaryInput;
+		}());
+
+		return Loader;
+	}());
+	spineGenerator.Loader = Loader;
+}(spineGenerator || (spineGenerator = {})));

+ 66 - 0
spine-ts/player/example/generator/ui.js

@@ -0,0 +1,66 @@
+var spineGenerator;
+
+(function (spineGenerator) {
+	var UI = (function () {
+		function UI(dropZone, multiple, acceptedExtensions, callback) {
+		}
+
+		UI.createElement = function (parent, html) {
+			parent.insertAdjacentHTML("beforeend", html);
+			return parent.lastChild;
+		}
+
+		UI.clear = function(element) {
+			element.innerHTML = "";
+		}
+
+		UI.hide = function(element) {
+			element.__oldDisplay = element.style.display;
+			element.style.display = "none";
+		}
+
+		UI.show = function(element, display) {
+			if (display) element.style.display = display;
+			else if (element.__oldDisplay) element.style.display = element.__oldDisplay;
+			else element.style.display = "block";
+		}
+
+		return UI;
+	}());
+	spineGenerator.UI = UI;
+}(spineGenerator || (spineGenerator = {})));
+
+(function (spineGenerator) {
+	var UI = spineGenerator.UI;
+	var DropZone = (function () {
+		function DropZone(dropZone, multiple, acceptedExtensions, callback) {
+			var fileButton = this.fileButton = UI.createElement(dropZone,
+				`<input style="display:none;" type="file" ${multiple?"multiple":""} accept="${acceptedExtensions}"/>`);
+
+			dropZone.onclick = function() {
+				fileButton.click();
+			};
+			dropZone.addEventListener("dragenter", function  (event) {
+				event.stopPropagation();
+				event.preventDefault();
+			}, false);
+			dropZone.addEventListener("dragover", function  (event) {
+				event.stopPropagation();
+				event.preventDefault();
+			}, false);
+			dropZone.addEventListener("drop", function  (event) {
+				event.stopPropagation();
+				event.preventDefault();
+
+				loadFiles(event.dataTransfer.files);
+			}, false);
+
+			fileButton.onchange = function () {
+				callback(fileButton.files);
+				fileButton.value = "";
+			};
+		}
+		return DropZone;
+	}());
+	spineGenerator.UI.DropZone = DropZone;
+}(spineGenerator || (spineGenerator = {})));