◆少前百科是非盈利性、非官方的少女前线维基百科。 ◆如果您发现某些内容错误/空缺,请勇于修正/添加!参与进来其实很容易!点这里 加入少前百科。 ◆有任何意见、建议、纠错,欢迎在 GFwiki:反馈与建议 提出和讨论。编辑事务讨论QQ群:597764980,微博@GFwiki少前百科 ◆To foreigners,You can use twitter to contact us. |
“MediaWiki:Gadget-chibiAnimation.js”的版本间的差异
(测试) |
(fixed bendDirection setting.) |
||
(未显示同一用户的30个中间版本) | |||
第40行: | 第40行: | ||
console.error("Loading needed libraries failed"); | console.error("Loading needed libraries failed"); | ||
}); | }); | ||
− | } | + | } |
function initGirl() { | function initGirl() { | ||
第46行: | 第46行: | ||
console.log("Init animation..."); | console.log("Init animation..."); | ||
chibiDivs.each(function() { | chibiDivs.each(function() { | ||
− | var | + | // you can set your drawing scale through adding attr |
+ | var baseViewWidth = 900; | ||
+ | var baseViewHeight = 900; | ||
+ | if($(this).attr("data-view-width")) baseViewWidth = Number($(this).attr("data-view-width")); | ||
+ | if($(this).attr("data-view-height")) baseViewHeight = Number($(this).attr("data-view-height")); | ||
+ | var chibiAnimationBaseview = new BaseView(baseViewWidth, baseViewHeight); | ||
+ | |||
chibiAnimationBaseview.start(); | chibiAnimationBaseview.start(); | ||
var currentDiv = $(this); | var currentDiv = $(this); | ||
第55行: | 第61行: | ||
}; | }; | ||
− | var requestedScale = currentDiv.data(" | + | var requestedScale = currentDiv.attr("data-chibiScale"); |
+ | var requestedHeightPosition = currentDiv.attr("data-chibiHeightPosition"); | ||
var renderView = $(chibiAnimationBaseview.getRenderer().view); | var renderView = $(chibiAnimationBaseview.getRenderer().view); | ||
renderView.addClass("chibiAnimation"); | renderView.addClass("chibiAnimation"); | ||
− | renderView.on('costume_changed', function(event, costumeSuffix ,tdollname) {console.log( | + | renderView.on('costume_changed', function(event, costumeSuffix ,tdollname) { |
+ | console.log("costume_changing", tdollname, costumeSuffix) | ||
var loadingDivs = $(event.target).closest('.tdoll_chibi,.chibiAnimationContainer'); | var loadingDivs = $(event.target).closest('.tdoll_chibi,.chibiAnimationContainer'); | ||
loadingDivs.addClass("loading"); | loadingDivs.addClass("loading"); | ||
− | if(tdollname!=null){var tdollId = tdollname.replace(" ", "_")}else{var tdollId = currentDiv. | + | if(tdollname!=null){var tdollId = tdollname.replace(" ", "_")}else{var tdollId = currentDiv.attr("data-tdoll-id").replace(" ", "_");}; |
− | loadingDivs.attr('data-tdoll-costume', costumeSuffix | + | loadingDivs.attr('data-tdoll-costume', costumeSuffix); |
var dormVariant = loadingDivs.find('.chibiDormSwitcher input').is(':checked'); | var dormVariant = loadingDivs.find('.chibiDormSwitcher input').is(':checked'); | ||
− | loadGirl(chibiAnimationBaseview, tdollId, costumeSuffix, dormVariant, girlLoadedHandler, requestedScale, changeSelect); | + | loadGirl(chibiAnimationBaseview, tdollId, costumeSuffix, dormVariant, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect); |
}); | }); | ||
第74行: | 第82行: | ||
e.stopPropagation(); | e.stopPropagation(); | ||
chibiAnimationBaseview.nextAnimation($(this).parent().children("select.chibiAnimationSelect")); | chibiAnimationBaseview.nextAnimation($(this).parent().children("select.chibiAnimationSelect")); | ||
+ | }); | ||
+ | |||
+ | var screencapLink = $('<a></a>'); | ||
+ | screencapLink.addClass('chibiScreenshotButton').addClass("chibiButton"); | ||
+ | screencapLink.prop("href", "javascript:void(0);"); | ||
+ | screencapLink.prop("target", "_blank"); | ||
+ | screencapLink.prop("rel", "noopener"); | ||
+ | screencapLink.prop("download", "chibi_screenshot.png"); | ||
+ | screencapLink.on('click', function(e) { | ||
+ | var canv = currentDiv.find('canvas')[0]; | ||
+ | var dataURL = canv.toDataURL('image/png'); | ||
+ | e.target.href = dataURL; | ||
}); | }); | ||
var rePlayButton = $("<div></div>"); | var rePlayButton = $("<div></div>"); | ||
− | rePlayButton.addClass("chibiAnimationRePlay"); | + | rePlayButton.addClass("chibiAnimationRePlay").addClass("chibiButton"); |
rePlayButton.click(function(){ | rePlayButton.click(function(){ | ||
chibiAnimationBaseview.replay(); | chibiAnimationBaseview.replay(); | ||
第83行: | 第103行: | ||
var changeSelect = $("<select></select>"); | var changeSelect = $("<select></select>"); | ||
− | changeSelect.addClass("chibiAnimationSelect") | + | changeSelect.addClass("chibiAnimationSelect").addClass("chibiButton"); |
− | |||
− | |||
changeSelect.change(function(e){ | changeSelect.change(function(e){ | ||
chibiAnimationBaseview.selectAnimation(this.value); | chibiAnimationBaseview.selectAnimation(this.value); | ||
第91行: | 第109行: | ||
var dormSliderButton = $("<div></div>"); | var dormSliderButton = $("<div></div>"); | ||
− | dormSliderButton.addClass("chibiDormButton"); | + | dormSliderButton.addClass("chibiDormButton").addClass("chibiButton"); |
dormSliderButton.addClass("stateoff"); | dormSliderButton.addClass("stateoff"); | ||
dormSliderButton.click( function() { | dormSliderButton.click( function() { | ||
第105行: | 第123行: | ||
var tdollChibiDiv = currentDormButton.closest('.tdoll_chibi,.chibiAnimationContainer'); | var tdollChibiDiv = currentDormButton.closest('.tdoll_chibi,.chibiAnimationContainer'); | ||
+ | var tdollChibiDivCostume = tdollChibiDiv.attr('data-tdoll-costume') || ""; | ||
+ | var tdollId = tdollChibiDiv.attr("data-tdoll-id").replace(" ", "_"); | ||
tdollChibiDiv.addClass("loading"); | tdollChibiDiv.addClass("loading"); | ||
− | + | loadGirl(chibiAnimationBaseview, tdollId, tdollChibiDivCostume, futureEnabledState, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect); | |
− | |||
− | |||
− | loadGirl(chibiAnimationBaseview, tdollId, tdollChibiDivCostume, futureEnabledState, girlLoadedHandler, requestedScale, changeSelect); | ||
}); | }); | ||
var downloadButton = $("<div></div>"); | var downloadButton = $("<div></div>"); | ||
− | downloadButton.addClass("chibiAnimationDownload"); | + | downloadButton.addClass("chibiAnimationDownload").addClass("chibiButton"); |
downloadButton.click(function(){ | downloadButton.click(function(){ | ||
− | $(this).parent(". | + | $(this).parent(".chibiAnimationControlDiv").parent().append("<div class=\"chibiAnimationBlock\"></div>"); |
− | chibiAnimationBaseview.download($(this).parent().children("canvas.chibiAnimation")); | + | chibiAnimationBaseview.download($(this).parent(".chibiAnimationControlDiv").parent().children("canvas.chibiAnimation")); |
}); | }); | ||
var animationInfo = $("<div></div>"); | var animationInfo = $("<div></div>"); | ||
− | animationInfo.addClass("chibiAnimationInfo") | + | animationInfo.addClass("chibiAnimationInfo").addClass("chibiButton"); |
− | |||
− | |||
animationInfo.click(function(){ | animationInfo.click(function(){ | ||
var newInfoDiv = $("<div></div>"); | var newInfoDiv = $("<div></div>"); | ||
第141行: | 第156行: | ||
newInfoDivClose.html("×"); | newInfoDivClose.html("×"); | ||
newInfoDivClose.click(function(e){ | newInfoDivClose.click(function(e){ | ||
− | $ | + | $("body").children(".chibiAnimationInfoShow").remove(); |
}); | }); | ||
newInfoDiv.append(newInfoDivClose); | newInfoDiv.append(newInfoDivClose); | ||
− | + | $("body").append(newInfoDiv); | |
}); | }); | ||
+ | var animationControlDiv = $("<div></div>"); | ||
+ | animationControlDiv.addClass("chibiAnimationControlDiv"); | ||
currentDiv.empty(); | currentDiv.empty(); | ||
currentDiv.append(clickArea); | currentDiv.append(clickArea); | ||
− | if (currentDiv.attr("data-tdoll- | + | if (!currentDiv.attr("data-tdoll-hidebuttonbox")) currentDiv.append(animationControlDiv); |
− | + | else if (currentDiv.attr("data-tdoll-hidebuttonbox") != 'true') currentDiv.append(animationControlDiv); | |
− | currentDiv.append( | + | |
− | currentDiv.append( | + | animationControlDiv.append(screencapLink); |
− | + | animationControlDiv.append(downloadButton); | |
+ | animationControlDiv.append(animationInfo); | ||
+ | animationControlDiv.append(rePlayButton); | ||
+ | if (!currentDiv.attr("data-tdoll-hidedormbutton")) animationControlDiv.append(dormSliderButton); | ||
+ | else if (currentDiv.attr("data-tdoll-hidedormbutton") != 'true') animationControlDiv.append(dormSliderButton); | ||
+ | animationControlDiv.append(changeSelect); | ||
+ | |||
currentDiv.append(renderView[0]); | currentDiv.append(renderView[0]); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
if(!currentDiv.data('tdollId')) { | if(!currentDiv.data('tdollId')) { | ||
var rendererDiv = $('#cancan'); | var rendererDiv = $('#cancan'); | ||
第179行: | 第189行: | ||
window.loadCommander(rendererDiv, baseview, selectedHead, selectedBody, selectedFeet); | window.loadCommander(rendererDiv, baseview, selectedHead, selectedBody, selectedFeet); | ||
} | } | ||
− | var tdollId = currentDiv. | + | var tdollId = currentDiv.attr("data-tdoll-id").replace(" ", "_"); |
− | loadGirl(chibiAnimationBaseview, tdollId, "", false, girlLoadedHandler, requestedScale, changeSelect); | + | loadGirl(chibiAnimationBaseview, tdollId, "", false, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect); |
}); | }); | ||
} | } | ||
− | function loadGirl(view, id, costumeSuffix, dormVersion, callback, requestedScale, changeSelect){ | + | function loadGirl(view, id, costumeSuffix, dormVersion, callback, requestedScale, requestedHeightPosition, changeSelect){ |
var costumeName = id; | var costumeName = id; | ||
costumeName = costumeName + costumeSuffix | costumeName = costumeName + costumeSuffix | ||
第198行: | 第208行: | ||
view.clean(); | view.clean(); | ||
− | view.addSpinePlayer(p, requestedScale); | + | view.addSpinePlayer(p, requestedScale, requestedHeightPosition); |
callback(); | callback(); | ||
第244行: | 第254行: | ||
var cpp = window.gfUtils.createWikiPathPart; | var cpp = window.gfUtils.createWikiPathPart; | ||
− | var basePath = " | + | var basePath = "../images/"; |
var ret = { | var ret = { | ||
第336行: | 第346行: | ||
} | } | ||
− | + | SkeletonBinary.prototype = { | |
− | + | BlendMode : ["normal", "additive", "multiply", "screen"], | |
− | + | AttachmentType : ["region", "boundingbox", "mesh", "skinnedmesh"], | |
− | + | ||
− | + | readByte : function(){ | |
− | + | return this.nextNum < this.data.length ? this.data[this.nextNum++] : null; | |
− | + | }, | |
− | + | readSByte : function(){ | |
− | + | var bitwidth = 8; | |
− | + | var val = this.readByte(); | |
− | + | var isnegative = val & (1 << (bitwidth - 1)); | |
− | + | var boundary = (1 << bitwidth); | |
− | + | var minval = -boundary; | |
− | + | var mask = boundary - 1; | |
− | + | return isnegative ? minval + (val & mask) : val; | |
− | + | }, | |
− | + | readBoolean : function(){ | |
− | + | return this.readByte() != 0; | |
− | + | }, | |
− | + | readShort : function(){ | |
− | + | return (this.readByte() << 8) | this.readByte(); | |
− | + | }, | |
− | + | readInt : function(optimizePositive){ | |
− | + | if(typeof optimizePositive === 'undefined'){ | |
− | + | return (this.readByte() << 24) | (this.readByte() << 16) | (this.readByte() << 8) | this.readByte(); | |
− | + | } | |
− | + | 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)); | |
− | + | }, | |
− | + | bytes2Float32 : function(bytes){ | |
− | + | var sign = (bytes & 0x80000000) ? -1 : 1; | |
− | + | var exponent = ((bytes >> 23) & 0xFF) - 127; | |
− | + | var significand = (bytes & ~(-1 << 23)); | |
− | + | ||
− | + | if (exponent == 128) | |
− | + | return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY); | |
− | + | ||
− | + | if (exponent == -127) { | |
− | + | if (significand == 0) return sign * 0.0; | |
− | + | exponent = -126; | |
− | + | significand /= (1 << 22); | |
− | + | } else significand = (significand | (1 << 23)) / (1 << 23); | |
− | + | ||
− | + | return sign * significand * Math.pow(2, exponent); | |
− | + | }, | |
− | + | readFloat : function(){ | |
− | + | return this.bytes2Float32((this.readByte()<<24) + (this.readByte()<<16) + (this.readByte()<<8) + (this.readByte()<<0)); | |
− | + | }, | |
− | + | readFloatArray : function(){ | |
− | + | var n = this.readInt(true); | |
− | + | var array = new Array(n); | |
− | + | if(this.scale == 1){ | |
− | + | for(var i = 0; i < n; i++){ | |
− | + | array[i] = this.readFloat(); | |
− | + | } | |
− | + | }else{ | |
− | + | for(var i = 0; i < n; i++){ | |
− | + | array[i] = this.readFloat() * this.scale; | |
− | + | } | |
− | + | } | |
− | + | return array; | |
− | + | }, | |
− | + | readShortArray : function(){ | |
− | + | var n = this.readInt(true); | |
− | + | var array = new Array(n); | |
− | + | for(var i = 0; i < n; i++){ | |
− | + | array[i] = this.readShort(); | |
− | + | } | |
− | + | return array; | |
− | + | }, | |
− | + | readIntArray : function(){ | |
− | + | var n = this.readInt(true); | |
− | + | var array = new Array(n); | |
− | + | for(var i = 0; i < n; i++) | |
− | + | array[i] = this.readInt(true); | |
− | + | return array; | |
− | + | }, | |
− | + | readHex : function(){ | |
− | + | var hex = this.readByte().toString(16); | |
− | + | return hex.length == 2 ? hex : '0' + hex; | |
− | + | }, | |
− | + | readColor : function(){ | |
− | + | return this.readHex() + this.readHex() + this.readHex() + this.readHex(); | |
− | + | }, | |
− | + | readUtf8_slow : function(charCount, charIndex, b){ | |
− | + | while(true){ | |
− | + | switch (b >> 4){ | |
− | + | case 0: | |
− | + | case 1: | |
− | + | case 2: | |
− | + | case 3: | |
− | + | case 4: | |
− | + | case 5: | |
− | + | case 6: | |
− | + | case 7: | |
− | + | this.chars += String.fromCharCode(b); | |
− | + | break; | |
− | + | case 12: | |
− | + | case 13: | |
− | + | this.chars += String.fromCharCode((b & 0x1F) << 6 | this.readByte() & 0x3F); | |
− | + | break; | |
− | + | case 14: | |
− | + | this.chars += String.fromCharCode((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F); | |
− | + | break; | |
− | + | } | |
− | + | if (++charIndex >= charCount) break; | |
− | + | b = this.readByte() & 0xFF; | |
− | + | } | |
− | + | }, | |
− | + | readString : function(){ | |
− | + | var charCount = this.readInt(this, true); | |
− | + | switch(charCount){ | |
− | + | case 0: | |
− | + | return null; | |
− | + | case 1: | |
− | + | return ""; | |
− | + | } | |
− | + | charCount--; | |
− | + | this.chars = ""; | |
− | + | var b = 0; | |
− | + | var charIndex = 0; | |
− | + | while (charIndex < charCount){ | |
− | + | b = this.readByte(); | |
− | + | if (b > 127) | |
− | + | break; | |
− | + | this.chars += String.fromCharCode(b); | |
− | + | charIndex++; | |
− | + | } | |
− | + | if (charIndex < charCount) | |
− | + | this.readUtf8_slow(charCount, charIndex, b); | |
− | + | return this.chars; | |
− | + | }, | |
− | + | initJson : function(){ | |
− | + | this.json.skeleton = {}; | |
− | + | var skeleton = this.json.skeleton; | |
− | + | skeleton.hash = this.readString(); | |
− | + | if(skeleton.hash.length == 0) | |
− | + | skeleton.hash = null; | |
− | + | skeleton.spine = this.readString(); | |
− | + | if(skeleton.spine.length == 0) | |
− | + | skeleton.spine = null; | |
− | + | skeleton.width = this.readFloat(); | |
− | + | skeleton.height = this.readFloat(); | |
− | + | var nonessential = this.readBoolean(); | |
− | + | if(nonessential){ | |
− | + | skeleton.images = this.readString(); | |
− | + | if(skeleton.images.length == 0) | |
− | + | skeleton.images = null; | |
− | + | } | |
− | + | ||
− | + | //Bones. | |
− | + | this.json.bones = new Array(this.readInt(true)); | |
− | + | var bones = this.json.bones; | |
− | + | for(var i = 0; i < bones.length; i++){ | |
− | + | var boneData = {}; | |
− | + | boneData.name = this.readString(); | |
− | + | boneData.parent = null; | |
− | + | var parentIndex = this.readInt(true) - 1; | |
− | + | if(parentIndex != -1) | |
− | + | boneData.parent = bones[parentIndex].name; | |
− | + | boneData.x = this.readFloat() * this.scale; | |
− | + | boneData.y = this.readFloat() * this.scale; | |
− | + | boneData.scaleX = this.readFloat(); | |
− | + | boneData.scaleY = this.readFloat(); | |
− | + | boneData.rotation = this.readFloat(); | |
− | + | boneData.length = this.readFloat() * this.scale; | |
− | + | boneData.flipX = this.readBoolean(); | |
− | + | boneData.flipY = this.readBoolean(); | |
− | + | boneData.inheritScale = this.readBoolean(); | |
− | + | boneData.inheritRotation = this.readBoolean(); | |
− | + | ||
− | + | if(nonessential){ | |
− | + | boneData.color = this.readColor(); | |
− | + | } | |
− | + | bones[i] = boneData; | |
− | + | } | |
− | + | ||
− | + | // IK constraints. | |
− | + | this.json.ik = new Array(this.readInt(true)); | |
− | + | var ik = this.json.ik; | |
− | + | for(var i = 0; i < ik.length; i++){ | |
− | + | var ikConstraints = {}; | |
− | + | ikConstraints.name = this.readString(); | |
− | + | ikConstraints.bones = new Array(this.readInt(true)); | |
− | + | for(var j = 0; j < ikConstraints.bones.length; j++){ | |
− | + | ikConstraints.bones[j] = this.json.bones[this.readInt(true)].name; | |
− | + | } | |
− | + | ikConstraints.target = this.json.bones[this.readInt(true)].name; | |
− | + | ikConstraints.mix = this.readFloat(); | |
− | + | ikConstraints.bendPositive = this.readBoolean(); | |
− | + | // Maybe use ReadSByte(); | |
− | + | ik[i] = ikConstraints; | |
− | + | } | |
− | + | ||
− | + | // Slots. | |
− | + | this.json.slots = new Array(this.readInt(true)); | |
− | + | var slots = this.json.slots; | |
− | + | for(var i = 0; i < slots.length; i++){ | |
− | + | var slotData = {}; | |
− | + | slotData.name = this.readString(); | |
− | + | var boneData = this.json.bones[this.readInt(true)]; | |
− | + | slotData.bone = boneData.name; | |
− | + | slotData.color = this.readColor(); | |
− | + | slotData.attachment = this.readString(); | |
− | + | slotData.blend = this.BlendMode[this.readInt(true)]; | |
− | + | slots[i] = slotData; | |
− | + | } | |
− | + | ||
− | + | // Default skin. | |
− | + | this.json.skins = {}; | |
− | + | this.json.skinsName = new Array(); | |
− | + | var skins = this.json.skins; | |
− | + | var defaultSkin = this.readSkin("default", nonessential); | |
− | + | if(defaultSkin != null){ | |
− | + | skins["default"] = defaultSkin; | |
− | + | this.json.skinsName.push("default"); | |
− | + | } | |
− | + | ||
− | + | // Skin. | |
− | + | for(var i = 0, n = this.readInt(true); i < n; i++){ | |
− | + | var skinName = this.readString(); | |
− | + | var skin = this.readSkin(skinName, nonessential); | |
− | + | skins[skinName] = skin; | |
− | + | this.json.skinsName.push("skinName"); | |
− | + | } | |
− | + | ||
− | + | // Events. | |
− | + | this.json.events = []; | |
− | + | this.json.eventsName = []; | |
− | + | var events = this.json.events; | |
− | + | for(var i = 0, n = this.readInt(true); i < n; i++){ | |
− | + | var eventName = this.readString(); | |
− | + | var event = {}; | |
− | + | event.int = this.readInt(false); | |
− | + | event.float = this.readFloat(); | |
− | + | event.string = this.readString(); | |
− | + | events[eventName] = event; | |
− | + | this.json.eventsName[i] = eventName; | |
− | + | } | |
− | + | ||
− | + | // Animations. | |
− | + | this.json.animations = {}; | |
− | + | var animations = this.json.animations; | |
− | + | for(var i = 0, n = this.readInt(true); i < n; i++){ | |
− | + | var animationName = this.readString(); | |
− | + | var animation = this.readAnimation(animationName); | |
− | + | animations[animationName] = animation; | |
− | + | } | |
− | + | ||
− | + | }, | |
− | + | readSkin : function(skinName, nonessential){ | |
− | + | var slotCount = this.readInt(true); | |
− | + | if(slotCount == 0) | |
− | + | return null; | |
− | + | var skin = {}; | |
− | + | for(var i = 0; i < slotCount; i++){ | |
− | + | var slotIndex = this.readInt(true); | |
− | + | var slot = {}; | |
− | + | for(var j = 0, n = this.readInt(true); j < n; j++){ | |
− | + | var name = this.readString(); | |
− | + | var attachment = this.readAttachment(name, nonessential); | |
− | + | slot[name] = attachment; | |
− | + | } | |
− | + | skin[this.json.slots[slotIndex].name] = slot; | |
− | + | } | |
− | + | return skin; | |
− | + | }, | |
− | + | readAttachment : function(attachmentName, nonessential){ | |
− | + | var name = this.readString(); | |
− | + | if(name == null) | |
− | + | name = attachmentName; | |
− | + | switch(this.AttachmentType[this.readByte()]){ | |
− | + | case "region": | |
− | + | var path = this.readString(); | |
− | + | if(path == null) | |
− | + | path = name; | |
− | + | var region = {}; | |
− | + | region.type = "region"; | |
− | + | region.name = name; | |
− | + | region.path = path; | |
− | + | region.x = this.readFloat() * this.scale; | |
− | + | region.y = this.readFloat() * this.scale; | |
− | + | region.scaleX = this.readFloat(); | |
− | + | region.scaleY = this.readFloat(); | |
− | + | region.rotation = this.readFloat(); | |
− | + | region.width = this.readFloat() * this.scale; | |
− | + | region.height = this.readFloat() * this.scale; | |
− | + | region.color = this.readColor(); | |
− | + | // Maybe need UpdateOffset() | |
− | + | return region; | |
− | + | case "boundingbox": | |
− | + | var box = {}; | |
− | + | box.type = "boundingbox"; | |
− | + | box.name = name; | |
− | + | box.vertices = this.readFloatArray(); | |
− | + | // Maybe need vertexCount or color | |
− | + | return box; | |
− | + | case "mesh": | |
− | + | var path = this.readString(); | |
− | + | if(path == null) | |
− | + | path = name; | |
− | + | var mesh = {}; | |
− | + | mesh.type = "mesh"; | |
− | + | mesh.name = name; | |
− | + | mesh.path = path; | |
− | + | mesh.uvs = this.readFloatArray(); | |
− | + | // Maybe need updateUVs() | |
− | + | mesh.triangles = this.readShortArray(); | |
− | + | mesh.vertices = this.readFloatArray(); | |
− | + | mesh.color = this.readColor(); | |
− | + | mesh.hull = this.readInt(true); | |
− | + | // Maybe need * 2 | |
− | + | if(nonessential){ | |
− | + | mesh.edges = this.readIntArray(); | |
− | + | mesh.width = this.readFloat(); | |
− | + | mesh.height = this.readFloat(); | |
− | + | // Maybe need * scale | |
− | + | } | |
− | + | return mesh; | |
− | + | case "skinnedmesh": | |
− | + | var path = this.readString(); | |
− | + | if(path == null) | |
− | + | path = name; | |
− | + | var skinnedmesh = {}; | |
− | + | skinnedmesh.type = "skinnedmesh"; | |
− | + | skinnedmesh.name = name; | |
− | + | skinnedmesh.path = path; | |
− | + | skinnedmesh.uvs = this.readFloatArray(); | |
− | + | skinnedmesh.triangles = this.readShortArray(); | |
− | + | ||
− | + | skinnedmesh.vertices = new Array(); | |
− | + | var vertexCount = this.readInt(true); | |
− | + | for(var i = 0; i < vertexCount;){ | |
− | + | var boneCount = Math.floor(this.readFloat()); | |
− | + | skinnedmesh.vertices[i++] = boneCount; | |
− | + | for(var nn = i + boneCount * 4; i < nn; i += 4){ | |
− | + | skinnedmesh.vertices[i] = Math.floor(this.readFloat()); | |
− | + | skinnedmesh.vertices[i + 1] = this.readFloat(); | |
− | + | skinnedmesh.vertices[i + 2] = this.readFloat(); | |
− | + | skinnedmesh.vertices[i + 3] = this.readFloat(); | |
− | + | } | |
− | + | } | |
− | + | skinnedmesh.color = this.readColor(); | |
− | + | skinnedmesh.hull = this.readInt(true); | |
− | + | // Maybe need * 2 | |
− | + | if(nonessential){ | |
− | + | skinnedmesh.edges = this.readIntArray(); | |
− | + | skinnedmesh.width = this.readFloat(); | |
− | + | skinnedmesh.height = this.readFloat(); | |
− | + | // Maybe need * scale | |
− | + | } | |
− | + | return skinnedmesh; | |
− | + | } | |
− | + | return null; | |
− | + | }, | |
− | + | readCurve : function(frameIndex, timeline){ | |
− | + | switch(this.readByte()){ | |
− | + | case 1: //CURVE_STEPPED | |
− | + | timeline[frameIndex].curve = "stepped"; | |
− | + | break; | |
− | + | case 2: //CURVE_BEZIER | |
− | + | var cx1 = this.readFloat(); | |
− | + | var cy1 = this.readFloat(); | |
− | + | var cx2 = this.readFloat(); | |
− | + | var cy2 = this.readFloat(); | |
− | + | timeline[frameIndex].curve = [cx1, cy1, cx2, cy2]; | |
− | + | } | |
− | + | }, | |
− | + | readAnimation : function(name){ | |
− | + | var animation = {}; | |
− | + | var scale = this.scale; | |
− | + | var duration = 0; | |
− | + | ||
− | + | // Slot timelines. | |
− | + | var slots = {}; | |
− | + | for(var i = 0, n = this.readInt(true); i < n; i++){ | |
− | + | var slotIndex = this.readInt(true); | |
− | + | var slotMap = {}; | |
− | + | var timeCount = this.readInt(true); | |
− | + | for(var ii = 0; ii < timeCount; ii++){ | |
− | + | var timelineType = this.readByte(); | |
− | + | var frameCount = this.readInt(true); | |
− | + | switch(timelineType){ | |
− | + | case 4: //TIMELINE_COLOR | |
− | + | var timeline = new Array(frameCount); | |
− | + | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | |
− | + | var time = this.readFloat(); | |
+ | var color = this.readColor(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = time; | ||
+ | timeline[frameIndex].color = color; | ||
+ | if(frameIndex < frameCount - 1){ | ||
+ | var str = this.readCurve(frameIndex, timeline); | ||
+ | } | ||
+ | } | ||
+ | slotMap.color = timeline; | ||
+ | duration = Math.max(duration, timeline[frameCount - 1].time); | ||
+ | break; | ||
+ | case 3: //TIMELINE_ATTACHMENT | ||
+ | var timeline = new Array(frameCount); | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var time = this.readFloat(); | ||
+ | var attachmentName = this.readString(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = time; | ||
+ | timeline[frameIndex].name = attachmentName; | ||
+ | } | ||
+ | slotMap.attachment = timeline; | ||
+ | duration = Math.max(duration, timeline[frameCount - 1].time); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | slots[this.json.slots[slotIndex].name] = slotMap; | ||
+ | } | ||
+ | animation.slots = slots; | ||
+ | |||
+ | //// Bone timelines. | ||
+ | var bones = {}; | ||
+ | for(var i = 0, n = this.readInt(true); i < n; i++){ | ||
+ | var boneIndex = this.readInt(true); | ||
+ | var boneMap = {}; | ||
+ | for(var ii = 0, nn = this.readInt(true); ii < nn; ii++){ | ||
+ | var timelineType = this.readByte(); | ||
+ | var frameCount = this.readInt(true); | ||
+ | switch(timelineType){ | ||
+ | case 1: //TIMELINE_ROTATE | ||
+ | var timeline = new Array(frameCount); | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var tltime = this.readFloat(); | ||
+ | var tlangle = this.readFloat(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = tltime; | ||
+ | timeline[frameIndex].angle = tlangle; | ||
+ | if(frameIndex < frameCount - 1){ | ||
+ | this.readCurve(frameIndex, timeline); | ||
+ | } | ||
+ | } | ||
+ | boneMap.rotate = timeline; | ||
+ | duration = Math.max(duration, timeline[frameCount - 1].time); | ||
+ | break; | ||
+ | case 2: //TIMELINE_TRANSLATE | ||
+ | case 0: //TIMELINE_SCALE | ||
+ | var timeline = new Array(frameCount); | ||
+ | var timelineScale = 1; | ||
+ | if(timelineType == 2){ | ||
+ | timelineScale = scale; | ||
+ | } | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var tltime = this.readFloat(); | ||
+ | var tlx = this.readFloat(); | ||
+ | var tly = this.readFloat(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = tltime; | ||
+ | timeline[frameIndex].x = tlx; | ||
+ | timeline[frameIndex].y = tly; | ||
+ | if(frameIndex < frameCount - 1){ | ||
+ | this.readCurve(frameIndex, timeline); | ||
+ | } | ||
+ | } | ||
+ | if(timelineType == 0){ | ||
+ | boneMap.scale = timeline; | ||
+ | }else{ | ||
+ | boneMap.translate = timeline; | ||
+ | } | ||
+ | duration = Math.max(duration, timeline[frameCount - 1].time); | ||
+ | break; | ||
+ | case 5: //TIMELINE_FLIPX | ||
+ | case 6: //TIMELINE_FLIPY | ||
+ | var timeline = new Array(frameCount); | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var tltime = this.readFloat(); | ||
+ | var tlflip = this.readBoolean(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = tltime; | ||
+ | if(timelineType == 5) | ||
+ | timeline[frameIndex].x = tlflip; | ||
+ | else | ||
+ | timeline[frameIndex].y = tlflip; | ||
+ | } | ||
+ | if(timelineType == 5) | ||
+ | boneMap.flipX = timeline; | ||
+ | else | ||
+ | boneMap.flipY = timeline; | ||
+ | duration = Math.max(duration, timeline[frameCount - 1].time); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | bones[this.json.bones[boneIndex].name] = boneMap; | ||
+ | } | ||
+ | animation.bones = bones; | ||
+ | |||
+ | // IK timelines. | ||
+ | var ik = {}; | ||
+ | for(var i = 0, n = this.readInt(true); i < n; i++){ | ||
+ | var ikIndex = this.readInt(true); | ||
+ | var frameCount = this.readInt(true); | ||
+ | var timeline = new Array(frameCount); | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var time = this.readFloat(); | ||
+ | var mix = this.readFloat(); | ||
+ | var bendData = this.readSByte(); | ||
+ | timeline[frameIndex] = {}; | ||
+ | timeline[frameIndex].time = time; | ||
+ | timeline[frameIndex].mix = mix; | ||
+ | timeline[frameIndex].bendPositive = bendData >= 0; | ||
+ | timeline[frameIndex].bendDirection = bendData; | ||
+ | if(frameIndex < frameCount - 1) | ||
+ | this.readCurve(frameIndex, timeline); | ||
+ | } | ||
+ | ik[this.json.ik[ikIndex].name] = timeline; | ||
+ | } | ||
+ | animation.ik = ik; | ||
+ | |||
+ | // FFD timelines. | ||
+ | var ffd = {}; | ||
+ | for(var i = 0, n = this.readInt(true); i < n; i++){ | ||
+ | var skinIndex = this.readInt(true); | ||
+ | var slotMap = {}; | ||
+ | for(var ii = 0, nn = this.readInt(true); ii < nn; ii++){ | ||
+ | var slotIndex = this.readInt(true); | ||
+ | var meshMap = {}; | ||
+ | for(var iii = 0, nnn = this.readInt(true); iii < nnn; iii++){ | ||
+ | var meshName = this.readString(); | ||
+ | var frameCount = this.readInt(true); | ||
+ | var attachment; | ||
+ | var attachments = this.json.skins[this.json.skinsName[skinIndex]][this.json.slots[slotIndex].name]; | ||
+ | for(var attachmentName in attachments){ | ||
+ | if(attachments[attachmentName].name == meshName) | ||
+ | attachment = attachments[attachmentName]; | ||
+ | } | ||
+ | |||
+ | if(!attachment) | ||
+ | console.log("FFD attachment not found: " + meshName); | ||
+ | |||
+ | var timeline = new Array(frameCount); | ||
+ | for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){ | ||
+ | var time = this.readFloat(); | ||
+ | var vertexCount; | ||
+ | if(attachment.type == "mesh"){ | ||
+ | vertexCount = attachment.vertices.length; | ||
+ | }else{ | ||
+ | vertexCount = attachment.uvs.length * 3 * 3; | ||
+ | // This maybe wrong | ||
+ | } | ||
+ | |||
+ | var vertices = new Array(vertexCount); | ||
+ | for (var verticeIdx = 0; verticeIdx < vertexCount; verticeIdx++){ | ||
+ | vertices[verticeIdx] = 0.0; | ||
+ | } | ||
+ | |||
+ | // ToDo: I have no idea why we need this | ||
+ | var bugFixMultiplicator = 0.1; | ||
+ | |||
+ | var end = this.readInt(true); | ||
+ | if (end == 0) { | ||
+ | if (attachment.type == "mesh") { | ||
+ | for (var verticeIdx = 0; verticeIdx < vertexCount; verticeIdx++){ | ||
+ | vertices[verticeIdx] += attachment.vertices[verticeIdx] * bugFixMultiplicator; | ||
+ | } | ||
} | } | ||
− | + | } else { | |
− | + | var start = this.readInt(true); | |
− | + | end += start; | |
− | + | ||
− | + | for(var v = start; v < end; v++){ | |
− | + | vertices[v] = this.readFloat() * scale; | |
− | + | } | |
− | + | ||
− | + | if(attachment.type == "mesh"){ | |
− | + | var meshVertices = attachment.vertices; | |
− | + | for(var v = 0, vn = vertices.length; v < vn; v++){ | |
− | + | vertices[v] += meshVertices[v] * bugFixMultiplicator; | |
− | + | } | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | } | |
− | + | timeline[frameIndex] = {}; | |
− | + | timeline[frameIndex].time = time; | |
− | + | timeline[frameIndex].vertices = vertices; | |
− | + | ||
− | + | if(frameIndex < frameCount - 1) | |
− | + | this.readCurve(frameIndex, timeline); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | + | meshMap[meshName] = timeline; | |
− | + | duration = Math.max(duration, timeline[frameCount - 1].time); | |
− | |||
} | } | ||
− | + | slotMap[this.json.slots[slotIndex].name] = meshMap; | |
− | + | } | |
− | + | ffd[this.json.skinsName[skinIndex]] = slotMap; | |
− | + | } | |
− | + | animation.ffd = ffd; | |
− | + | ||
− | + | // Draw order timeline. | |
− | + | var drawOrderCount = this.readInt(true); | |
− | + | if(drawOrderCount > 0){ | |
− | + | var drawOrders = new Array(drawOrderCount); | |
− | + | // var timeline = new Array(drawOrderCount); | |
− | + | var slotCount = this.json.slots.length; | |
− | + | for(var i = 0; i < drawOrderCount; i++){ | |
− | + | var drawOrderMap = {}; | |
− | + | var offsetCount = this.readInt(true); | |
− | + | // var drawOrder = new Array(slotCount); | |
− | + | // for(var ii = slotCount - 1; ii >= 0; ii--){ | |
+ | // drawOrder[ii] = -1; | ||
+ | // } | ||
+ | // var unchanged = new Array(slotCount - offsetCount); | ||
+ | // var originalIndex = 0, unchangedIndex = 0; | ||
+ | var offsets = new Array(offsetCount); | ||
+ | for(var ii = 0; ii < offsetCount; ii++){ | ||
+ | var offsetMap = {}; | ||
+ | var slotIndex = this.readInt(true); | ||
+ | offsetMap.slot = this.json.slots[slotIndex].name; | ||
+ | // while (originalIndex != slotIndex) | ||
+ | // unchanged[unchangedIndex++] = originalIndex++; | ||
+ | var dooffset = this.readInt(true); | ||
+ | offsetMap.offset = dooffset; | ||
+ | // drawOrder[originalIndex + dooffset] = originalIndex++; | ||
+ | offsets[ii] = offsetMap; | ||
+ | } | ||
+ | drawOrderMap.offsets = offsets; | ||
+ | |||
+ | // while(originalIndex < slotCount) | ||
+ | // unchanged[unchangedIndex++] = originalIndex++; | ||
+ | // for (var ii = slotCount - 1; ii >= 0; ii--){ | ||
+ | // if (drawOrder[ii] == -1) | ||
+ | // drawOrder[ii] = unchanged[--unchangedIndex]; | ||
+ | var tltime = this.readFloat(); | ||
+ | drawOrderMap.time = tltime; | ||
+ | drawOrders[i] = drawOrderMap; | ||
+ | } | ||
+ | duration = Math.max(duration, drawOrders[drawOrderCount - 1].time); | ||
+ | animation.drawOrder = drawOrders; | ||
+ | } | ||
+ | |||
+ | // Event timeline. | ||
+ | var eventCount = this.readInt(true); | ||
+ | if(eventCount > 0){ | ||
+ | var events = new Array(eventCount); | ||
+ | for(var i = 0; i < eventCount; i++){ | ||
+ | var time = this.readFloat(); | ||
+ | var name = this.json.eventsName[this.readInt(true)]; | ||
+ | var eventData = this.json.events[name]; | ||
+ | var e = {}; | ||
+ | e.name = name; | ||
+ | e.int = this.readInt(true); | ||
+ | e.float = this.readFloat(); | ||
+ | e.string = this.readBoolean() ? this.readString() : eventData.string; | ||
+ | e.time = time; | ||
+ | events[i] = e; | ||
+ | } | ||
+ | duration = Math.max(duration, events[eventCount - 1].time); | ||
+ | animation.events = events; | ||
+ | } | ||
+ | return animation; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function SkeletonLoader(path){ | ||
+ | var path = path; | ||
+ | var resources = window.chibiAnimationCache = window.chibiAnimationCache || {}; | ||
+ | var loader = new PIXI.loaders.Loader(path); | ||
+ | var RES_PATH = ['skel', 'json', 'atlas', 'png']; | ||
+ | |||
+ | return { | ||
+ | log : function(l){ | ||
+ | console.log(l + " : SkeletonLoader"); | ||
+ | }, | ||
+ | getfullpath : function(genus, type, dormMode, useDormSpritemap){ | ||
+ | var full_path = ''; | ||
+ | var linkGen = window.gfUtils.createWikiPathPart; | ||
+ | var dormAddition = ""; | ||
+ | if (dormMode) { | ||
+ | dormAddition = "dorm_"; | ||
+ | } | ||
+ | var dormSpritesAddition = useDormSpritemap ? dormAddition : ""; | ||
+ | |||
+ | if (type == "png") | ||
+ | full_path = linkGen(genus + "_chibi_" + dormSpritesAddition + "spritemap.png") + genus + "_chibi_" + dormSpritesAddition + "spritemap.png"; | ||
+ | else if (type == "atlas") | ||
+ | full_path = linkGen(genus + "_chibi_" + dormSpritesAddition + "atlas.txt") + genus + "_chibi_" + dormSpritesAddition + "atlas.txt"; | ||
+ | else if (type == "skel") | ||
+ | full_path = linkGen(genus + "_chibi_" + dormAddition + "skel.skel") + genus + "_chibi_" + dormAddition + "skel.skel"; | ||
+ | else if (type == "json") | ||
+ | full_path = linkGen(genus + "_chibi_" + dormAddition + "skel.txt") + genus + "_chibi_" + dormAddition + "skel.txt"; | ||
+ | return full_path; | ||
+ | }, | ||
+ | load : function(genus, dormMode, successCallback, failureCallback, changeSelect){ | ||
+ | var res_name; | ||
+ | if (typeof genus === "object") { | ||
+ | var regexp = /^(?:.+\/)?(.*)_chibi_.*$/ig; | ||
+ | var match = regexp.exec(genus.png); | ||
+ | res_name = match[1]; | ||
+ | } else { | ||
+ | res_name = genus; | ||
+ | } | ||
+ | |||
+ | var res_cache_name = res_name; | ||
+ | if (dormMode) res_cache_name += "-dorm"; | ||
+ | |||
+ | var precheckHandler = function(skeletonLoaderReference, useDormSpritemap) { | ||
+ | try { | ||
+ | if(!genus){ | ||
+ | this.log("????"); | ||
+ | return ; | ||
+ | } | ||
+ | |||
+ | var res_paths = {}; | ||
+ | |||
+ | if (typeof genus === "object") { | ||
+ | res_paths.json = genus.json; | ||
+ | res_paths.skel = genus.skel; | ||
+ | res_paths.atlas = genus.atlas; | ||
+ | res_paths.png = genus.png; | ||
+ | } else { | ||
+ | for(var i = 0; i < RES_PATH.length; i++){ | ||
+ | res_paths[RES_PATH[i]] = skeletonLoaderReference.getfullpath(genus, RES_PATH[i], dormMode, useDormSpritemap); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (resources.hasOwnProperty(res_cache_name)) { | ||
+ | successCallback(resources[res_cache_name]); | ||
+ | animationControl(changeSelect, resources[res_cache_name]); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (genus == "Destroyer") loader.add(res_cache_name + '-json', res_paths.json, { 'xhrTypr' : 'text' }); // Why is she the only one?! | ||
+ | if (!resources.hasOwnProperty(res_cache_name+'-skel') && genus !== "Destroyer") loader.add(res_cache_name + '-skel', res_paths.skel, { 'xhrType' : 'arraybuffer' }); | ||
+ | if (!resources.hasOwnProperty(res_cache_name+'-atlas')) loader.add(res_cache_name + '-atlas', res_paths.atlas, { 'xhrTypr' : 'text' }); | ||
+ | if (!resources.hasOwnProperty(res_cache_name+'-png')) loader.add(res_cache_name + '-png', res_paths.png, { 'xhrTypr' : 'png' }); | ||
+ | loader.load(function(loader, paramResources) { | ||
+ | try { | ||
+ | var rawSkeletonData; | ||
+ | var rawAtlasData = resources[res_cache_name + '-atlas'] ? resources[res_cache_name + '-atlas'].data : paramResources[res_cache_name + '-atlas'].data; | ||
+ | var rawPngData = resources[res_cache_name + '-png'] ? resources[res_cache_name + '-png'].data : paramResources[res_cache_name + '-png'].data; | ||
+ | |||
+ | if (!resources.hasOwnProperty(res_cache_name)) { | ||
+ | if(paramResources[res_cache_name + '-json']){ | ||
+ | rawSkeletonData = JSON.parse(paramResources[res_cache_name + '-json'].data); | ||
+ | } else { | ||
+ | var skelDataBinaryToUse = resources[res_cache_name + '-skel'] ? resources[res_cache_name + '-skel'].data : paramResources[res_cache_name + '-skel'].data; | ||
+ | resources[res_cache_name + '-skel'] = skelDataBinaryToUse; | ||
+ | var rawdata = skelDataBinaryToUse; | ||
+ | if (rawdata != null && typeof(rawdata) === 'string' && rawdata.charAt(0) === '{') { | ||
+ | // Dirty quickfix if data is json format :) | ||
+ | rawSkeletonData = JSON.parse(rawdata); | ||
+ | } else { | ||
+ | var skel_bin = new SkeletonBinary(); | ||
+ | skel_bin.data = new Uint8Array(rawdata); | ||
+ | skel_bin.initJson(); | ||
+ | rawSkeletonData = skel_bin.json; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var spineAtlas = new PIXI.spine.SpineRuntime.Atlas(rawAtlasData, function(line, callback, pngData) { | ||
+ | if (!(pngData)) { | ||
+ | pngData = rawPngData; | ||
+ | } | ||
+ | callback(new PIXI.BaseTexture(pngData)); | ||
+ | }); | ||
+ | var spineAtlasParser = new PIXI.spine.SpineRuntime.AtlasAttachmentParser(spineAtlas); | ||
+ | var spineJsonParser = new PIXI.spine.SpineRuntime.SkeletonJsonParser(spineAtlasParser); | ||
+ | var skeletonData = spineJsonParser.readSkeletonData(rawSkeletonData, name); | ||
+ | |||
+ | animationControl(changeSelect, skeletonData); | ||
+ | |||
+ | resources[res_cache_name + '-atlas'] = rawAtlasData; | ||
+ | resources[res_cache_name + '-png'] = rawPngData; | ||
+ | resources[res_cache_name] = skeletonData; | ||
+ | } | ||
+ | |||
+ | successCallback(resources[res_cache_name]); | ||
+ | |||
+ | } catch(err) { | ||
+ | failureCallback(err); | ||
+ | } | ||
+ | }); | ||
+ | } catch(err) { | ||
+ | failureCallback(err); | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | var skeletonLoaderReference = this; | ||
+ | if (typeof genus === "object") { | ||
+ | precheckHandler(skeletonLoaderReference, false); | ||
+ | } else { | ||
+ | var urlToCheck = path + window.gfUtils.createWikiPathPart(res_name + "_chibi_dorm_atlas.txt") + res_name + "_chibi_dorm_atlas.txt"; | ||
+ | $.ajax({ | ||
+ | url: urlToCheck, | ||
+ | type:'HEAD', | ||
+ | error: function() { precheckHandler(skeletonLoaderReference, false); }, | ||
+ | success: function() { precheckHandler(skeletonLoaderReference, true); } | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | }; | ||
第1,207行: | 第1,223行: | ||
stage.addChild(element); | stage.addChild(element); | ||
}, | }, | ||
− | addSpinePlayer : function(skeletonData, requestedScale){ | + | addSpinePlayer : function(skeletonData, requestedScale, requestedHeightPosition){ |
var spineplayer = new PIXI.spine.Spine(skeletonData); | var spineplayer = new PIXI.spine.Spine(skeletonData); | ||
var animations = spineplayer.spineData.animations; | var animations = spineplayer.spineData.animations; | ||
− | spineplayer.position.set(width / 2, | + | var heightPosition = height * ((requestedHeightPosition) ? requestedHeightPosition : 0.60); |
+ | spineplayer.position.set(width / 2, heightPosition); | ||
var scaleToUse = 1; | var scaleToUse = 1; | ||
第1,396行: | 第1,413行: | ||
var animationName = animations[currentPlayer.animation_num].name; | var animationName = animations[currentPlayer.animation_num].name; | ||
var recordTime = animations[currentPlayer.animation_num].duration * 1000; | var recordTime = animations[currentPlayer.animation_num].duration * 1000; | ||
− | |||
if(animationName == "victory"){ | if(animationName == "victory"){ | ||
for(animNumber in animations) | for(animNumber in animations) | ||
− | if(animNumber.name == "victoryloop") recordTime += animNumber.duration * 1000 * | + | if(animations[animNumber].name == "victoryloop") recordTime += animations[animNumber].duration * 1000 * 2; |
} | } | ||
第1,416行: | 第1,432行: | ||
var url = URL.createObjectURL(new Blob(data, { type: 'video/webm' })); | var url = URL.createObjectURL(new Blob(data, { type: 'video/webm' })); | ||
var element = document.createElement('a'); | var element = document.createElement('a'); | ||
− | var name_dorm = (canvas.parent( | + | var name_dorm = (canvas.parent().children(".chibiDormButton").hasClass("stateoff")) ? "dorm_" : ""; |
− | var name_all = canvas.parent( | + | var name_all = canvas.parent().attr("data-tdoll-id") + "_" + name_dorm + animations[currentPlayer.animation_num].name; |
element.setAttribute('href', url); | element.setAttribute('href', url); | ||
element.setAttribute('download', name_all); | element.setAttribute('download', name_all); | ||
第1,444行: | 第1,460行: | ||
recorder.stop(); | recorder.stop(); | ||
console.log("Recording end"); | console.log("Recording end"); | ||
− | canvas.parent( | + | canvas.parent().children(".chibiAnimationBlock").remove(); |
}, recordTime); | }, recordTime); | ||
} | } |
2022年3月27日 (日) 16:41的最新版本
RLQ.push(function () {
$(document).ready(function() {
// Maybe if the user switched the animations off, skip init?
if (mw.user.options.get("gadget-chibiAnimation") != 1) {
console.log("Property 'gadget-chibiAnimation != 1'.");
return;
}
var chibiDivs = $(".tdoll_chibi,.chibiAnimationContainer");
console.log("Booting up Chibi Animation Gadget. Containers found: ", chibiDivs.length);
// if this page doesn't contain a chibi animation we skip the init
if (chibiDivs.length < 1) {
return;
}
chibiDivs.addClass("loading");
mw.loader.using(['ext.gadget.md5hasher', 'ext.gadget.pixiLoader']).then(function() {
window.animations.PIXILoader.init().then(function() {
initGirl();
}, function(x,y,z) {
console.error("Loading Spine failed");
chibiDivs.removeClass("loading");
});
}, function(x,y,z) {
console.error("Loading needed libraries failed");
chibiDivs.removeClass("loading");
});
});
});
var chibiDivs = $(".tdoll_chibi,.chibiAnimationContainer");
chibiDivs.addClass("loading");
function loaderload() {
mw.loader.using(['ext.gadget.md5hasher']).then(function() {
initGirl();
}, function() {
console.error("Loading needed libraries failed");
});
}
function initGirl() {
var chibiDivs = $(".tdoll_chibi,.chibiAnimationContainer");
console.log("Init animation...");
chibiDivs.each(function() {
// you can set your drawing scale through adding attr
var baseViewWidth = 900;
var baseViewHeight = 900;
if($(this).attr("data-view-width")) baseViewWidth = Number($(this).attr("data-view-width"));
if($(this).attr("data-view-height")) baseViewHeight = Number($(this).attr("data-view-height"));
var chibiAnimationBaseview = new BaseView(baseViewWidth, baseViewHeight);
chibiAnimationBaseview.start();
var currentDiv = $(this);
currentDiv.data('baseview', chibiAnimationBaseview);
var girlLoadedHandler = function () {
currentDiv.removeClass("loading");
};
var requestedScale = currentDiv.attr("data-chibiScale");
var requestedHeightPosition = currentDiv.attr("data-chibiHeightPosition");
var renderView = $(chibiAnimationBaseview.getRenderer().view);
renderView.addClass("chibiAnimation");
renderView.on('costume_changed', function(event, costumeSuffix ,tdollname) {
console.log("costume_changing", tdollname, costumeSuffix)
var loadingDivs = $(event.target).closest('.tdoll_chibi,.chibiAnimationContainer');
loadingDivs.addClass("loading");
if(tdollname!=null){var tdollId = tdollname.replace(" ", "_")}else{var tdollId = currentDiv.attr("data-tdoll-id").replace(" ", "_");};
loadingDivs.attr('data-tdoll-costume', costumeSuffix);
var dormVariant = loadingDivs.find('.chibiDormSwitcher input').is(':checked');
loadGirl(chibiAnimationBaseview, tdollId, costumeSuffix, dormVariant, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect);
});
var clickArea = $("<div></div>");
clickArea.addClass("chibiAnimationClickArea");
clickArea.click(function(e){
e.stopPropagation();
chibiAnimationBaseview.nextAnimation($(this).parent().children("select.chibiAnimationSelect"));
});
var screencapLink = $('<a></a>');
screencapLink.addClass('chibiScreenshotButton').addClass("chibiButton");
screencapLink.prop("href", "javascript:void(0);");
screencapLink.prop("target", "_blank");
screencapLink.prop("rel", "noopener");
screencapLink.prop("download", "chibi_screenshot.png");
screencapLink.on('click', function(e) {
var canv = currentDiv.find('canvas')[0];
var dataURL = canv.toDataURL('image/png');
e.target.href = dataURL;
});
var rePlayButton = $("<div></div>");
rePlayButton.addClass("chibiAnimationRePlay").addClass("chibiButton");
rePlayButton.click(function(){
chibiAnimationBaseview.replay();
});
var changeSelect = $("<select></select>");
changeSelect.addClass("chibiAnimationSelect").addClass("chibiButton");
changeSelect.change(function(e){
chibiAnimationBaseview.selectAnimation(this.value);
});
var dormSliderButton = $("<div></div>");
dormSliderButton.addClass("chibiDormButton").addClass("chibiButton");
dormSliderButton.addClass("stateoff");
dormSliderButton.click( function() {
var currentDormButton = $(this);
var futureEnabledState = currentDormButton.hasClass('stateoff');
if(futureEnabledState) {
currentDormButton.addClass('stateon');
currentDormButton.removeClass('stateoff');
} else {
currentDormButton.removeClass('stateon');
currentDormButton.addClass('stateoff');
}
var tdollChibiDiv = currentDormButton.closest('.tdoll_chibi,.chibiAnimationContainer');
var tdollChibiDivCostume = tdollChibiDiv.attr('data-tdoll-costume') || "";
var tdollId = tdollChibiDiv.attr("data-tdoll-id").replace(" ", "_");
tdollChibiDiv.addClass("loading");
loadGirl(chibiAnimationBaseview, tdollId, tdollChibiDivCostume, futureEnabledState, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect);
});
var downloadButton = $("<div></div>");
downloadButton.addClass("chibiAnimationDownload").addClass("chibiButton");
downloadButton.click(function(){
$(this).parent(".chibiAnimationControlDiv").parent().append("<div class=\"chibiAnimationBlock\"></div>");
chibiAnimationBaseview.download($(this).parent(".chibiAnimationControlDiv").parent().children("canvas.chibiAnimation"));
});
var animationInfo = $("<div></div>");
animationInfo.addClass("chibiAnimationInfo").addClass("chibiButton");
animationInfo.click(function(){
var newInfoDiv = $("<div></div>");
newInfoDiv.addClass("chibiAnimationInfoShow");
newInfoDiv.css({"left":(String(window.innerWidth / 2 - 150) + "px")});
newInfoDiv.append("<div class=\"chibiAnimationInfoShowLine\"><div>动画名称<\/div><div>持续时间/s<\/div><div>TimeLine<\/div><\/div>");
for(var i = 0; i < 20; i++){
if(!$(this).attr("data-name" + String(i))) break;
var html_text = "<div class=\"chibiAnimationInfoShowLine\"><div>" + $(this).attr("data-name" + String(i));
html_text += "<\/div><div>" + Number($(this).attr("data-duration" + String(i))).toFixed(5);
html_text += "<\/div><div>" + $(this).attr("data-frame" + String(i)) + "<\/div><\/div>";
newInfoDiv.append(html_text);
}
var newInfoDivClose = $("<div></div>");
newInfoDivClose.addClass("chibiAnimationInfoShowClose");
newInfoDivClose.html("×");
newInfoDivClose.click(function(e){
$("body").children(".chibiAnimationInfoShow").remove();
});
newInfoDiv.append(newInfoDivClose);
$("body").append(newInfoDiv);
});
var animationControlDiv = $("<div></div>");
animationControlDiv.addClass("chibiAnimationControlDiv");
currentDiv.empty();
currentDiv.append(clickArea);
if (!currentDiv.attr("data-tdoll-hidebuttonbox")) currentDiv.append(animationControlDiv);
else if (currentDiv.attr("data-tdoll-hidebuttonbox") != 'true') currentDiv.append(animationControlDiv);
animationControlDiv.append(screencapLink);
animationControlDiv.append(downloadButton);
animationControlDiv.append(animationInfo);
animationControlDiv.append(rePlayButton);
if (!currentDiv.attr("data-tdoll-hidedormbutton")) animationControlDiv.append(dormSliderButton);
else if (currentDiv.attr("data-tdoll-hidedormbutton") != 'true') animationControlDiv.append(dormSliderButton);
animationControlDiv.append(changeSelect);
currentDiv.append(renderView[0]);
if(!currentDiv.data('tdollId')) {
var rendererDiv = $('#cancan');
var selectedHead = $('.commander-sim-option.head option:selected').val();
var selectedBody = $('.commander-sim-option.body option:selected').val();
var selectedFeet = $('.commander-sim-option.feet option:selected').val();
var baseview = rendererDiv.data('baseview');
window.loadCommander(rendererDiv, baseview, selectedHead, selectedBody, selectedFeet);
}
var tdollId = currentDiv.attr("data-tdoll-id").replace(" ", "_");
loadGirl(chibiAnimationBaseview, tdollId, "", false, girlLoadedHandler, requestedScale, requestedHeightPosition, changeSelect);
});
}
function loadGirl(view, id, costumeSuffix, dormVersion, callback, requestedScale, requestedHeightPosition, changeSelect){
var costumeName = id;
costumeName = costumeName + costumeSuffix
console.log("Loading", costumeName);
view.clean();
var sl = new SkeletonLoader("/images/", costumeName);
var successHandler = function(p){
if (p === null) {
return;
}
view.clean();
view.addSpinePlayer(p, requestedScale, requestedHeightPosition);
callback();
};
var failureHandler = function(p){
var textSample = new PIXI.Text('模型未载入', {
"fill": "#f00000",
"font": "20px \"Courier New\", Courier, monospace"
});
textSample['anchor'].set(0.5, 0.5);
textSample.x = view.getRenderer().width / 2;
textSample.y = view.getRenderer().height / 2;
view.clean();
view.addSprite(textSample);
console.log("Failed loading T-Doll Chibi", view, id, costumeSuffix, dormVersion, p);
callback();
};
sl.load(costumeName, dormVersion, successHandler, failureHandler, changeSelect);
}
window.defineVisibleParts = function(skeleton, startId, endId) {
var startReached = false;
var endReached = endId === null;
for (var i=skeleton.slots.length-1; i>=0; i--) {
var shouldBeVisible = endReached && !startReached;
skeleton.slots[i].a = shouldBeVisible ? 1 : 0;
if (skeleton.slots[i].name == endId) {
endReached = true;
}
if (skeleton.slots[i].name == startId) {
startReached = true;
}
}
};
window.parseCommanderString = function(rawData) {
var files = rawData.split(";");
var cpp = window.gfUtils.createWikiPathPart;
var basePath = "../images/";
var ret = {
baseId: files[2],
skel: basePath + cpp(files[0]) + files[0],
atlas: basePath + cpp(files[1]) + files[1],
png: basePath + cpp(files[2]) + files[2]
};
return ret;
};
window.loadCommander = function(commanderDiv, view, headRaw, bodyRaw, feetRaw){
commanderDiv.addClass('loading');
if (typeof view == "undefined"){}else
{view.clean();}
var sl = new SkeletonLoader(".");
var headGenus = parseCommanderString(headRaw);
var failureHandler = function(p){
commanderDiv.removeClass('loading');
var textSample = new PIXI.Text('模型未载入', {
"fill": "#f00000",
"font": "20px \"Courier New\", Courier, monospace"
});
textSample.anchor.set(0.5, 0.5);
textSample.x = view.getRenderer().width / 2;
textSample.y = view.getRenderer().height / 2;
view.clean();
view.addSprite(textSample);
console.log("Failed loading Commander Chibi", view, headRaw, bodyRaw, feetRaw, p);
};
sl.load(headGenus, false, function(headSkeleton){
if (headSkeleton == null) {
return;
}
var feetGenus = parseCommanderString(feetRaw);
sl.load(feetGenus, false, function(feetSkeleton){
if (feetSkeleton == null) {
return;
}
var bodyGenus = parseCommanderString(bodyRaw);
sl.load(bodyGenus, false, function(bodySkeleton){
if (bodySkeleton == null) {
return;
}
defineVisibleParts(headSkeleton, null, 'FaceLayer');
view.addSpinePlayer(headSkeleton);
defineVisibleParts(bodySkeleton, null, 'BodyLayer');
view.addSpinePlayer(bodySkeleton);
defineVisibleParts(feetSkeleton, null, 'FootLayer');
view.addSpinePlayer(feetSkeleton);
defineVisibleParts(feetSkeleton, 'FootLayer', null);
view.addSpinePlayer(feetSkeleton);
defineVisibleParts(bodySkeleton, 'BodyLayer', 'RHandLayer');
view.addSpinePlayer(bodySkeleton);
defineVisibleParts(headSkeleton, 'FaceLayer', null);
view.addSpinePlayer(headSkeleton);
defineVisibleParts(bodySkeleton, 'RHandLayer', null);
view.addSpinePlayer(bodySkeleton);
// Everything done here
commanderDiv.removeClass("loading");
}, failureHandler);
}, failureHandler);
}, failureHandler);
};
function SkeletonBinary() {
this.data = null;
this.scale = 1;
this.json = {};
this.nextNum = 0;
this.chars = null;
}
SkeletonBinary.prototype = {
BlendMode : ["normal", "additive", "multiply", "screen"],
AttachmentType : ["region", "boundingbox", "mesh", "skinnedmesh"],
readByte : function(){
return this.nextNum < this.data.length ? this.data[this.nextNum++] : null;
},
readSByte : function(){
var bitwidth = 8;
var val = this.readByte();
var isnegative = val & (1 << (bitwidth - 1));
var boundary = (1 << bitwidth);
var minval = -boundary;
var mask = boundary - 1;
return isnegative ? minval + (val & mask) : val;
},
readBoolean : function(){
return this.readByte() != 0;
},
readShort : function(){
return (this.readByte() << 8) | this.readByte();
},
readInt : function(optimizePositive){
if(typeof optimizePositive === 'undefined'){
return (this.readByte() << 24) | (this.readByte() << 16) | (this.readByte() << 8) | this.readByte();
}
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));
},
bytes2Float32 : function(bytes){
var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand == 0) return sign * 0.0;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
},
readFloat : function(){
return this.bytes2Float32((this.readByte()<<24) + (this.readByte()<<16) + (this.readByte()<<8) + (this.readByte()<<0));
},
readFloatArray : function(){
var n = this.readInt(true);
var array = new Array(n);
if(this.scale == 1){
for(var i = 0; i < n; i++){
array[i] = this.readFloat();
}
}else{
for(var i = 0; i < n; i++){
array[i] = this.readFloat() * this.scale;
}
}
return array;
},
readShortArray : function(){
var n = this.readInt(true);
var array = new Array(n);
for(var i = 0; i < n; i++){
array[i] = this.readShort();
}
return array;
},
readIntArray : function(){
var n = this.readInt(true);
var array = new Array(n);
for(var i = 0; i < n; i++)
array[i] = this.readInt(true);
return array;
},
readHex : function(){
var hex = this.readByte().toString(16);
return hex.length == 2 ? hex : '0' + hex;
},
readColor : function(){
return this.readHex() + this.readHex() + this.readHex() + this.readHex();
},
readUtf8_slow : function(charCount, charIndex, b){
while(true){
switch (b >> 4){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
this.chars += String.fromCharCode(b);
break;
case 12:
case 13:
this.chars += String.fromCharCode((b & 0x1F) << 6 | this.readByte() & 0x3F);
break;
case 14:
this.chars += String.fromCharCode((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F);
break;
}
if (++charIndex >= charCount) break;
b = this.readByte() & 0xFF;
}
},
readString : function(){
var charCount = this.readInt(this, true);
switch(charCount){
case 0:
return null;
case 1:
return "";
}
charCount--;
this.chars = "";
var b = 0;
var charIndex = 0;
while (charIndex < charCount){
b = this.readByte();
if (b > 127)
break;
this.chars += String.fromCharCode(b);
charIndex++;
}
if (charIndex < charCount)
this.readUtf8_slow(charCount, charIndex, b);
return this.chars;
},
initJson : function(){
this.json.skeleton = {};
var skeleton = this.json.skeleton;
skeleton.hash = this.readString();
if(skeleton.hash.length == 0)
skeleton.hash = null;
skeleton.spine = this.readString();
if(skeleton.spine.length == 0)
skeleton.spine = null;
skeleton.width = this.readFloat();
skeleton.height = this.readFloat();
var nonessential = this.readBoolean();
if(nonessential){
skeleton.images = this.readString();
if(skeleton.images.length == 0)
skeleton.images = null;
}
//Bones.
this.json.bones = new Array(this.readInt(true));
var bones = this.json.bones;
for(var i = 0; i < bones.length; i++){
var boneData = {};
boneData.name = this.readString();
boneData.parent = null;
var parentIndex = this.readInt(true) - 1;
if(parentIndex != -1)
boneData.parent = bones[parentIndex].name;
boneData.x = this.readFloat() * this.scale;
boneData.y = this.readFloat() * this.scale;
boneData.scaleX = this.readFloat();
boneData.scaleY = this.readFloat();
boneData.rotation = this.readFloat();
boneData.length = this.readFloat() * this.scale;
boneData.flipX = this.readBoolean();
boneData.flipY = this.readBoolean();
boneData.inheritScale = this.readBoolean();
boneData.inheritRotation = this.readBoolean();
if(nonessential){
boneData.color = this.readColor();
}
bones[i] = boneData;
}
// IK constraints.
this.json.ik = new Array(this.readInt(true));
var ik = this.json.ik;
for(var i = 0; i < ik.length; i++){
var ikConstraints = {};
ikConstraints.name = this.readString();
ikConstraints.bones = new Array(this.readInt(true));
for(var j = 0; j < ikConstraints.bones.length; j++){
ikConstraints.bones[j] = this.json.bones[this.readInt(true)].name;
}
ikConstraints.target = this.json.bones[this.readInt(true)].name;
ikConstraints.mix = this.readFloat();
ikConstraints.bendPositive = this.readBoolean();
// Maybe use ReadSByte();
ik[i] = ikConstraints;
}
// Slots.
this.json.slots = new Array(this.readInt(true));
var slots = this.json.slots;
for(var i = 0; i < slots.length; i++){
var slotData = {};
slotData.name = this.readString();
var boneData = this.json.bones[this.readInt(true)];
slotData.bone = boneData.name;
slotData.color = this.readColor();
slotData.attachment = this.readString();
slotData.blend = this.BlendMode[this.readInt(true)];
slots[i] = slotData;
}
// Default skin.
this.json.skins = {};
this.json.skinsName = new Array();
var skins = this.json.skins;
var defaultSkin = this.readSkin("default", nonessential);
if(defaultSkin != null){
skins["default"] = defaultSkin;
this.json.skinsName.push("default");
}
// Skin.
for(var i = 0, n = this.readInt(true); i < n; i++){
var skinName = this.readString();
var skin = this.readSkin(skinName, nonessential);
skins[skinName] = skin;
this.json.skinsName.push("skinName");
}
// Events.
this.json.events = [];
this.json.eventsName = [];
var events = this.json.events;
for(var i = 0, n = this.readInt(true); i < n; i++){
var eventName = this.readString();
var event = {};
event.int = this.readInt(false);
event.float = this.readFloat();
event.string = this.readString();
events[eventName] = event;
this.json.eventsName[i] = eventName;
}
// Animations.
this.json.animations = {};
var animations = this.json.animations;
for(var i = 0, n = this.readInt(true); i < n; i++){
var animationName = this.readString();
var animation = this.readAnimation(animationName);
animations[animationName] = animation;
}
},
readSkin : function(skinName, nonessential){
var slotCount = this.readInt(true);
if(slotCount == 0)
return null;
var skin = {};
for(var i = 0; i < slotCount; i++){
var slotIndex = this.readInt(true);
var slot = {};
for(var j = 0, n = this.readInt(true); j < n; j++){
var name = this.readString();
var attachment = this.readAttachment(name, nonessential);
slot[name] = attachment;
}
skin[this.json.slots[slotIndex].name] = slot;
}
return skin;
},
readAttachment : function(attachmentName, nonessential){
var name = this.readString();
if(name == null)
name = attachmentName;
switch(this.AttachmentType[this.readByte()]){
case "region":
var path = this.readString();
if(path == null)
path = name;
var region = {};
region.type = "region";
region.name = name;
region.path = path;
region.x = this.readFloat() * this.scale;
region.y = this.readFloat() * this.scale;
region.scaleX = this.readFloat();
region.scaleY = this.readFloat();
region.rotation = this.readFloat();
region.width = this.readFloat() * this.scale;
region.height = this.readFloat() * this.scale;
region.color = this.readColor();
// Maybe need UpdateOffset()
return region;
case "boundingbox":
var box = {};
box.type = "boundingbox";
box.name = name;
box.vertices = this.readFloatArray();
// Maybe need vertexCount or color
return box;
case "mesh":
var path = this.readString();
if(path == null)
path = name;
var mesh = {};
mesh.type = "mesh";
mesh.name = name;
mesh.path = path;
mesh.uvs = this.readFloatArray();
// Maybe need updateUVs()
mesh.triangles = this.readShortArray();
mesh.vertices = this.readFloatArray();
mesh.color = this.readColor();
mesh.hull = this.readInt(true);
// Maybe need * 2
if(nonessential){
mesh.edges = this.readIntArray();
mesh.width = this.readFloat();
mesh.height = this.readFloat();
// Maybe need * scale
}
return mesh;
case "skinnedmesh":
var path = this.readString();
if(path == null)
path = name;
var skinnedmesh = {};
skinnedmesh.type = "skinnedmesh";
skinnedmesh.name = name;
skinnedmesh.path = path;
skinnedmesh.uvs = this.readFloatArray();
skinnedmesh.triangles = this.readShortArray();
skinnedmesh.vertices = new Array();
var vertexCount = this.readInt(true);
for(var i = 0; i < vertexCount;){
var boneCount = Math.floor(this.readFloat());
skinnedmesh.vertices[i++] = boneCount;
for(var nn = i + boneCount * 4; i < nn; i += 4){
skinnedmesh.vertices[i] = Math.floor(this.readFloat());
skinnedmesh.vertices[i + 1] = this.readFloat();
skinnedmesh.vertices[i + 2] = this.readFloat();
skinnedmesh.vertices[i + 3] = this.readFloat();
}
}
skinnedmesh.color = this.readColor();
skinnedmesh.hull = this.readInt(true);
// Maybe need * 2
if(nonessential){
skinnedmesh.edges = this.readIntArray();
skinnedmesh.width = this.readFloat();
skinnedmesh.height = this.readFloat();
// Maybe need * scale
}
return skinnedmesh;
}
return null;
},
readCurve : function(frameIndex, timeline){
switch(this.readByte()){
case 1: //CURVE_STEPPED
timeline[frameIndex].curve = "stepped";
break;
case 2: //CURVE_BEZIER
var cx1 = this.readFloat();
var cy1 = this.readFloat();
var cx2 = this.readFloat();
var cy2 = this.readFloat();
timeline[frameIndex].curve = [cx1, cy1, cx2, cy2];
}
},
readAnimation : function(name){
var animation = {};
var scale = this.scale;
var duration = 0;
// Slot timelines.
var slots = {};
for(var i = 0, n = this.readInt(true); i < n; i++){
var slotIndex = this.readInt(true);
var slotMap = {};
var timeCount = this.readInt(true);
for(var ii = 0; ii < timeCount; ii++){
var timelineType = this.readByte();
var frameCount = this.readInt(true);
switch(timelineType){
case 4: //TIMELINE_COLOR
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var time = this.readFloat();
var color = this.readColor();
timeline[frameIndex] = {};
timeline[frameIndex].time = time;
timeline[frameIndex].color = color;
if(frameIndex < frameCount - 1){
var str = this.readCurve(frameIndex, timeline);
}
}
slotMap.color = timeline;
duration = Math.max(duration, timeline[frameCount - 1].time);
break;
case 3: //TIMELINE_ATTACHMENT
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var time = this.readFloat();
var attachmentName = this.readString();
timeline[frameIndex] = {};
timeline[frameIndex].time = time;
timeline[frameIndex].name = attachmentName;
}
slotMap.attachment = timeline;
duration = Math.max(duration, timeline[frameCount - 1].time);
break;
}
}
slots[this.json.slots[slotIndex].name] = slotMap;
}
animation.slots = slots;
//// Bone timelines.
var bones = {};
for(var i = 0, n = this.readInt(true); i < n; i++){
var boneIndex = this.readInt(true);
var boneMap = {};
for(var ii = 0, nn = this.readInt(true); ii < nn; ii++){
var timelineType = this.readByte();
var frameCount = this.readInt(true);
switch(timelineType){
case 1: //TIMELINE_ROTATE
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var tltime = this.readFloat();
var tlangle = this.readFloat();
timeline[frameIndex] = {};
timeline[frameIndex].time = tltime;
timeline[frameIndex].angle = tlangle;
if(frameIndex < frameCount - 1){
this.readCurve(frameIndex, timeline);
}
}
boneMap.rotate = timeline;
duration = Math.max(duration, timeline[frameCount - 1].time);
break;
case 2: //TIMELINE_TRANSLATE
case 0: //TIMELINE_SCALE
var timeline = new Array(frameCount);
var timelineScale = 1;
if(timelineType == 2){
timelineScale = scale;
}
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var tltime = this.readFloat();
var tlx = this.readFloat();
var tly = this.readFloat();
timeline[frameIndex] = {};
timeline[frameIndex].time = tltime;
timeline[frameIndex].x = tlx;
timeline[frameIndex].y = tly;
if(frameIndex < frameCount - 1){
this.readCurve(frameIndex, timeline);
}
}
if(timelineType == 0){
boneMap.scale = timeline;
}else{
boneMap.translate = timeline;
}
duration = Math.max(duration, timeline[frameCount - 1].time);
break;
case 5: //TIMELINE_FLIPX
case 6: //TIMELINE_FLIPY
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var tltime = this.readFloat();
var tlflip = this.readBoolean();
timeline[frameIndex] = {};
timeline[frameIndex].time = tltime;
if(timelineType == 5)
timeline[frameIndex].x = tlflip;
else
timeline[frameIndex].y = tlflip;
}
if(timelineType == 5)
boneMap.flipX = timeline;
else
boneMap.flipY = timeline;
duration = Math.max(duration, timeline[frameCount - 1].time);
break;
}
}
bones[this.json.bones[boneIndex].name] = boneMap;
}
animation.bones = bones;
// IK timelines.
var ik = {};
for(var i = 0, n = this.readInt(true); i < n; i++){
var ikIndex = this.readInt(true);
var frameCount = this.readInt(true);
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var time = this.readFloat();
var mix = this.readFloat();
var bendData = this.readSByte();
timeline[frameIndex] = {};
timeline[frameIndex].time = time;
timeline[frameIndex].mix = mix;
timeline[frameIndex].bendPositive = bendData >= 0;
timeline[frameIndex].bendDirection = bendData;
if(frameIndex < frameCount - 1)
this.readCurve(frameIndex, timeline);
}
ik[this.json.ik[ikIndex].name] = timeline;
}
animation.ik = ik;
// FFD timelines.
var ffd = {};
for(var i = 0, n = this.readInt(true); i < n; i++){
var skinIndex = this.readInt(true);
var slotMap = {};
for(var ii = 0, nn = this.readInt(true); ii < nn; ii++){
var slotIndex = this.readInt(true);
var meshMap = {};
for(var iii = 0, nnn = this.readInt(true); iii < nnn; iii++){
var meshName = this.readString();
var frameCount = this.readInt(true);
var attachment;
var attachments = this.json.skins[this.json.skinsName[skinIndex]][this.json.slots[slotIndex].name];
for(var attachmentName in attachments){
if(attachments[attachmentName].name == meshName)
attachment = attachments[attachmentName];
}
if(!attachment)
console.log("FFD attachment not found: " + meshName);
var timeline = new Array(frameCount);
for(var frameIndex = 0; frameIndex < frameCount; frameIndex++){
var time = this.readFloat();
var vertexCount;
if(attachment.type == "mesh"){
vertexCount = attachment.vertices.length;
}else{
vertexCount = attachment.uvs.length * 3 * 3;
// This maybe wrong
}
var vertices = new Array(vertexCount);
for (var verticeIdx = 0; verticeIdx < vertexCount; verticeIdx++){
vertices[verticeIdx] = 0.0;
}
// ToDo: I have no idea why we need this
var bugFixMultiplicator = 0.1;
var end = this.readInt(true);
if (end == 0) {
if (attachment.type == "mesh") {
for (var verticeIdx = 0; verticeIdx < vertexCount; verticeIdx++){
vertices[verticeIdx] += attachment.vertices[verticeIdx] * bugFixMultiplicator;
}
}
} else {
var start = this.readInt(true);
end += start;
for(var v = start; v < end; v++){
vertices[v] = this.readFloat() * scale;
}
if(attachment.type == "mesh"){
var meshVertices = attachment.vertices;
for(var v = 0, vn = vertices.length; v < vn; v++){
vertices[v] += meshVertices[v] * bugFixMultiplicator;
}
}
}
timeline[frameIndex] = {};
timeline[frameIndex].time = time;
timeline[frameIndex].vertices = vertices;
if(frameIndex < frameCount - 1)
this.readCurve(frameIndex, timeline);
}
meshMap[meshName] = timeline;
duration = Math.max(duration, timeline[frameCount - 1].time);
}
slotMap[this.json.slots[slotIndex].name] = meshMap;
}
ffd[this.json.skinsName[skinIndex]] = slotMap;
}
animation.ffd = ffd;
// Draw order timeline.
var drawOrderCount = this.readInt(true);
if(drawOrderCount > 0){
var drawOrders = new Array(drawOrderCount);
// var timeline = new Array(drawOrderCount);
var slotCount = this.json.slots.length;
for(var i = 0; i < drawOrderCount; i++){
var drawOrderMap = {};
var offsetCount = this.readInt(true);
// var drawOrder = new Array(slotCount);
// for(var ii = slotCount - 1; ii >= 0; ii--){
// drawOrder[ii] = -1;
// }
// var unchanged = new Array(slotCount - offsetCount);
// var originalIndex = 0, unchangedIndex = 0;
var offsets = new Array(offsetCount);
for(var ii = 0; ii < offsetCount; ii++){
var offsetMap = {};
var slotIndex = this.readInt(true);
offsetMap.slot = this.json.slots[slotIndex].name;
// while (originalIndex != slotIndex)
// unchanged[unchangedIndex++] = originalIndex++;
var dooffset = this.readInt(true);
offsetMap.offset = dooffset;
// drawOrder[originalIndex + dooffset] = originalIndex++;
offsets[ii] = offsetMap;
}
drawOrderMap.offsets = offsets;
// while(originalIndex < slotCount)
// unchanged[unchangedIndex++] = originalIndex++;
// for (var ii = slotCount - 1; ii >= 0; ii--){
// if (drawOrder[ii] == -1)
// drawOrder[ii] = unchanged[--unchangedIndex];
var tltime = this.readFloat();
drawOrderMap.time = tltime;
drawOrders[i] = drawOrderMap;
}
duration = Math.max(duration, drawOrders[drawOrderCount - 1].time);
animation.drawOrder = drawOrders;
}
// Event timeline.
var eventCount = this.readInt(true);
if(eventCount > 0){
var events = new Array(eventCount);
for(var i = 0; i < eventCount; i++){
var time = this.readFloat();
var name = this.json.eventsName[this.readInt(true)];
var eventData = this.json.events[name];
var e = {};
e.name = name;
e.int = this.readInt(true);
e.float = this.readFloat();
e.string = this.readBoolean() ? this.readString() : eventData.string;
e.time = time;
events[i] = e;
}
duration = Math.max(duration, events[eventCount - 1].time);
animation.events = events;
}
return animation;
}
}
function SkeletonLoader(path){
var path = path;
var resources = window.chibiAnimationCache = window.chibiAnimationCache || {};
var loader = new PIXI.loaders.Loader(path);
var RES_PATH = ['skel', 'json', 'atlas', 'png'];
return {
log : function(l){
console.log(l + " : SkeletonLoader");
},
getfullpath : function(genus, type, dormMode, useDormSpritemap){
var full_path = '';
var linkGen = window.gfUtils.createWikiPathPart;
var dormAddition = "";
if (dormMode) {
dormAddition = "dorm_";
}
var dormSpritesAddition = useDormSpritemap ? dormAddition : "";
if (type == "png")
full_path = linkGen(genus + "_chibi_" + dormSpritesAddition + "spritemap.png") + genus + "_chibi_" + dormSpritesAddition + "spritemap.png";
else if (type == "atlas")
full_path = linkGen(genus + "_chibi_" + dormSpritesAddition + "atlas.txt") + genus + "_chibi_" + dormSpritesAddition + "atlas.txt";
else if (type == "skel")
full_path = linkGen(genus + "_chibi_" + dormAddition + "skel.skel") + genus + "_chibi_" + dormAddition + "skel.skel";
else if (type == "json")
full_path = linkGen(genus + "_chibi_" + dormAddition + "skel.txt") + genus + "_chibi_" + dormAddition + "skel.txt";
return full_path;
},
load : function(genus, dormMode, successCallback, failureCallback, changeSelect){
var res_name;
if (typeof genus === "object") {
var regexp = /^(?:.+\/)?(.*)_chibi_.*$/ig;
var match = regexp.exec(genus.png);
res_name = match[1];
} else {
res_name = genus;
}
var res_cache_name = res_name;
if (dormMode) res_cache_name += "-dorm";
var precheckHandler = function(skeletonLoaderReference, useDormSpritemap) {
try {
if(!genus){
this.log("????");
return ;
}
var res_paths = {};
if (typeof genus === "object") {
res_paths.json = genus.json;
res_paths.skel = genus.skel;
res_paths.atlas = genus.atlas;
res_paths.png = genus.png;
} else {
for(var i = 0; i < RES_PATH.length; i++){
res_paths[RES_PATH[i]] = skeletonLoaderReference.getfullpath(genus, RES_PATH[i], dormMode, useDormSpritemap);
}
}
if (resources.hasOwnProperty(res_cache_name)) {
successCallback(resources[res_cache_name]);
animationControl(changeSelect, resources[res_cache_name]);
return;
}
if (genus == "Destroyer") loader.add(res_cache_name + '-json', res_paths.json, { 'xhrTypr' : 'text' }); // Why is she the only one?!
if (!resources.hasOwnProperty(res_cache_name+'-skel') && genus !== "Destroyer") loader.add(res_cache_name + '-skel', res_paths.skel, { 'xhrType' : 'arraybuffer' });
if (!resources.hasOwnProperty(res_cache_name+'-atlas')) loader.add(res_cache_name + '-atlas', res_paths.atlas, { 'xhrTypr' : 'text' });
if (!resources.hasOwnProperty(res_cache_name+'-png')) loader.add(res_cache_name + '-png', res_paths.png, { 'xhrTypr' : 'png' });
loader.load(function(loader, paramResources) {
try {
var rawSkeletonData;
var rawAtlasData = resources[res_cache_name + '-atlas'] ? resources[res_cache_name + '-atlas'].data : paramResources[res_cache_name + '-atlas'].data;
var rawPngData = resources[res_cache_name + '-png'] ? resources[res_cache_name + '-png'].data : paramResources[res_cache_name + '-png'].data;
if (!resources.hasOwnProperty(res_cache_name)) {
if(paramResources[res_cache_name + '-json']){
rawSkeletonData = JSON.parse(paramResources[res_cache_name + '-json'].data);
} else {
var skelDataBinaryToUse = resources[res_cache_name + '-skel'] ? resources[res_cache_name + '-skel'].data : paramResources[res_cache_name + '-skel'].data;
resources[res_cache_name + '-skel'] = skelDataBinaryToUse;
var rawdata = skelDataBinaryToUse;
if (rawdata != null && typeof(rawdata) === 'string' && rawdata.charAt(0) === '{') {
// Dirty quickfix if data is json format :)
rawSkeletonData = JSON.parse(rawdata);
} else {
var skel_bin = new SkeletonBinary();
skel_bin.data = new Uint8Array(rawdata);
skel_bin.initJson();
rawSkeletonData = skel_bin.json;
}
}
var spineAtlas = new PIXI.spine.SpineRuntime.Atlas(rawAtlasData, function(line, callback, pngData) {
if (!(pngData)) {
pngData = rawPngData;
}
callback(new PIXI.BaseTexture(pngData));
});
var spineAtlasParser = new PIXI.spine.SpineRuntime.AtlasAttachmentParser(spineAtlas);
var spineJsonParser = new PIXI.spine.SpineRuntime.SkeletonJsonParser(spineAtlasParser);
var skeletonData = spineJsonParser.readSkeletonData(rawSkeletonData, name);
animationControl(changeSelect, skeletonData);
resources[res_cache_name + '-atlas'] = rawAtlasData;
resources[res_cache_name + '-png'] = rawPngData;
resources[res_cache_name] = skeletonData;
}
successCallback(resources[res_cache_name]);
} catch(err) {
failureCallback(err);
}
});
} catch(err) {
failureCallback(err);
}
};
var skeletonLoaderReference = this;
if (typeof genus === "object") {
precheckHandler(skeletonLoaderReference, false);
} else {
var urlToCheck = path + window.gfUtils.createWikiPathPart(res_name + "_chibi_dorm_atlas.txt") + res_name + "_chibi_dorm_atlas.txt";
$.ajax({
url: urlToCheck,
type:'HEAD',
error: function() { precheckHandler(skeletonLoaderReference, false); },
success: function() { precheckHandler(skeletonLoaderReference, true); }
});
}
}
};
};
function animationControl(changeSelect, skeletonData){
var infoDiv = $(changeSelect.parent(".tdoll_chibi,.chibiAnimationContainer").children(".chibiAnimationInfo"));
for(var i = 1; i < 20; i ++){
if(!infoDiv.attr("data-name" + String(i))) break;
infoDiv.removeAttr("data-name" + String(i));
infoDiv.removeAttr("data-duration" + String(i));
infoDiv.removeAttr("data-frame" + String(i));
}
changeSelect.children("option").remove();
for(i in skeletonData.animations){
infoDiv.attr("data-name" + String(i), skeletonData.animations[i].name);
infoDiv.attr("data-duration" + String(i), skeletonData.animations[i].duration);
infoDiv.attr("data-frame" + String(i), skeletonData.animations[i].timelines.length);
var op = document.createElement("OPTION");
if(skeletonData.animations[i].name == "victoryloop") continue;
op.value = skeletonData.animations[i].name;
op.innerHTML = skeletonData.animations[i].name;
changeSelect.append(op);
}
changeSelect.val("wait");
}
function BaseView(w, h){
var width = w || 400;
var height = h || 400;
var last_time = 0;
var now_time = 0;
var isUpdate = true;
var animationframe = null;
var animations = new Array();
var player = new Array();
var stage = new PIXI.Container;
var renderer = PIXI.autoDetectRenderer(width, height, { transparent : true, preserveDrawingBuffer: true });
var self = this;
var animate = function(t) {
animationframe = window.requestAnimationFrame(function(time) { animate(time); });
last_time = now_time;
now_time = t;
var time_diff = now_time - last_time;
if(isUpdate){
for(var i = 0; i < player.length; i++){
if(player[i].update && player[i].isupdate){
player[i].update(time_diff / 1000);
}
}
}
renderer.render(stage);
};
return {
clean : function(){
stage.removeChildren();
player = new Array();
},
getRenderer : function(){
return renderer;
},
addSprite : function(element){
stage.addChild(element);
},
addSpinePlayer : function(skeletonData, requestedScale, requestedHeightPosition){
var spineplayer = new PIXI.spine.Spine(skeletonData);
var animations = spineplayer.spineData.animations;
var heightPosition = height * ((requestedHeightPosition) ? requestedHeightPosition : 0.60);
spineplayer.position.set(width / 2, heightPosition);
var scaleToUse = 1;
if (requestedScale) {
var tmpParse = parseFloat(requestedScale);
if (!isNaN(tmpParse)) {
scaleToUse = tmpParse;
}
}
spineplayer.scale.set(scaleToUse);
spineplayer.animation_num = animations.length-1;
spineplayer.state.setAnimationByName(0, animations[spineplayer.animation_num].name, true);
spineplayer.skeleton.setToSetupPose();
spineplayer.autoUpdate = false;
spineplayer.update(0);
spineplayer.isupdate = true;
var num;
num = player.push(spineplayer);
stage.addChild(spineplayer);
renderer.render(stage);
return num;
},
nextAnimation : function(theChangeSelect){
var jumpAnimation = false;
for (var playerIdx = 0; playerIdx < player.length; playerIdx++) {
var currentPlayer = player[playerIdx];
if(currentPlayer && currentPlayer.spineData && currentPlayer.spineData.animations){
var animations = currentPlayer.spineData.animations;
currentPlayer.animation_num = (currentPlayer.animation_num + 1) % animations.length;
var animationName = animations[currentPlayer.animation_num].name;
var hasVictoryLoop = this.hasVictoryLoop(animations);
var isVictoryAnimation = animationName == "victory";
// Change the animation select options, if it doesn't exist, then continue;
var isExist = false;
var count = theChangeSelect.find('option').length;
for(var i = 0; i < count; i++){
if(theChangeSelect.get(0).options[i].value == animationName){ isExist = true; break; }
}
if(isExist) theChangeSelect.val(animationName);
// Generally it should be repeatet
var repeat = true;
repeat &= animationName != "die"; // except on "die" animations
repeat &= !isVictoryAnimation || isVictoryAnimation && !hasVictoryLoop; // victory should repeat except if it has victoryloop
currentPlayer.state.setAnimationByName(0, animationName, repeat);
// if there is a victoryloop animation and victory is now showing, chain them up
if (isVictoryAnimation && hasVictoryLoop) {
currentPlayer.state.addAnimationByName(0, "victoryloop", true, 0);
}
currentPlayer.update(0);
// We skip on animations without movement and on victoryloop (which is already chained to another animation)
if (animations[currentPlayer.animation_num].duration == 0.0 || (hasVictoryLoop && animationName == "victoryloop")) {
jumpAnimation = true;
}
}
}
if (jumpAnimation) {
this.nextAnimation(theChangeSelect);
}
},
selectAnimation : function(targetName){
for (var playerIdx = 0; playerIdx < player.length; playerIdx++) {
var currentPlayer = player[playerIdx];
if(currentPlayer && currentPlayer.spineData && currentPlayer.spineData.animations){
var animations = currentPlayer.spineData.animations;
for(var num = 0; num < animations.length; num ++){
if(animations[num].name == targetName){
currentPlayer.animation_num = num;
break;
}
}
var animationName = targetName;
var hasVictoryLoop = this.hasVictoryLoop(animations);
var isVictoryAnimation = animationName == "victory";
// Generally it should be repeatet
var repeat = true;
repeat &= animationName != "die"; // except on "die" animations
repeat &= !isVictoryAnimation || isVictoryAnimation && !hasVictoryLoop; // victory should repeat except if it has victoryloop
currentPlayer.state.setAnimationByName(0, animationName, repeat);
// if there is a victoryloop animation and victory is now showing, chain them up
if (isVictoryAnimation && hasVictoryLoop) {
currentPlayer.state.addAnimationByName(0, "victoryloop", true, 0);
}
currentPlayer.update(0);
}
}
},
hasVictoryLoop: function(anims) {
for (var idx = 0; idx < anims.length; idx++) {
if (anims[idx].name == "victoryloop") {
return true;
}
}
return false;
},
changeupdate : function(num){
player[num].isupdate = !player[num].isupdate;
return player[num].isupdate;
},
upplayer : function(num){
if(num <= 0){
return null;
}
var now = stage.getChildIndex(player[num]);
var next = stage.getChildIndex(player[num - 1]);
var p = player[num];
player[num] = player[num - 1];
player[num - 1] = p;
stage.addChildAt(player[num], now);
stage.addChildAt(player[num - 1], next);
return num - 1;
},
downplayer : function(num){
if(num >= player.length - 1){
return null;
}
var now = stage.getChildIndex(player[num]);
var next = stage.getChildIndex(player[num + 1]);
var p = player[num];
player[num] = player[num + 1];
player[num + 1] = p;
stage.addChildAt(player[num], now);
stage.addChildAt(player[num + 1], next);
return num + 1;
},
addImagePlayer : function(texture){
var imageplayer = new PIXI.Sprite(texture);
imageplayer.anchor.set(0.5);
imageplayer.position.set(width / 2, height / 2);
player.push(imageplayer);
stage.addChild(imageplayer);
renderer.render(stage);
},
start : function(){
animationframe = window.requestAnimationFrame(function(time) { animate(time); });
},
replay : function(){
for (var playerIdx = 0; playerIdx < player.length; playerIdx++) {
var currentPlayer = player[playerIdx];
if(currentPlayer && currentPlayer.spineData && currentPlayer.spineData.animations){
var animations = currentPlayer.spineData.animations;
var animationName = animations[currentPlayer.animation_num].name;
var hasVictoryLoop = this.hasVictoryLoop(animations);
var isVictoryAnimation = animationName == "victory";
// Generally it should be repeatet
var repeat = true;
repeat &= animationName != "die"; // except on "die" animations
repeat &= !isVictoryAnimation || isVictoryAnimation && !hasVictoryLoop; // victory should repeat except if it has victoryloop
currentPlayer.state.setAnimationByName(0, animationName, repeat);
// if there is a victoryloop animation and victory is now showing, chain them up
if (isVictoryAnimation && hasVictoryLoop) {
currentPlayer.state.addAnimationByName(0, "victoryloop", true, 0);
}
currentPlayer.update(0);
}
}
},
download : function(canvas){
for (var playerIdx = 0; playerIdx < player.length; playerIdx++) {
var data = [];
var currentPlayer = player[playerIdx];
if(currentPlayer && currentPlayer.spineData && currentPlayer.spineData.animations){
var animations = currentPlayer.spineData.animations;
var animationName = animations[currentPlayer.animation_num].name;
var recordTime = animations[currentPlayer.animation_num].duration * 1000;
if(animationName == "victory"){
for(animNumber in animations)
if(animations[animNumber].name == "victoryloop") recordTime += animations[animNumber].duration * 1000 * 2;
}
var stream = canvas[0].captureStream();
var recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
console.log("Recording start");
recorder.ondataavailable = function (event) {
if (event.data && event.data.size) {
data.push(event.data);
}
};
recorder.onstop = function(){
// download webm when is over
var url = URL.createObjectURL(new Blob(data, { type: 'video/webm' }));
var element = document.createElement('a');
var name_dorm = (canvas.parent().children(".chibiDormButton").hasClass("stateoff")) ? "dorm_" : "";
var name_all = canvas.parent().attr("data-tdoll-id") + "_" + name_dorm + animations[currentPlayer.animation_num].name;
element.setAttribute('href', url);
element.setAttribute('download', name_all);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};
// copy from nextAnimation
var hasVictoryLoop = this.hasVictoryLoop(animations);
var isVictoryAnimation = animationName == "victory";
var repeat = true;
repeat &= animationName != "die";
repeat &= !isVictoryAnimation || isVictoryAnimation && !hasVictoryLoop;
currentPlayer.state.setAnimationByName(0, animationName, repeat);
if (isVictoryAnimation && hasVictoryLoop) {
currentPlayer.state.addAnimationByName(0, "victoryloop", true, 0);
}
// start offically
currentPlayer.update(0);
recorder.start();
setTimeout(function(){
recorder.stop();
console.log("Recording end");
canvas.parent().children(".chibiAnimationBlock").remove();
}, recordTime);
}
}
}
};
};