'use strict'; const fs=require('fs'),path=require('path'),assert=require('assert/strict'); const render=require('../js/spine-render'),utils=require('../js/spine-utils'),clipping=require('../js/spine-canvas-clipping'); const root=path.resolve(process.argv[2]||path.join(__dirname,'.fixtures')); (async()=>{ let files=0,poses=0; for(const version of ['3.4','3.5','3.6','3.7','3.8','4.0','4.1','4.2','4.3']){ const spine=render.loadRuntime(version); for(const name of fs.readdirSync(path.join(root,version)).filter(n=>!n.startsWith('.')&&fs.statSync(path.join(root,version,n)).isDirectory())){ const dir=path.join(root,version,name),atlasPath=path.join(dir,name+'.atlas'); if(!fs.existsSync(atlasPath))continue; const text=fs.readFileSync(atlasPath,'utf8'); for(const page of utils.parseAtlasPages(text))assert(fs.existsSync(path.join(dir,page)),version+'/'+name+' missing '+page); const atlas=await render.buildTextureAtlas(spine,text,dir); for(const file of fs.readdirSync(dir).filter(n=>/\.(json|skel)$/.test(n))){ const source=path.join(dir,file),detected=utils.detectVersion(source); assert.equal(utils.chooseRuntimeDir(detected,file.endsWith('.skel')),version,source+' version'); const data=render.readSkeletonData(spine,source,atlas,file.endsWith('.skel')); assert(data.bones.length>0,source); const renderer=clipping.createRenderer(spine,{globalAlpha:1,globalCompositeOperation:'source-over'},version); let triangles=0;renderer.drawTriangle=(_image,...coords)=>{assert(coords.every(Number.isFinite),source+' geometry');triangles++}; for(const animation of data.animations){ const skeleton=new spine.Skeleton(data),state=new spine.AnimationState(new spine.AnimationStateData(data)); state.setAnimation(0,animation.name,true);state.update(animation.duration*0.37);state.apply(skeleton); if(spine.Physics)skeleton.updateWorldTransform(spine.Physics.update);else skeleton.updateWorldTransform(); renderer.draw(skeleton);poses++; } assert(triangles>0||data.animations.length===0,source+' empty geometry');files++; } } console.log('PASS '+version+' official exports'); } console.log('PASS: '+files+' skeleton files, '+poses+' animation/render checks; all atlas pages present'); })().catch(error=>{console.error(error);process.exitCode=1});