Showing preview only (3,202K chars total). Download the full file or copy to clipboard to get everything.
Repository: flowtsohg/mdx-m3-viewer
Branch: master
Commit: 2ff0bc00c636
Files: 496
Total size: 3.0 MB
Directory structure:
gitextract_a23fu6lt/
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .npmignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── Viewer.code-workspace
├── Viewer.sublime-project
├── clean.js
├── clients/
│ ├── README.md
│ ├── downgrader/
│ │ ├── index.html
│ │ └── index.js
│ ├── example/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ └── resources/
│ │ ├── SmileyGW_004.mdx
│ │ └── Textures/
│ │ └── SmileyGW.blp
│ ├── map/
│ │ ├── README.md
│ │ ├── index.html
│ │ └── index.js
│ ├── mdlx/
│ │ ├── index.html
│ │ └── index.js
│ ├── mdlxoptimizer/
│ │ ├── index.html
│ │ └── index.ts
│ ├── melee/
│ │ ├── README.md
│ │ ├── index.html
│ │ └── index.js
│ ├── rebuild/
│ │ ├── README.md
│ │ ├── components/
│ │ │ └── rebuilder.js
│ │ ├── index.html
│ │ └── index.js
│ ├── recorder/
│ │ ├── README.md
│ │ ├── index.html
│ │ └── index.js
│ ├── sanitytest/
│ │ ├── README.md
│ │ ├── components/
│ │ │ ├── logger.js
│ │ │ ├── mdlview.js
│ │ │ ├── sanitytester.js
│ │ │ ├── teamcolors.js
│ │ │ ├── testmeta.js
│ │ │ ├── testresults.js
│ │ │ ├── tooltips.js
│ │ │ ├── viewer.js
│ │ │ └── viewercontrols.js
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── index.js
│ │ └── test.js
│ ├── shared/
│ │ ├── camera.js
│ │ ├── component.js
│ │ ├── components/
│ │ │ └── toggle.js
│ │ ├── domutils.js
│ │ ├── localorhive.js
│ │ └── utils.js
│ ├── tests/
│ │ ├── README.md
│ │ ├── components/
│ │ │ └── unittester.js
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── solvers.js
│ │ ├── tests/
│ │ │ ├── base.js
│ │ │ ├── m3.js
│ │ │ ├── mdx.js
│ │ │ └── mdxprimitives.js
│ │ └── unittester.js
│ ├── textureatlas/
│ │ ├── index.html
│ │ └── index.js
│ ├── thirdparty/
│ │ ├── filesaver.js
│ │ └── resemble.js
│ └── weu/
│ ├── README.md
│ ├── TriggerDataCustom.txt
│ ├── TriggerDataPTR129.txt
│ ├── TriggerDataWEU.txt
│ ├── TriggerDataYDWE.txt
│ ├── components/
│ │ ├── weuchanges.js
│ │ ├── weuconverter.js
│ │ └── weumeta.js
│ ├── index.css
│ ├── index.html
│ └── index.js
├── package.json
├── src/
│ ├── common/
│ │ ├── arrayunique.ts
│ │ ├── audio.ts
│ │ ├── binarystream.ts
│ │ ├── bitstream.ts
│ │ ├── bytesof.ts
│ │ ├── canvas.ts
│ │ ├── convertbitrange.ts
│ │ ├── dxt.ts
│ │ ├── fetchdatatype.ts
│ │ ├── gl-matrix-addon.ts
│ │ ├── index.ts
│ │ ├── isformat.ts
│ │ ├── math.ts
│ │ ├── path.ts
│ │ ├── searches.ts
│ │ ├── seededrandom.ts
│ │ ├── sstrhash2.ts
│ │ ├── stringreverse.ts
│ │ ├── typecast.ts
│ │ ├── urlwithparams.ts
│ │ └── utf8.ts
│ ├── index.ts
│ ├── parsers/
│ │ ├── blp/
│ │ │ ├── image.ts
│ │ │ ├── index.ts
│ │ │ ├── isformat.ts
│ │ │ └── jpg.js
│ │ ├── dds/
│ │ │ ├── image.ts
│ │ │ ├── index.ts
│ │ │ └── isformat.ts
│ │ ├── index.ts
│ │ ├── ini/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── m3/
│ │ │ ├── animationreference.ts
│ │ │ ├── attachmentpoint.ts
│ │ │ ├── batch.ts
│ │ │ ├── bone.ts
│ │ │ ├── boundingshape.ts
│ │ │ ├── boundingsphere.ts
│ │ │ ├── camera.ts
│ │ │ ├── division.ts
│ │ │ ├── event.ts
│ │ │ ├── index.ts
│ │ │ ├── indexentry.ts
│ │ │ ├── isformat.ts
│ │ │ ├── layer.ts
│ │ │ ├── light.ts
│ │ │ ├── materialreference.ts
│ │ │ ├── md34.ts
│ │ │ ├── model.ts
│ │ │ ├── modelheader.ts
│ │ │ ├── reference.ts
│ │ │ ├── region.ts
│ │ │ ├── sd.ts
│ │ │ ├── sequence.ts
│ │ │ ├── standardmaterial.ts
│ │ │ ├── stc.ts
│ │ │ ├── stg.ts
│ │ │ ├── sts.ts
│ │ │ └── unsupportedentry.ts
│ │ ├── mdlx/
│ │ │ ├── animatedobject.ts
│ │ │ ├── animationmap.ts
│ │ │ ├── animations.ts
│ │ │ ├── attachment.ts
│ │ │ ├── bone.ts
│ │ │ ├── camera.ts
│ │ │ ├── collisionshape.ts
│ │ │ ├── eventobject.ts
│ │ │ ├── extent.ts
│ │ │ ├── faceeffect.ts
│ │ │ ├── genericobject.ts
│ │ │ ├── geoset.ts
│ │ │ ├── geosetanimation.ts
│ │ │ ├── helper.ts
│ │ │ ├── index.ts
│ │ │ ├── isformat.ts
│ │ │ ├── layer.ts
│ │ │ ├── light.ts
│ │ │ ├── material.ts
│ │ │ ├── model.ts
│ │ │ ├── particleemitter.ts
│ │ │ ├── particleemitter2.ts
│ │ │ ├── particleemitterpopcorn.ts
│ │ │ ├── ribbonemitter.ts
│ │ │ ├── sequence.ts
│ │ │ ├── texture.ts
│ │ │ ├── textureanimation.ts
│ │ │ ├── tokenstream.ts
│ │ │ └── unknownchunk.ts
│ │ ├── mpq/
│ │ │ ├── adpcm.ts
│ │ │ ├── archive.ts
│ │ │ ├── block.ts
│ │ │ ├── blocktable.ts
│ │ │ ├── constants.ts
│ │ │ ├── crypto.ts
│ │ │ ├── explode.ts
│ │ │ ├── file.ts
│ │ │ ├── hash.ts
│ │ │ ├── hashtable.ts
│ │ │ ├── index.ts
│ │ │ └── isarchive.ts
│ │ ├── slk/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── tga/
│ │ │ ├── image.ts
│ │ │ ├── index.ts
│ │ │ └── isformat.ts
│ │ └── w3x/
│ │ ├── doo/
│ │ │ ├── doodad.ts
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ ├── randomitem.ts
│ │ │ ├── randomitemset.ts
│ │ │ └── terraindoodad.ts
│ │ ├── imp/
│ │ │ ├── file.ts
│ │ │ ├── import.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── map.ts
│ │ ├── mmp/
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ └── minimapicon.ts
│ │ ├── shd/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── unitsdoo/
│ │ │ ├── droppeditem.ts
│ │ │ ├── droppeditemset.ts
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ ├── inventoryitem.ts
│ │ │ ├── modifiedability.ts
│ │ │ ├── randomunit.ts
│ │ │ └── unit.ts
│ │ ├── w3c/
│ │ │ ├── camera.ts
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── w3d/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── w3e/
│ │ │ ├── corner.ts
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── w3f/
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ ├── maporder.ts
│ │ │ └── maptitle.ts
│ │ ├── w3i/
│ │ │ ├── file.ts
│ │ │ ├── force.ts
│ │ │ ├── index.ts
│ │ │ ├── player.ts
│ │ │ ├── randomitem.ts
│ │ │ ├── randomitemset.ts
│ │ │ ├── randomitemtable.ts
│ │ │ ├── randomunit.ts
│ │ │ ├── randomunittable.ts
│ │ │ ├── techavailabilitychange.ts
│ │ │ └── upgradeavailabilitychange.ts
│ │ ├── w3o/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── w3r/
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ └── region.ts
│ │ ├── w3s/
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ └── sound.ts
│ │ ├── w3u/
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ ├── modification.ts
│ │ │ ├── modificationtable.ts
│ │ │ └── modifiedobject.ts
│ │ ├── wct/
│ │ │ ├── customtexttrigger.ts
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── wpm/
│ │ │ ├── file.ts
│ │ │ └── index.ts
│ │ ├── wtg/
│ │ │ ├── eca.ts
│ │ │ ├── file.ts
│ │ │ ├── index.ts
│ │ │ ├── parameter.ts
│ │ │ ├── subparameters.ts
│ │ │ ├── trigger.ts
│ │ │ ├── triggercategory.ts
│ │ │ ├── triggerdata.ts
│ │ │ └── variable.ts
│ │ └── wts/
│ │ ├── file.ts
│ │ └── index.ts
│ ├── utils/
│ │ ├── blp/
│ │ │ ├── index.ts
│ │ │ └── sanitytest.ts
│ │ ├── dds/
│ │ │ ├── index.ts
│ │ │ └── sanitytest.ts
│ │ ├── index.ts
│ │ ├── jass2/
│ │ │ ├── compilenatives.ts
│ │ │ ├── constanthandles.ts
│ │ │ ├── context.ts
│ │ │ ├── index.ts
│ │ │ ├── jass2lua.ts
│ │ │ ├── natives.ts
│ │ │ ├── thread.ts
│ │ │ ├── tokenstream.ts
│ │ │ └── types/
│ │ │ ├── agent.ts
│ │ │ ├── aidifficulty.ts
│ │ │ ├── alliancetype.ts
│ │ │ ├── animtype.ts
│ │ │ ├── attacktype.ts
│ │ │ ├── blendmode.ts
│ │ │ ├── camerafield.ts
│ │ │ ├── camerasetup.ts
│ │ │ ├── damagetype.ts
│ │ │ ├── dialogevent.ts
│ │ │ ├── effecttype.ts
│ │ │ ├── enum.ts
│ │ │ ├── eventid.ts
│ │ │ ├── fgamestate.ts
│ │ │ ├── fogstate.ts
│ │ │ ├── force.ts
│ │ │ ├── gamedifficulty.ts
│ │ │ ├── gameevent.ts
│ │ │ ├── gamespeed.ts
│ │ │ ├── gamestate.ts
│ │ │ ├── gametype.ts
│ │ │ ├── group.ts
│ │ │ ├── handle.ts
│ │ │ ├── hashtable.ts
│ │ │ ├── igamestate.ts
│ │ │ ├── index.ts
│ │ │ ├── itemtype.ts
│ │ │ ├── limitop.ts
│ │ │ ├── location.ts
│ │ │ ├── mapcontrol.ts
│ │ │ ├── mapdensity.ts
│ │ │ ├── mapflag.ts
│ │ │ ├── mapsetting.ts
│ │ │ ├── mapvisibility.ts
│ │ │ ├── mousebuttontype.ts
│ │ │ ├── pathingtype.ts
│ │ │ ├── placement.ts
│ │ │ ├── player.ts
│ │ │ ├── playercolor.ts
│ │ │ ├── playerevent.ts
│ │ │ ├── playergameresult.ts
│ │ │ ├── playerscore.ts
│ │ │ ├── playerslotstate.ts
│ │ │ ├── playerstate.ts
│ │ │ ├── playerunitevent.ts
│ │ │ ├── race.ts
│ │ │ ├── racepreference.ts
│ │ │ ├── raritycontrol.ts
│ │ │ ├── rect.ts
│ │ │ ├── region.ts
│ │ │ ├── soundtype.ts
│ │ │ ├── startlocprio.ts
│ │ │ ├── subanimtype.ts
│ │ │ ├── texmapflags.ts
│ │ │ ├── timer.ts
│ │ │ ├── trigger.ts
│ │ │ ├── unit.ts
│ │ │ ├── unitevent.ts
│ │ │ ├── unitstate.ts
│ │ │ ├── unittype.ts
│ │ │ ├── version.ts
│ │ │ ├── volumegroup.ts
│ │ │ ├── weapontype.ts
│ │ │ ├── weathereffect.ts
│ │ │ ├── widget.ts
│ │ │ └── widgetevent.ts
│ │ ├── mappeddata.ts
│ │ ├── mdlx/
│ │ │ ├── index.ts
│ │ │ ├── mdlstructure.ts
│ │ │ ├── primitives/
│ │ │ │ ├── createprimitive.ts
│ │ │ │ └── primitives.ts
│ │ │ └── sanitytest/
│ │ │ ├── data.ts
│ │ │ ├── sanitytest.ts
│ │ │ ├── testers.ts
│ │ │ ├── tracks.ts
│ │ │ └── utils.ts
│ │ └── w3x/
│ │ ├── generatelistfile.ts
│ │ ├── index.ts
│ │ └── weu/
│ │ ├── conversions.ts
│ │ ├── data.ts
│ │ ├── parsewtg.ts
│ │ ├── processing.ts
│ │ ├── transformations/
│ │ │ ├── blz.ts
│ │ │ ├── functions.ts
│ │ │ ├── presets.ts
│ │ │ ├── specific.ts
│ │ │ └── transformer.ts
│ │ ├── utils.ts
│ │ └── weu.ts
│ ├── version.ts
│ └── viewer/
│ ├── bounds.ts
│ ├── camera.ts
│ ├── cell.ts
│ ├── emittedobject.ts
│ ├── emittedobjectupdater.ts
│ ├── emitter.ts
│ ├── genericresource.ts
│ ├── gl/
│ │ ├── clientbuffer.ts
│ │ ├── clientdatatexture.ts
│ │ ├── datatexture.ts
│ │ ├── gl.ts
│ │ ├── index.ts
│ │ └── shader.ts
│ ├── grid.ts
│ ├── handlerresource.ts
│ ├── handlers/
│ │ ├── blp/
│ │ │ ├── handler.ts
│ │ │ └── texture.ts
│ │ ├── dds/
│ │ │ ├── handler.ts
│ │ │ └── texture.ts
│ │ ├── index.ts
│ │ ├── m3/
│ │ │ ├── attachment.ts
│ │ │ ├── batch.ts
│ │ │ ├── bone.ts
│ │ │ ├── boundingshape.ts
│ │ │ ├── camera.ts
│ │ │ ├── handler.ts
│ │ │ ├── layer.ts
│ │ │ ├── model.ts
│ │ │ ├── modelinstance.ts
│ │ │ ├── node.ts
│ │ │ ├── region.ts
│ │ │ ├── sd.ts
│ │ │ ├── sequence.ts
│ │ │ ├── shaders/
│ │ │ │ ├── layers.glsl.ts
│ │ │ │ ├── standard.frag.ts
│ │ │ │ └── standard.vert.ts
│ │ │ ├── skeleton.ts
│ │ │ ├── standardmaterial.ts
│ │ │ ├── stc.ts
│ │ │ ├── stg.ts
│ │ │ ├── sts.ts
│ │ │ └── texture.ts
│ │ ├── mdx/
│ │ │ ├── animatedobject.ts
│ │ │ ├── attachment.ts
│ │ │ ├── attachmentinstance.ts
│ │ │ ├── batch.ts
│ │ │ ├── batchgroup.ts
│ │ │ ├── bone.ts
│ │ │ ├── camera.ts
│ │ │ ├── collisionshape.ts
│ │ │ ├── emitter.ts
│ │ │ ├── emittergroup.ts
│ │ │ ├── eventobjectemitter.ts
│ │ │ ├── eventobjectemitterobject.ts
│ │ │ ├── eventobjectsnd.ts
│ │ │ ├── eventobjectsndemitter.ts
│ │ │ ├── eventobjectsplemitter.ts
│ │ │ ├── eventobjectsplubr.ts
│ │ │ ├── eventobjectspn.ts
│ │ │ ├── eventobjectspnemitter.ts
│ │ │ ├── eventobjectubremitter.ts
│ │ │ ├── filtermode.ts
│ │ │ ├── genericobject.ts
│ │ │ ├── geometryemitterfuncs.ts
│ │ │ ├── geoset.ts
│ │ │ ├── geosetanimation.ts
│ │ │ ├── handler.ts
│ │ │ ├── helper.ts
│ │ │ ├── layer.ts
│ │ │ ├── light.ts
│ │ │ ├── material.ts
│ │ │ ├── model.ts
│ │ │ ├── modelinstance.ts
│ │ │ ├── node.ts
│ │ │ ├── particle.ts
│ │ │ ├── particle2.ts
│ │ │ ├── particleemitter.ts
│ │ │ ├── particleemitter2.ts
│ │ │ ├── particleemitter2object.ts
│ │ │ ├── particleemitterobject.ts
│ │ │ ├── replaceableids.ts
│ │ │ ├── ribbon.ts
│ │ │ ├── ribbonemitter.ts
│ │ │ ├── ribbonemitterobject.ts
│ │ │ ├── sd.ts
│ │ │ ├── sequence.ts
│ │ │ ├── setupgeosets.ts
│ │ │ ├── setupgroups.ts
│ │ │ ├── shaders/
│ │ │ │ ├── hd.frag.ts
│ │ │ │ ├── hd.vert.ts
│ │ │ │ ├── particles.frag.ts
│ │ │ │ ├── particles.vert.ts
│ │ │ │ ├── sd.frag.ts
│ │ │ │ ├── sd.vert.ts
│ │ │ │ └── transforms.glsl.ts
│ │ │ ├── texture.ts
│ │ │ └── textureanimation.ts
│ │ ├── shaders/
│ │ │ ├── bonetexture.glsl.ts
│ │ │ ├── precision.glsl.ts
│ │ │ └── quattransform.glsl.ts
│ │ ├── tga/
│ │ │ ├── handler.ts
│ │ │ └── texture.ts
│ │ └── w3x/
│ │ ├── doodad.ts
│ │ ├── map.ts
│ │ ├── shaders/
│ │ │ ├── cliffs.frag.ts
│ │ │ ├── cliffs.vert.ts
│ │ │ ├── ground.frag.ts
│ │ │ ├── ground.vert.ts
│ │ │ ├── water.frag.ts
│ │ │ └── water.vert.ts
│ │ ├── standsequence.ts
│ │ ├── terraindoodad.ts
│ │ ├── terrainmodel.ts
│ │ ├── unit.ts
│ │ ├── variations.ts
│ │ ├── viewer.ts
│ │ └── widget.ts
│ ├── imagetexture.ts
│ ├── index.ts
│ ├── model.ts
│ ├── modelinstance.ts
│ ├── node.ts
│ ├── resource.ts
│ ├── scene.ts
│ ├── skeletalnode.ts
│ ├── texture.ts
│ └── viewer.ts
├── tsconfig.json
├── types/
│ ├── fengari.d.ts
│ └── tga-js.d.ts
└── webpack.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintignore
================================================
dist
clients
thirdparty
webpack.config.js
clean.js
================================================
FILE: .eslintrc.json
================================================
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": ["./tsconfig.json"]
},
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"eol-last": "error",
"@typescript-eslint/indent": [
"error",
2
],
"no-tabs": "error",
"@typescript-eslint/semi": "error",
"@typescript-eslint/no-extra-semi": 2,
"prefer-const": "error",
"@typescript-eslint/object-curly-spacing": [ "error", "always", { "arraysInObjects": false, "objectsInObjects": false }],
"array-bracket-spacing": ["error", "never"],
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"no-return-await": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
"@typescript-eslint/no-empty-function": "warn",
"no-empty": "warn"
}
}
================================================
FILE: .gitignore
================================================
node_modules
dist
package-lock.json
================================================
FILE: .npmignore
================================================
.*
**/tsconfig.json
**/webpack.config.js
node_modules
Viewer.code-workspace
Viewer.sublime-project
src
clients
dist/clients
clean.js
================================================
FILE: CONTRIBUTING.md
================================================
If you want to contribute, here are a few notes:
1) If the changes are related in any way to the viewer itself (parsers that are used, handlers, shaders, etc.), then the unit tests must all pass.
This of course doesn't include unit tests that are directly related to the changes, and thus need to be updated.
2) If the changes are related to real-time parts of the code, they should be efficient! There are no such things as real-time heap allocations (e.g. `new`, `[]`, `{}`), typed arrays are generally preferred for data storage over arrays/objects, and so on.
3) Use `npm run dev` to start webpack in watch mode and re-build the source as you write it.
4) Have fun :)
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2013-2021 Chananya Freiman
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
**NO LONGER ACTIVELY MAINTAINED.**
mdx-m3-viewer
=============
At the core of it, a 3D model viewer for MDX and M3 models used by the games Warcraft 3 and Starcraft 2 respectively.
The viewer part handles the following formats:
* MDX (Warcraft 3 model): extensive support, almost everything should work.
* M3 (Starcraft 2 model): partial support.
* W3M/W3X (Warcraft 3 map): partial support.
* BLP1 (Warcraft 3 texture): extensive support, almost everything should work.
* TGA (image): extensive support, almost everything should work.
* DDS (compressed texture): partial support - DXT1/DXT3/DXT5/RGTC.
* PNG/JPG/GIF/WebP: supported by the browser.
There are file parsers that the viewer depends on.\
These don't rely on the viewer or indeed on even running in a browser.\
They include:
* MDX/MDL: read/write.
* M3: read.
* BLP1: read.
* INI: read/write.
* SLK: read/write.
* MPQ1: read/write.
* W3M/W3X/W3N: read/write, including all of the internal files.
* DDS: read (DXT1/DXT3/DXT5/RGTC).
* TGA: read.
There are all sorts of utilities that were made over the years.\
These include things like...
* The library's unit tester, which compares rendered results against stored images that were generated in the same way.
* The MDX sanity test, which looks for errors and weird things in MDX models.
* A Jass context that can...well, run Jass code. That being said, it really runs Lua code converted from Jass, on a JS Lua VM. What a tongue twiser. While it supports some Warcraft 3 natives, don't expect it run whole maps. Maybe in the future 😉
* A utility that makes it possible to open Warcraft 3 maps in the vanilla World Editor, in cases were said maps used a non-vanilla editor with extended GUI, in which case they crash upon opening in the official editor.
* etc.
Finally, the library also comes with a bunch of clients.\
A "client" in this context means external code that uses the library.\
Most of these clients are simple and messy, since they were made as side projects while working on the library.\
Most of these clients are also just wrappers around the viewer and the utilities, merely giving them an interface on a web page.\
These include things like...
* A simple example client.
* The unit tester's page, which allows to run the unit tests, and to download the results.
* The MDX sanity test's page, which visually shows the results of sanity tests, and other nifty things.
* etc.
------------------------
#### Building
```
npm install mdx-m3-viewer
npm run build
```
This will generate the CommonJS, UMD, and the packed clients under `dist`.
------------------------
#### Examples
Run the Webpack dev server with:
```
npm run serve
```
Once it compiled the code, open `http://localhost:8080/clients/example/` in the browser, and play with the client's source to see how things change.
You can also check out the other available clients.
------------------------
#### Importing
You can import the viewer in different ways:
```javascript
// UMD export in the browser.
new ModelViewer.viewer.ModelViewer(canvas);
// require/import the library.
const ModelViewer = require('mdx-m3-viewer'); // CommonJS.
import ModelViewer from 'mdx-m3-viewer'; // ES6.
new ModelViewer.viewer.ModelViewer(canvas);
// require/import something directly.
const ModelViewer = require('mdx-m3-viewer/src/viewer/viewer'); // CommonJS.
import ModelViewer from 'mdx-m3-viewer/src/viewer/viewer'; // ES6.
new ModelViewer(canvas);
```
When developing with TypeScript, nothing needs to be done to get correct typings.
This is true also when importing specific files, which means a client can import only what it needs from the library.
All code snippets will use the names as if you imported them directly to avoid some mess. See the examples for actual namespacing.
------------------------
#### Usage
First, let's create the viewer:
```javascript
let canvas = ...; // A <canvas> aka HTMLCanvasElement object.
let viewer = new ModelViewer(canvas);
```
If the client doesn't have the WebGL requierments to run the viewer, an exception will be thrown when trying to create it.
Now that we have a viewer, a scene can be created.
Each scene has its own camera and viewport, and holds a list of things to update and render.
```javascript
let scene = viewer.addScene();
// Move the camera backwards a bit, so we can actually see the origin.
scene.camera.move([0, 0, 500]);
```
Finally, we need to actually let the viewer update and render:
```javascript
(function step() {
requestAnimationFrame(step);
viewer.updateAndRender();
}());
```
---
Models and textures are loaded with the `load` function.
To load models and textures with `load`, the viewer must have handlers that tell it how to load the different file formats.\
If you want to load an MDX model, the MDX handler must be added to the viewer, and so on.\
This is done with the `addHandler` function, and the different handlers are exported as a part of the library.
Let's add the MDX and BLP handlers:
```javascript
viewer.addHandler(handlers.mdx);
viewer.addHandler(handlers.blp);
```
Now MDX (and MDL) and BLP files will be accepted by the viewer.
Suppose we have the following directory structure, where `model.mdx` uses `texture.blp`:
```
├── index.html
└── Resources
├── model.mdx
└── texture.blp
```
Loading the model is simple:
```javascript
let modelPromise = viewer.load("Resources/model.mdx");
```
You get back a promise, which will resolve to either the MDX model, or to undefined if any error occured.
When the MDX model loads, it also loads internal resources, like its textures, so the viewer will attempt to fetch `texture.blp`.\
If the server knows this is a relative path to `Resources/` then all is fine.\
It is typically a lot easier and more dynamic to control the paths on the client though.\
This is done with "path solvers" - functions that, given a source to load from, such as a path, can modify it and return the actual source to load from.\
It will probably make more sense with code - let's load the model again, with the texture fetch asking for the correct path: `Resources/texture.blp`.
```javascript
function pathSolver(path) {
return "Resources/" + path;
}
let modelPromise = viewer.load("model.mdx", pathSolver);
```
Here's the short version of what happens:
1. `pathSolver` is called with `"model.mdx"` and returns `"Resources/model.mdx"`.
2. The viewer starts the fetch, and emits the `loadstart` event.
3. A promise is returned.
4. ...time passes until the file finishes loading...
5. The viewer detects the format as MDX based on the file data (the url is irrelevant to this process).
6. The model is constructed successfuly, or not, with a `load` or `error` event sent respectively, followed by the `loadend` event.
7. In the case of an MDX model, the previous step will also cause it to load its textures.
8. `pathSolver` is called with `"texture.blp"`, which returns `"Resources/texture.blp"`, and we loop back to step 2, but with a texture this time.
Path solvers can return promises which will be waited upon, and they can return models and textures directly for injections.
Generally speaking, you'll need a simple path solver that expects urls and prepends them by some base directory or API url.\
There are however times when this is not the case, such as loading models with custom textures, and handling both in-memory and fetches in the same solver as done in the map viewer.
Once the promise is resolved, we have a model, however a model in this context is simply a source of data.\
The next step is to create an instance of this model.\
Instances can be rendered, moved, rotated, scaled, parented to other instances or nodes, play animations, and so on.
```javascript
let instance = model.addInstance();
```
And finally add the instance to the scene, so it's updated and rendered:
```javascript
instance.setScene(scene);
// Equivalent to:
scene.addInstance(instance);
```
---
Other resources, such as SLK tables and INI configurations, are loaded with `loadGeneric`.
```javascript
let resourcePromise = viewer.loadGeneric(path, dataType[, callback]);
```
Where:
* `path` is an url string.
* `dataType` is a string with one of these values: `text`, `arrayBuffer`, `blob`, `bytes`, or `image`.
* `callback` is an optional function that will be called with the data once the fetch is complete, and should return the resource's data.
If a callback is given, `resource.data` will be whatever the callback returns.\
If a promise is returned, the loader waits for it to resolve, and uses whatever it resolved to.\
If no callback is given, the data will be the fetch data itself, according to the given data type (`bytes` refers to a `Uint8Array`).
`loadGeneric` is a simple layer above the standard `fetch` function.\
The purpose of loading other files through the viewer is to cache the results and avoid multiple loads, while also allowing the viewer itself to handle events correctly.
------------------------
#### Events and Promises
As mentioned above, there are emitted events, and they can be used with the NodeJS EventEmitter API:
```javascript
viewer.on(eventName, listener)
viewer.off(eventName, listener)
viewer.once(eventName, listener)
viewer.emit(eventName[, ...args])
```
The built-in names are:
* `loadstart` - a resource started loading.
* `load` - a resource successfully loaded.
* `error` - something bad happened.
* `loadend` - a resource finished loading, follows both `load` and `error` when loading a resource.
* `idle` - all loads finished for now.
For example:
```javascript
viewer.on('error', (e) => console.log(e));
```
In addition there is `viewer.whenAllLoaded([callback])`, which can be used to run code when nothing is loading.
If a callback is given, it will be called, otherwise a promise is returned.
If there are no resources currently being loaded, this will happen instantly. Otherwise, it will happen once the `idle` event is emitted.
```javascript
viewer.whenAllLoaded((viewer) => {
// Nothing is loading!
});
viewer.whenAllLoaded()
.then((viewer) => {
// Nothing is loading!
});
```
---
And now some more specific information and tips.
#### Team colors, event objects, and Reforged
When loading an MDX model that uses team color/glow textures, it will tell the handler to load all of the team textures.
Similarly, if an MDX model has event objects, it will tell the handler to load the needed SLK files.
The handler uses `load` much like the client does, and thus the same implications apply - if the server is set for the relative paths, all is fine, otherwise a path solver should be used.
A path solver can be passed when adding the handler:
```javascript
viewer.addHandler(handlers.mdx, wc3PathSolver);
```
The handler also selects between TFT (16) and Reforged (28) team colors.\
These will be used regardless of whether any specific model being rendered is a TFT or Reforged model.\
The default mode is TFT, and it can be changed by passing true as the third parameter when adding the handler:
```javascript
viewer.addHandler(handlers.mdx, wc3PathSolver, true); // Reforged team colors and event objects.
```
#### Interacting with model instances
Model instances are nodes, and can be transformed as such:
```javascript
instance.setLocation([50, 0, 0]); // Move to the given point.
instance.move([50, 0, 0]); // Move by the given offset.
instance.setRotation([0, 0, 0, 1]); // Set the rotation to the given quaternion.
instance.rotate([0, 0, 0, 1]); // Rotate by the given quaternion.
instance.setScale([2, 2, 2]); // Set the scale to the given vector.
instance.scale([2, 2, 2]); // Scale by the given vector.
instance.setUniformScale(2); // Set the scale to the given number.
instance.uniformScale(2); // Scale by the given number.
instance.face([50, 0, 0], [0, 0, 1]); // Face the given point, with the given "up" vector.
instance.setParent(nodeOrInstance); // Set a parent, making all other transformations relative to it.
instance.setParent(); // Remove the parent.
```
Both MDX and M3 instances can run animations, have team colors, etc.:
```javascript
instance.setSequence(-1); // No animation.
instance.setSequence(0); // First animation.
instance.setSequenceLoopMode(0); // Never loop animations.
instance.setSequenceLoopMode(1); // Loop animations based on the model.
instance.setSequenceLoopMode(2); // Always loop animations.
instance.setTeamColor(0); // First team color.
instance.setVertexColor([1, 0, 0]); // Red vertex color.
let node = instance.getAttachment(0); // Get the first attachment point.
```
MDX instances have `setTexture`, `setParticle2Texture`, and `setEventTexture`, to override textures, particle emitter textures, and event object textures:
```javascript
instance.setTexture(0, myTexture); // Override texture 0.
instance.setParticle2Texture(0, myTexture); // Override the texture of particle emitter 0.
instance.setEventTexture(0, myTexture); // Override the texture of event emitter 0.
instance.setTexture(0); // Remove the override, same with the other functions.
```
M3 instances have `setTexture`:
```javascript
instance.setTexture(1, 0, myTexture); // Override texture 0 of standard material 1.
```
#### Solver Params: Reforged and the map viewer
It is in fact possible to send more data to path solvers with `load`.
The full signature is as follows:
```javascript
let resourcePromise = viewer.load(src[, pathSolver[, solverParams]]);
```
Where `solverParams` can be anything.
When `solverParams` exists, it will be sent to the path solver as the second argument:
```javascript
function pathSolver(src, solverParams) {
// ...
}
```
The MDX handler and the map viewer use `solverParams` to select between SD/HD Reforged resources, and to select specific tileset resources.
The MDX handler defines the parameters as such: `{reforged?: boolean, hd?: boolean}`.\
The map viewer defines them as such: `{reforged?: boolean, hd?: boolean, tileset: string}`.
If `reforged` is falsy or doesn't exist, they want a TFT resource.\
If `reforged` is true, they want a Reforged SD resource and...\
If `hd` and `reforged` are true, they want a Reforged HD resource.
For example, when a new MDX model is being loaded, and it is detected as a Reforged model (version > 800), any internal resources like its textures will be loaded with `solverParams = {reforged: true}`, and if the model is detected to be HD: `solverParams = {reforged: true, hd: true}`.
You can also manually supply your own parameters.\
For example, let's suppose we want to load the Warcraft 3 Footman model, but with a twist - we want all three versions of it - RoC/TFT, Reforged SD, and Reforged HD.\
The loading code can be something along these lines:
```js
let TFT = viewer.load('Units/Human/Footman/Footman.mdx', mySolver);
let SD = viewer.load('Units/Human/Footman/Footman.mdx', mySolver, {reforged: true});
let HD = viewer.load('Units/Human/Footman/Footman.mdx', mySolver, {reforged: true, hd: true});
```
So what does the path solver do with `solverParams`?\
As always, that depends on the client.\
For example, the solver may append the parameters as url parameters, and the server selects the game based on them.\
The solver can also completely ignore these parameters and return whatever resources it wants.
#### Starcraft 2 models are tiny
SC2 models are tiny compared to WC3 models.\
If a client needs models of both games to co-exist, it's suggested to scale SC2 models by 100.\
This can be done with something along the lines of:
```javascript
let instance = model.addInstance();
if (model instanceof handlers.m3.resource) {
instance.uniformScale(100);
}
```
#### Loading resources from memory
Resources don't have to be fetched - if you have the data, you can load it directly.\
Nothing special is needed, simply use it as you would an url:
```javascript
let resourcePromise = viewer.load(buffer);
```
Say a web page wants to load MDX models from local files that are dragged into it.\
After some event handling, you end up with data such as a `string` or an `ArrayBuffer`.
Practically speaking, most MDX models will attempt to load Warcraft 3 textures.\
This means that if we load the model directly, it will fail to load the textures, unless as always, the server is set for the relative paths.
A path solver can again simplify the load:
```javascript
function pathSolver(src) {
if (src === buffer) {
return src;
}
return wc3PathSolver(src);
}
viewer.load(buffer, pathSolver);
```
When the thing being loaded is the buffer, it will be used, otherwise, e.g. for the textures, the Warcraft 3 path solver will be used instead.
#### Primitive shapes
It is possible to construct primitive shapes with `createPrimitive`, which is available under `utils.mdlx.createPrimitive`.
The function expects an object describing a primitive geometry, which can be obtained via the different functions in `utils.mdlx.primitives`.
An optional material can be given, which can control the render mode between polygons and lines, the color, texture, and such.
For example:
```javascript
let modelPromise = createPrimitive(viewer, primitives.createUnitCube(), { color: [1, 0, 0] });
```
Note that this loads a standard MDX model which can be used like any other MDX model.
#### Sounds
MDX models have sound emitters, and the viewer supports them.
If sound is desired, `viewer.audioEnabled` should be set to true BEFORE loading models.\
This signals to the MDX handler that sound is desired, and it will load the neccessary sound files when loading models.\
If `audioEnabled` isn't true, the sound files aren't downloaded in the first place to reduce file fetching.
To get the sounds to actually run, you must call `scene.enableAudio()`, which returns a promise that resolves to whether audio was actually enabled.\
There are two reasons for it to fail - either because the browser simply does not support audio, or because the browser did not want to enable audio.\
The latter will happen if you attempt to enable audio before the user made any interaction with the page (like clicking something). This is a browser policy and there is no control over it.
If audio was enabled, you will hear familiar sounds when running animations, like attack sounds, death sounds, and so on.\
Not enough work was put into them to have the same feel as Warcraft 3, but it's sometimes a fun surprise to suddenly hear a model making sounds in the browser.
#### Scene composition
You can have any number of scenes you want.
Each scene offers the following to control how it's composed on the canvas:
* `viewport` - the position and size of the scene in pixels (defaults to the entire canvas).
* `alpha` - determines whether the scene has a background, or can be seen through (defaults to false - has a background).
* `color` - the background color, which is used when `alpha` is false (defaults to black).
```javascript
scene.viewport[0] = 100; // X offset from the left side of the canvas.
scene.viewport[1] = 100; // Y offset from the bottom side of the canvas.
scene.viewport[2] = 200; // Width.
scene.viewport[3] = 200; // Height.
scene.alpha = false; // Opaque, i.e. has a background (and also the default).
scene.color[0] = 1; // Red background.
scene.color[1] = 0;
scene.color[2] = 0;
```
The order in which the scenes are drawn is based on the order of creation, but you can manually move scenes around in `viewer.scenes`.
For example, let's say we want to mimic how Warcraft 3 looks. This could be done with 3 scenes:
1) The game world.
2) The UI with `alpha = true` so that where the UI isn't drawn, the game world will be seen through.
3) The selected portrait, moved and sized to be on the correct portion of the UI.
#### Everything is blurry
WebGL uses a canvas as its back buffer, meaning it has the same amount of pixels as the canvas does. Surprising, right?\
What may actually surprise you, however, is that the canvas back buffer isn't neccassarily the size it is drawn at, due to CSS styling.\
For example, you can have a canvas that is scaled via CSS to the entire page, but if you never set its actual size, it will probably be a 100x100 pixel canvas (or whatever default size the browser uses), stretched to the page size.\
If you want to set the size of the back buffer, i.e. the real resolution of the canvas, use the `width` and `height` properties of the canvas, rather than CSS properties such as `clientWidth` and `clientHeight`.
```javascript
// Could be a static size.
canvas.width = 512;
canvas.height = 512;
// Or perhaps scaled with CSS, if you put this in a resize event listener.
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
// This however only changes the CSS size, not the canvas resolution!
canvas.clientWidth = 512;
canvas.clientHeight = 512;
// Nor does this.
canvas.style.width = '512px';
canvas.style.height = '512px';
```
#### Variable frames per second
`ModelViewer.update()` and `ModelViewer.updateAndRender()` have an optional `dt` argument.
`dt` controls how much time in miliseconds to advance the animations.
By default, `dt` is set for 60FPS, or `1000 / 60`.
If a client runs on a >60Hz monitor, and uses `requestAnimationFrame` for its main loop as it should, animations will run faster than they should.
In other cases, a client might have too many things rendering and it slows down, causing animations to go slow motion.
To support a variable FPS while keeping the same animation speed, `dt` can be controlled dynamically, for example:
```javascript
let lastTime = performance.now();
(function step() {
requestAnimationFrame(step);
let now = performance.now();
// The faster the FPS, the lower dt will be.
// Twice the FPS? half the dt.
// There are more frames per second, so every frame advances the animation less.
// And the other way is also true.
// Half the FPS? twice the dt.
// There are less frames per second, so every frame advances the animation more.
let dt = now - lastTime;
lastTime = now;
viewer.updateAndRender(dt);
}());
```
================================================
FILE: Viewer.code-workspace
================================================
{
"folders": [
{
"path": "."
}
],
"settings": {
"editor.tabSize": 2,
"files.eol": "\n",
"typescript.preferences.quoteStyle": "single",
"typescript.validate.enable": true,
"editor.formatOnSave": true,
"eslint.lintTask.enable": true,
"eslint.validate": [
"typescript"
],
"workbench.editor.enablePreview": false,
"typescript.tsdk": "node_modules\\typescript\\lib"
}
}
================================================
FILE: Viewer.sublime-project
================================================
{
"folders":
[
{
"path": "."
}
],
"tab_size": 2,
"translate_tabs_to_spaces": true,
"use_tab_stops": true,
}
================================================
FILE: clean.js
================================================
// See https://stackoverflow.com/a/52526549/2503048
var fs = require('fs');
function deleteFolderRecursive(path) {
if (fs.existsSync(path) && fs.lstatSync(path).isDirectory()) {
fs.readdirSync(path).forEach(function (file, index) {
var curPath = path + "/" + file;
if (fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
console.log(`Deleting directory "${path}"...`);
fs.rmdirSync(path);
}
}
console.log("Cleaning build files...");
deleteFolderRecursive("./dist/cjs");
deleteFolderRecursive("./dist/umd");
console.log("Successfully cleaned the build files!");
console.log("Running TSC and Webpack, it might take a while...");
================================================
FILE: clients/README.md
================================================
Over the years, many different clients were made with this library. Most of them have gone into the pages of forgotten history, but some remain.
I present them as-is, in their messy state, so that they may perhaps help anyone who wants to use the library, or for anyone wanting to improve them.
Note that if the web page you open doesn't point to `127.0.0.1` (e.g. you are using a remote server, or using `localhost` instead), all downloads will be redirected to the Hiveworkshop. Once upon a time Ralle, the Hive's owner, said he's ok with this. If at any point this changes, I will remove this information from the repository.
Due to this, for the time being, all of the clients should run out of the box.
================================================
FILE: clients/downgrader/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<div>
Drag & Drop a Warcraft 3 "new" map (~1.29 and onwards) to downgrade it back to an "old" map (~1.28 and
backwards).
</div>
<div> This currently handles the map information, doodads/destructibles, and units/items.</div>
<div>
Triggers of Reforged maps (1.32) will be deleted, because my code doesn't (yet?) support Reforged triggers.
</div>
<script src="../thirdparty/filesaver.js"></script>
<script src="/clients/downgrader.min.js"></script>
</body>
</html>
================================================
FILE: clients/downgrader/index.js
================================================
import War3Map from '../../src/parsers/w3x/map';
import War3MapW3i from '../../src/parsers/w3x/w3i/file';
import War3MapDoo from '../../src/parsers/w3x/doo/file';
import War3MapUnitsDoo from '../../src/parsers/w3x/unitsdoo/file';
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
const file = e.dataTransfer.files[0];
const reader = new FileReader();
reader.addEventListener('loadend', (e) => {
const buffer = e.target.result;
const map = new War3Map();
map.load(buffer);
const w3i = new War3MapW3i();
w3i.load(map.get('war3map.w3i').arrayBuffer());
if (w3i.version > 25) {
console.log(`war3map.w3i version ${w3i.version} => 25`);
w3i.version = 25;
map.set('war3map.w3i', w3i.save());
}
const buildVersion = w3i.getBuildVersion();
if (buildVersion > 131) {
console.log(`war3map.doo buildVersion ${buildVersion} => 0`);
const doo = new War3MapDoo();
doo.load(map.get('war3map.doo').arrayBuffer(), buildVersion);
console.log(doo)
map.set('war3map.doo', doo.save(0));
console.log(`war3mapUnits.doo buildVersion ${buildVersion} => 0`);
const unitsDoo = new War3MapUnitsDoo();
unitsDoo.load(map.get('war3mapUnits.doo').arrayBuffer(), buildVersion);
console.log(unitsDoo)
map.set('war3mapUnits.doo', unitsDoo.save(0));
console.log('Deleting the triggers, because this is a Reforged map, and my code does not support Reforged triggers (yet?)');
map.delete('war3map.wtg');
}
saveAs(new Blob([map.save().buffer], { type: 'application/octet-stream' }), 'downgraded_' + file.name);
});
reader.readAsArrayBuffer(file);
});
================================================
FILE: clients/example/README.md
================================================
A simple example client.
Thanks to Frank from the HiveWorkshop for the MDX model and BLP texture!
================================================
FILE: clients/example/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>MDX Example</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="canvas"></canvas>
<script src="/clients/example.min.js"></script>
</body>
</html>
================================================
FILE: clients/example/index.js
================================================
import * as ModelViewer from '../../src/';
import { setupCamera } from '../shared/camera';
const handlers = ModelViewer.viewer.handlers;
let canvas = document.getElementById('canvas');
canvas.width = 800;
canvas.height = 600;
// Create the viewer!
let viewer = new ModelViewer.viewer.ModelViewer(canvas);
// Create a new scene. Each scene has its own camera, and a list of things to render.
let scene = viewer.addScene();
// Check camera.js!
setupCamera(scene);
// Events.
viewer.on('loadstart', (e) => console.log(e));
viewer.on('load', (e) => console.log('load', e));
viewer.on('loadend', (e) => console.log('loadend', e));
viewer.on('error', (e) => console.log('error', e));
// Add the MDX handler.
// Note that this also loads all of the team colors/glows.
// You can optionally supply a path solver (look below) to point the viewer to the right location of the textures.
// Additionally, a boolean can be given that selects between RoC/TFT and Reforged team colors.
// For example:
// viewer.addHandler(handlers.mdx, pathSolver); // Roc/TFT = 14 teams.
// viewer.addHandler(handlers.mdx, pathSolver, true); // Reforged = 28 teams.
// In the case of this example, team colors aren't used, so it's fine for their loads to simply fail.
viewer.addHandler(handlers.mdx);
// Add the BLP handler.
viewer.addHandler(handlers.blp);
// A path solver is used for every load call.
// Given a possibly relative source, it should return the actual source to load from.
// This can be in the form of an URL string, or direct sources from memory (e.g. a previously loaded ArrayBuffer).
function pathSolver(src) {
return 'resources/' + src;
}
// Load our MDX model!
let modelPromise = viewer.load('SmileyGW_004.mdx', pathSolver);
modelPromise.then((model) => {
// The promise can return undefined if something went wrong!
if (model) {
// Create an instance of this model.
let instance = model.addInstance();
// Set the instance's scene.
// Equivalent to scene.addInstance(instance)
instance.setScene(scene);
// Want to run the second animation.
// 0 is the first animation, and -1 is no animation.
instance.setSequence(1);
// Tell the instance to loop animations forever.
// This overrides the setting in the model itself.
instance.setSequenceLoopMode(2);
// Let's create another instance and do other stuff with it.
let instance2 = model.addInstance();
instance2.setScene(scene);
instance2.setSequence(0);
instance2.setSequenceLoopMode(2);
instance2.move([100, 100, 0]);
instance2.uniformScale(0.5);
// And a third one.
let instance3 = model.addInstance();
instance3.setScene(scene);
instance3.setSequence(2);
instance3.setSequenceLoopMode(2);
instance3.move([-100, -100, 0]);
}
});
// The viewer has the update(), startFrame(), render(), and updateAndRender() functions.
// Generally speaking, you will want a simple never ending loop like the one that follows, but who knows. The control is in your hands.
(function step() {
requestAnimationFrame(step);
viewer.updateAndRender();
})();
================================================
FILE: clients/map/README.md
================================================
A Warcraft 3 map viewer client. Drag and drop a map file (W3X, W3M) into the page.
================================================
FILE: clients/map/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Map | HIVE</title>
<meta charset="utf-8" />
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
color: white;
}
#canvas {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
#stats {
position: absolute;
left: 10px;
top: 10px;
user-select: none;
pointer-events: none;
}
#status {
position: absolute;
left: 10%;
top: 10%;
width: 80%;
height: 80%;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
pointer-events: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div id="status">Loading the page</div>
<div id="stats">
<div id="cells"></div>
<div id="instances"></div>
<div id="particles"></div>
</div>
<script src="../thirdparty/fpsmeter.min.js"></script>
<script src="/clients/map.min.js"></script>
</body>
</html>
================================================
FILE: clients/map/index.js
================================================
import { basename, extname } from "../../src/common/path";
import War3MapViewer from '../../src/viewer/handlers/w3x/viewer';
import { setupCamera } from "../shared/camera";
import localOrHive from "../shared/localorhive";
let statusElement = document.getElementById('status');
statusElement.textContent = 'Initializing the viewer';
let canvas = document.getElementById('canvas');
// true because the Reforged Hive API is used in localOrHive.
let viewer = new War3MapViewer(canvas, localOrHive, true);
let thingsLoading = [];
function updateStatus() {
if (thingsLoading.length) {
statusElement.textContent = `Loading ${thingsLoading.join(', ')}`;
} else {
statusElement.textContent = '';
}
}
for (let key of viewer.promiseMap.keys()) {
thingsLoading.push(basename(key));
}
updateStatus();
viewer.on('loadstart', ({ fetchUrl }) => {
thingsLoading.push(basename(fetchUrl));
updateStatus();
});
viewer.on('loadend', ({ fetchUrl }) => {
let file = basename(fetchUrl);
let index = thingsLoading.indexOf(file);
if (index !== -1) {
thingsLoading.splice(index, 1);
updateStatus();
}
});
let meter = new FPSMeter({
position: 'absolute',
right: '10px',
top: '10px',
left: 'calc(100% - 130px)',
theme: 'transparent',
heat: 1,
graph: 1
});
let cellsElement = document.getElementById('cells');
let instancesElement = document.getElementById('instances');
let particlesElement = document.getElementById('particles');
(function step() {
requestAnimationFrame(step);
viewer.updateAndRender();
meter.tick();
cellsElement.textContent = `Cells: ${viewer.visibleCells}`;
instancesElement.textContent = `Instances: ${viewer.visibleInstances}`;
particlesElement.textContent = `Particles: ${viewer.updatedParticles}`;
}());
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
if (viewer.loadedBaseFiles) {
let file = e.dataTransfer.files[0];
let name = file.name;
let ext = extname(name);
if (ext === '.w3m' || ext === '.w3x') {
let reader = new FileReader();
reader.addEventListener('loadend', e => {
viewer.loadMap(e.target.result);
setupCamera(viewer.map.worldScene, { distance: 3000 });
});
reader.readAsArrayBuffer(file);
}
}
});
================================================
FILE: clients/mdlx/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>MDX <-> MDL</title>
<meta charset="utf-8" />
<style>
#status {
width: 500px;
height: 100px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
user-select: none;
pointer-events: none;
}
</style>
</head>
<body>
<div id="status">Drop any combination of models (.mdl, .mdx) to convert them</div>
<script src="../thirdparty/filesaver.js"></script>
<script src="/clients/mdlx.min.js"></script>
</body>
</html>
================================================
FILE: clients/mdlx/index.js
================================================
import { extname } from "../../src/common/path";
import { version } from "../../src/version";
import Model from '../../src/parsers/mdlx/model';
console.log('Viewer version', version);
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
for (let file of e.dataTransfer.files) {
let name = file.name;
let ext = extname(name);
if (ext === '.mdx' || ext === '.mdl') {
let reader = new FileReader();
reader.addEventListener('loadend', (e) => {
let model = new Model();
model.load(e.target.result);
let buffer;
let type;
if (ext === '.mdl') {
buffer = model.saveMdx().buffer;
type = 'application/octet-stream';
ext = 'mdx';
} else {
buffer = model.saveMdl();
type = 'text/plain';
ext = 'mdl'
}
saveAs(new Blob([buffer], { type }), name.slice(0, -3) + ext);
});
if (ext === '.mdl') {
reader.readAsText(file);
} else {
reader.readAsArrayBuffer(file);
}
}
}
});
================================================
FILE: clients/mdlxoptimizer/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>MDLX Optimizer</title>
<meta charset="utf-8" />
</head>
<body>
<script src="../thirdparty/filesaver.js"></script>
<script src="/clients/mdlxoptimizer.min.js"></script>
</body>
</html>
================================================
FILE: clients/mdlxoptimizer/index.ts
================================================
import { extname } from "../../src/common/path";
// @ts-ignore
import { getAllFileEntries, readEntry } from "../shared/utils";
import MdlxModel from '../../src/parsers/mdlx/model';
import AnimatedObject from '../../src/parsers/mdlx/animatedobject';
import { Animation } from '../../src/parsers/mdlx/animations';
import { getValuesDiff } from '../../src/utils/mdlx/sanitytest/tracks';
type Value = Uint32Array | Float32Array;
type Entry = [number, Value, Value, Value];
const FRAME = 0;
const VALUE = 1;
const INTAN = 2;
const OUTTAN = 3;
function optimizeAnimation(model: MdlxModel, animation: Animation) {
const sequences = model.sequences;
const { interpolationType, globalSequenceId, frames, values, inTans, outTans } = animation;
if (globalSequenceId !== -1) {
console.error('NEED TO ADD GLOBAL ANIMATION SUPPORT');
return 0;
}
// Map the keyframes to entries, and remove duplicated frames while we're at it.
const entryMap = new Map<number, Entry>();
for (let i = 0, l = frames.length; i < l; i++) {
entryMap.set(frames[i], [frames[i], values[i], inTans[i], outTans[i]])
}
// Now back to an array.
const entries: Entry[] = [...entryMap.values()];
// And sort it.
entries.sort((a, b) => a[FRAME] - b[FRAME]);
// Get all of the edge entries.
// In other words, the frames of the current first and last entries for every sequence.
const edges = new Set<number>();
for (const sequence of sequences) {
const [start, end] = sequence.interval;
let startFrame = Infinity;
let endFrame = Infinity;
for (const entry of entries) {
const frame = entry[FRAME];
if (startFrame === Infinity && frame - start >= 0) {
startFrame = frame;
}
if (end - frame >= 0) {
endFrame = frame;
}
}
edges.add(startFrame);
edges.add(endFrame);
}
const keptEntries: Entry[] = [];
// Now we can iterate over the entries.
for (let i = 0, l = entries.length; i < l; i++) {
const entry = entries[i];
const frame = entry[FRAME];
// Edge entries are left as-is.
if (edges.has(frame)) {
keptEntries.push(entry);
} else {
// Otherwise, let's see if this entry is in any sequence to begin with.
for (const sequence of sequences) {
const [start, end] = sequence.interval;
if (frame >= start && frame <= end) {
keptEntries.push(entry);
break;
}
}
}
}
const finalEntries: Entry[] = [];
// Now that all of the entries are valid in sequences, we can check for values.
if (keptEntries.length >= 2) {
for (let i = 0, l = keptEntries.length; i < l; i++) {
const entry = keptEntries[i];
const frame = entry[FRAME];
// Once again, don't touch edges.
if (edges.has(frame)) {
finalEntries.push(entry);
continue;
}
// Otherwise, if this isn't the first or last entries, check for equal values.
if (i > 0 && i < keptEntries.length - 1) {
const prevEntry = keptEntries[i - 1];
const nextEntry = keptEntries[i + 1];
const difference = getValuesDiff(prevEntry[VALUE], entry[VALUE], nextEntry[VALUE]);
if (difference > 0.0001) {
finalEntries.push(entry);
}
}
}
}
const newFrames = [];
const newValues = [];
const newInTans = [];
const newOutTans = [];
for (const entry of finalEntries) {
newFrames.push(entry[FRAME]);
newValues.push(entry[VALUE]);
if (interpolationType > 1) {
newInTans.push(entry[INTAN]);
newOutTans.push(entry[OUTTAN]);
}
}
animation.frames = newFrames;
animation.values = newValues;
animation.inTans = newInTans;
animation.outTans = newOutTans;
return frames.length - newFrames.length;
}
function optimizeAnimations(model: MdlxModel, animations: Animation[]) {
let tracks = 0;
for (const animation of animations) {
tracks += optimizeAnimation(model, animation);
}
return tracks;
}
function optimizeMaterials(model: MdlxModel) {
let tracks = 0;
for (const material of model.materials) {
for (const layer of material.layers) {
tracks += optimizeAnimations(model, layer.animations)
}
}
return tracks;
}
function optimizeObjects(model: MdlxModel, objects: AnimatedObject[]) {
let tracks = 0;
for (const object of objects) {
tracks += optimizeAnimations(model, object.animations);
}
return tracks;
}
function optimizeModel(name: string, buffer: ArrayBuffer) {
try {
const model = new MdlxModel();
model.load(buffer);
let tracks = 0;
tracks += optimizeMaterials(model);
tracks += optimizeObjects(model, model.textureAnimations);
tracks += optimizeObjects(model, model.geosetAnimations);
tracks += optimizeObjects(model, model.bones);
tracks += optimizeObjects(model, model.lights);
tracks += optimizeObjects(model, model.helpers);
tracks += optimizeObjects(model, model.attachments);
tracks += optimizeObjects(model, model.particleEmitters);
tracks += optimizeObjects(model, model.particleEmitters2);
tracks += optimizeObjects(model, model.particleEmittersPopcorn);
tracks += optimizeObjects(model, model.ribbonEmitters);
tracks += optimizeObjects(model, model.cameras);
tracks += optimizeObjects(model, model.collisionShapes);
console.log(`Removed ${tracks} tracks`);
return model.saveMdx();
} catch (e) {
console.error(`Error for "${name}": ${e}`);
return undefined;
}
}
async function optimizeDataTransfer(dataTransfer: DataTransfer) {
const entries = await getAllFileEntries(dataTransfer);
const names = [];
const promises = [];
for (let entry of entries) {
const name = entry.name;
const ext = extname(name);
if (ext === '.mdx' || ext === '.mdl') {
names.push(name);
promises.push(readEntry(entry, ext === '.mdl'));
}
}
const buffers = await Promise.all(promises);
const optimizedBuffers = [];
for (let i = 0, l = buffers.length; i < l; i++) {
optimizedBuffers.push(optimizeModel(names[i], buffers[i]));
}
for (let i = 0, l = buffers.length; i < l; i++) {
const buffer = optimizedBuffers[i];
if (buffer) {
// @ts-ignore
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'opt_' + names[i]);
}
}
}
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
if (e.dataTransfer) {
optimizeDataTransfer(e.dataTransfer);
}
});
================================================
FILE: clients/melee/README.md
================================================
A small tool to fake a map as a Melee map. This changes the map's icon when it is listed in the game. I don't know of any other effects.
================================================
FILE: clients/melee/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Melee</title>
<meta charset="utf-8" />
<style>
.center {
text-align: center;
user-select: none;
}
</style>
</head>
<body>
<p class="center">Drop a map anywhere</p>
<script src="../../dist/viewer.min.js"></script>
<script src="../thirdparty/filesaver.js"></script>
<script src="index.js"></script>
</body>
</html>
================================================
FILE: clients/melee/index.js
================================================
let w3x = ModelViewer.default.parsers.w3x;
function onLocalLoaded(e, name) {
let buffer = e.target.result;
console.log('Reading the map');
let map = new w3x.Map();
map.load(buffer);
console.log('Setting the map melee flag');
map.flags |= 0x4;
console.log('Reading war3map.w3i');
let w3i = new w3x.w3i.File();
w3i.load(map.get('war3map.w3i').arrayBuffer());
console.log('Setting the w3i melee flag');
w3i.flags |= 0x4;
console.log('Saving war3map.w3i');
map.set('war3map.w3i', w3i.save());
let newName = `${name.substr(0, name.length - 4)}_melee${name.substr(-4)}`;
console.log(`Saving the map as "${newName}"`);
saveAs(new Blob([map.save().buffer], { type: 'application/octet-stream' }), newName);
}
function onFileDrop(e) {
let file = e.dataTransfer.files[0];
let name = file.name.toLowerCase();
if (file && (name.endsWith('.w3m') || name.endsWith('.w3x'))) {
let reader = new FileReader();
reader.addEventListener('loadend', (e) => onLocalLoaded(e, file.name));
reader.readAsArrayBuffer(file);
}
}
document.addEventListener('dragover', (e) => {
e.preventDefault();
});
document.addEventListener('dragend', (e) => {
e.preventDefault();
onFileDrop(e);
});
document.addEventListener('drop', (e) => {
e.preventDefault();
onFileDrop(e);
});
================================================
FILE: clients/rebuild/README.md
================================================
This is a small proof of concept of rebuilding a "protected" map.
This is done by running the map's Jass script with a virtual machine, and keeping track of created objects (e.g. units and doodads).
The objects are then re-created in their "un-protected" files, e.g. `war3mapUnits.doo`.
Note that this is, indeed, merely a proof of concept, not a complete implementation.
================================================
FILE: clients/rebuild/components/rebuilder.js
================================================
import { extname } from "../../../src/common/path";
import War3Map from "../../../src/parsers/w3x/map";
import UnitsDooFile from "../../../src/parsers/w3x/unitsdoo/file";
import UnitsDooUnit from "../../../src/parsers/w3x/unitsdoo/unit";
import Context from '../../../src/utils/jass2/context';
import JassUnit from '../../../src/utils/jass2/types/unit';
import Component from "../../shared/component";
import { createElement } from "../../shared/domutils";
import localOrHive from "../../shared/localorhive";
import { aFrame } from "../../shared/utils";
export default class Rebuilder extends Component {
constructor(parentElement) {
super();
this.commonjText = '';
this.blizzardjText = '';
this.ready = false;
this.load();
parentElement.appendChild(this.container);
}
async load() {
this.text('Fetching files: "Scripts\\common.j", "Scripts\\Blizzard.j"');
this.text('Please wait...');
let [commonjResponse, blizzardjResponse] = await Promise.all([
fetch('https://www.hiveworkshop.com/data/static_assets/mpq/tft/scripts/common.j'),
fetch('https://www.hiveworkshop.com/data/static_assets/mpq/tft/scripts/blizzard.j'),
]);
let [commonjText, blizzardjText] = await Promise.all([
commonjResponse.text(),
blizzardjResponse.text(),
]);
this.commonjText = commonjText;
this.blizzardjText = blizzardjText;
this.text('Ready, drag and drop a map (*.w3m, *.w3x) anywhere on the page.');
}
clear() {
this.container.innerHTML = '';
}
text(text) {
createElement({ textContent: text, container: this.container });
}
rebuildFile(file) {
if (file) {
let name = file.name;
let ext = extname(name);
let isMap = ext === '.w3m' || ext === '.w3x';
this.clear();
if (isMap) {
this.text(`Reading ${name}`);
let reader = new FileReader();
reader.addEventListener('loadend', async (e) => {
let buffer = e.target.result;
this.text(`Parsing ${name}`);
let map = new War3Map();
try {
map.load(buffer);
} catch (e) {
this.text(`Failed to parse: ${e}`);
return;
}
let context = new Context();
this.text('Converting and running common.j');
await aFrame();
context.run(this.commonjText, true);
this.text('Converting and running Blizzard.j');
await aFrame();
context.run(this.blizzardjText, true);
this.text('Converting and running war3map.j');
await aFrame();
context.open(map);
this.text('Running config()');
await aFrame();
context.call('config');
this.text('Running main()');
await aFrame();
context.call('main');
this.text('Collecting handles');
await aFrame();
let unitsFile = new UnitsDooFile();
let units = unitsFile.units;
for (let handle of context.handles) {
if (handle instanceof JassUnit) {
let unit = new UnitsDooUnit();
unit.id = handle.unitId;
unit.location[0] = handle.x;
unit.location[1] = handle.y;
// For z need the height of the terrain!
unit.angle = handle.face / 180 * Math.PI;
unit.player = handle.player.index;
unit.targetAcquisition = handle.acquireRange;
units.push(unit);
}
}
this.text(`Saving war3mapUnits.doo with ${units.length} objects`);
await aFrame();
map.set('war3mapUnits.doo', unitsFile.save(false));
this.text('Finished');
saveAs(new Blob([map.get('war3mapUnits.doo').arrayBuffer()], { type: 'application/octet-stream' }), 'war3mapUnits.doo');
});
reader.readAsArrayBuffer(file);
} else {
this.text(`${name} is not a map`);
}
}
}
}
================================================
FILE: clients/rebuild/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Rebuilder</title>
<meta charset="utf-8" />
<style>
.log {}
.info {
display: block;
font-family: monospace;
white-space: pre;
}
.warn {
color: darkgoldenrod;
}
.error {
color: #cc0000;
}
.unused {
color: rgb(96, 166, 0);
}
</style>
</head>
<body>
<script src="../thirdparty/filesaver.js"></script>
<script src="/clients/rebuild.min.js"></script>
</body>
</html>
================================================
FILE: clients/rebuild/index.js
================================================
import Rebuilder from './components/rebuilder';
const rebuilder = new Rebuilder(document.body);
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
rebuilder.rebuildFile(e.dataTransfer.files[0]);
});
// For debugging etc.
window.rebuilder = rebuilder;
================================================
FILE: clients/recorder/README.md
================================================
This client is used to record unit animations into a collection of images, that can be downloaded in a zip file.
================================================
FILE: clients/recorder/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Recorder | HIVE</title>
<meta charset="utf-8" />
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
}
.left,
.right {
position: absolute;
width: 50%;
height: 100%;
padding: 5px;
box-sizing: border-box;
top: 0;
}
.left {
left: 0;
}
.right {
right: 0;
}
canvas {
width: 100%;
height: 100%;
}
#controls {
position: absolute;
left: 0;
top: 0;
color: white;
margin: 8px;
}
</style>
</head>
<body>
<div class="left">
<canvas id="canvas"></canvas>
<div id="controls">
<p id="sequence_name"></p>
<p id="frame_counter"></p>
</div>
</div>
<div class="right" id="right">
<!--<canvas id="output"></canvas>-->
</div>
<script src="../../dist/viewer.min.js"></script>
<script src="../thirdparty/jszip.min.js"></script>
<script src="../thirdparty/filesaver.js"></script>
<script src="../shared/camera.js"></script>
<script src="../shared/localorhive.js"></script>
<script src="index.js"></script>
</body>
</html>
================================================
FILE: clients/recorder/index.js
================================================
ModelViewer = ModelViewer.default;
let common = ModelViewer.common;
let quat = common.glMatrix.quat;
let vec3 = common.glMatrix.vec3;
let math = common.math;
let geometry = common.geometry;
var keyboard = {};
var mouse = { buttons: [false, false, false], x: 0, y: 0, x2: 0, y2: 0 };
var canvas = document.getElementById('canvas');
var viewer = new ModelViewer.viewer.ModelViewer(canvas, { alpha: true });
var instance;
viewer.on('error', (e) => console.error(e));
viewer.addHandler(ModelViewer.viewer.handlers.mdx, localOrHive);
viewer.addHandler(ModelViewer.viewer.handlers.blp);
viewer.addHandler(ModelViewer.viewer.handlers.tga);
viewer.addHandler(ModelViewer.viewer.handlers.dds);
let backgroundOpaque = true;
let turnTable = false;
let turnTableSpeed = 0;
let turnTableQuat = quat.create();
let isRecording = false;
let recordingFrame = 0;
let oneTimeRecord = false;
let zip = new JSZip();
let frameCounterElement = document.getElementById('frame_counter');
let sequenceNameElement = document.getElementById('sequence_name');
(function step() {
viewer.updateAndRender();
if (instance) {
instance.rotate(turnTableQuat);
if (isRecording || oneTimeRecord) {
oneTimeRecord = false;
zip.file(
`${recordingFrame++}_${instance.model.name}_${Math.floor(instance.frame)}.png`,
viewer.canvas.toDataURL().substring(22),
{ base64: true }
);
frameCounterElement.textContent = recordingFrame;
}
}
requestAnimationFrame(step);
})();
let scene = viewer.addScene();
scene.alpha = true;
setupCamera(scene, { distance: 500 });
console.log('Viewer version', ModelViewer.version);
// Run the next sequence for the given instance at e.
function runNextSequence(e) {
let instance = e.target;
instance.setSequence((instance.sequence + 1) % instance.model.sequences.length);
}
// Log load starts to the console.
viewer.on('loadstart', target => {
let path = target.fetchUrl;
if (path) {
console.log('Loading ' + target.fetchUrl);
}
});
// Log load ends to the console.
viewer.on('load', target => {
let path = target.fetchUrl;
if (path) {
console.log('Finished loading ' + target.fetchUrl);
}
});
function normalizePath(path) {
return path.toLocaleLowerCase().replace(/\\/g, '/');
}
// Load a local file
function onLocalFileLoaded(name, buffer) {
if (name.endsWith('.mdx')) {
let pathSolver = src => {
if (src === buffer) {
return src;
} else {
return localOrHive(normalizePath(src));
}
};
turnTableSpeed = 0;
quat.identity(turnTableQuat);
isRecording = false;
scene.clear();
viewer.load(buffer, pathSolver)
.then((model) => {
instance = model.addInstance();
instance.setSequenceLoopMode(2);
instance.setSequence(0);
sequenceNameElement.textContent = model.sequences[0].name;
scene.addInstance(instance);
});
}
}
canvas.addEventListener('contextmenu', function (e) {
e.preventDefault();
});
canvas.addEventListener('selectstart', function (e) {
e.preventDefault();
});
function onFileDrop(e) {
let file = e.dataTransfer.files[0];
if (file) {
let name = file.name.toLowerCase();
if (name.endsWith('.mdx') || name.endsWith('.blp')) {
let reader = new FileReader();
reader.addEventListener('loadend', e => onLocalFileLoaded(name, e.target.result));
reader.readAsArrayBuffer(file);
}
}
}
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
onFileDrop(e);
});
document.addEventListener('drop', e => {
e.preventDefault();
onFileDrop(e);
});
window.addEventListener('keydown', e => {
let key = e.key;
if (instance) {
let model = instance.model;
if (key === ' ') {
isRecording = !isRecording;
} else if (key === 'ArrowLeft') {
if (instance.sequence === 0) {
instance.setSequence(model.sequences.length - 1);
} else {
instance.setSequence(instance.sequence - 1);
}
sequenceNameElement.textContent = model.sequences[instance.sequence].name;
} else if (key === 'ArrowRight') {
if (instance.sequence === model.sequences.length - 1) {
instance.setSequence(0);
} else {
instance.setSequence(instance.sequence + 1);
}
sequenceNameElement.textContent = model.sequences[instance.sequence].name;
} else if (key === 'ArrowUp') {
turnTableSpeed += 0.2;
quat.setAxisAngle(turnTableQuat, [0, 0, 1], math.degToRad(turnTableSpeed));
} else if (key === 'ArrowDown') {
turnTableSpeed -= 0.2;
quat.setAxisAngle(turnTableQuat, [0, 0, 1], math.degToRad(turnTableSpeed));
} else if (key === 'Enter') {
oneTimeRecord = true;
} else if (key === 'Escape') {
if (recordingFrame > 0) {
zip.generateAsync({ type: 'blob' }).then(blob => {
saveAs(blob, `recorded_frames_${recordingFrame}.zip`);
zip = new JSZip();
recordingFrame = 0;
frameCounterElement.textContent = '';
});
}
}
}
if (key === 'b') {
backgroundOpaque = !backgroundOpaque;
if (backgroundOpaque) {
viewer.alpha = false;
sequenceNameElement.style.color = 'white';
frameCounterElement.style.color = 'white';
} else {
viewer.alpha = true;
sequenceNameElement.style.color = 'black';
frameCounterElement.style.color = 'black';
}
}
});
================================================
FILE: clients/sanitytest/README.md
================================================
This client runs the MDX sanity tester, and shows the information in a graphical manner.
It is used on the Hiveworkshop to find issues with Warcraft 3 models and textures.
================================================
FILE: clients/sanitytest/components/logger.js
================================================
import Component from "../../shared/component";
import Toggle from "../../shared/components/toggle";
import { createElement, scrolledToBottom, scrollToBottom } from "../../shared/domutils";
export default class Logger extends Component {
constructor(options) {
super({ ...options, className: 'console' });
this.messages = [];
this.tabs = createElement({ className: 'tabs', container: this.container });
this.logsToggler = new Toggle('Hide Logs', 'Show Logs', (e) => this.filter(), { container: this.tabs });
this.infoToggler = new Toggle('Hide Info', 'Show Info', (e) => this.filter(), { container: this.tabs });
this.errorsToggler = new Toggle('Hide Errors', 'Show Errors', (e) => this.filter(), { container: this.tabs });
this.contents = createElement({ className: 'tab-contents', container: this.container });
// Default to hiding the log spam.
this.logsToggler.toggle();
}
message(type, message) {
let loggerMessage = new LoggerMessage(type, message);
loggerMessage.filter(this.logsToggler.clicked, this.infoToggler.clicked, this.errorsToggler.clicked);
this.messages.push(loggerMessage);
// If scrolled all the way...
let scrolled = scrolledToBottom(this.contents);
this.contents.appendChild(loggerMessage.container);
// ...scroll back down after adding the message.
if (scrolled) {
scrollToBottom(this.contents);
}
}
log(message) {
this.message('log', message);
}
info(message) {
this.message('info', message);
}
error(message) {
this.message('error', message);
}
filter() {
// If scrolled all the way...
let scrolled = scrolledToBottom(this.contents);
for (let message of this.messages) {
message.filter(this.logsToggler.clicked, this.infoToggler.clicked, this.errorsToggler.clicked);
}
// ...scroll down after filtering.
if (scrolled) {
scrollToBottom(this.contents);
}
}
}
class LoggerMessage extends Component {
constructor(type, message) {
super({ className: type, textContent: message });
this.type = type;
}
matchFilters(logs, info, errors) {
let type = this.type;
return (type === 'log' && !logs) || (type === 'info' && !info) || (type === 'error' && !errors);
}
filter(logs, info, errors) {
if (this.matchFilters(logs, info, errors)) {
this.show();
} else {
this.hide();
}
}
}
================================================
FILE: clients/sanitytest/components/mdlview.js
================================================
import mdlStructure from "../../../src/utils/mdlx/mdlstructure";
import Component from "../../shared/component";
import { createElement } from "../../shared/domutils";
export default class MdlView extends Component {
constructor(parser) {
super({ className: 'mdl-view' });
const mdlNodes = mdlStructure(parser);
this.structureElement = createElement({ className: 'mdl-structure', container: this.container });
this.sourceElement = createElement({ tagName: 'pre', className: 'mdl-source', container: this.container });
this.nodes = [];
this.visibleNode = null;
for (let node of mdlNodes) {
this.nodes.push(new MdlViewNode(this, node, this.structureElement));
}
}
showNode(node) {
if (this.visibleNode) {
this.visibleNode.normal();
}
this.visibleNode = node;
node.highlight();
this.sourceElement.textContent = node.node.source;
}
}
class MdlViewNode extends Component {
constructor(view, node, parentElement) {
super({ className: 'clickable highlightable', textContent: node.name, container: parentElement });
this.container.addEventListener('click', () => view.showNode(this));
this.node = node;
this.nodes = [];
if (node.nodes && node.nodes.length) {
let container = createElement({ className: 'indent' });
for (let child of node.nodes) {
this.nodes.push(new MdlViewNode(view, child, container));
}
parentElement.appendChild(container);
}
}
}
================================================
FILE: clients/sanitytest/components/sanitytester.js
================================================
import { basename, extname } from "../../../src/common/path";
import War3Map from "../../../src/parsers/w3x/map";
import Component from "../../shared/component";
import Toggle from "../../shared/components/toggle";
import { createElement, hideElement, showElement } from "../../shared/domutils";
import localOrHive from "../../shared/localorhive";
import { getAllFileEntries, readFile, readEntry } from "../../shared/utils";
import Test from "../test";
import Logger from "./logger";
import Viewer from "./viewer";
export default class SanityTester extends Component {
constructor(parentElement) {
super({ className: 'client' });
this.tests = [];
this.visibleTest = null;
// Tests header
let testsHeader = createElement({ className: 'tests-header', container: this.container });
createElement({ tagName: 'h1', textContent: 'Tests', container: testsHeader, container: testsHeader });
// Tests body
let testsBody = createElement({ className: 'tests-body', container: this.container });
this.searchTests = createElement({ tagName: 'input', placeholder: 'Search tests', oninput: () => this.filterTests(), container: testsBody });
this.testsElement = createElement({ className: 'tests', container: testsBody });
// Results header
let resultsHeader = createElement({ className: 'results-header', container: this.container });
createElement({ tagName: 'h1', textContent: 'Test Results', container: resultsHeader, container: resultsHeader });
this.unusedToggle = new Toggle('Hide Unused', 'Show Unused', () => this.filterResults(), { container: resultsHeader });
this.warningToggle = new Toggle('Hide Warnings', 'Show Warnings', () => this.filterResults(), { container: resultsHeader });
this.severeToggler = new Toggle('Hide Severe', 'Show Severe', () => this.filterResults(), { container: resultsHeader });
this.errorToggler = new Toggle('Hide Errors', 'Show Errors', () => this.filterResults(), { container: resultsHeader });
// Results body
this.resultsBody = createElement({ className: 'results-body', container: this.container });
// Viewer/Logger and MDL header
let viewerLoggerMdlHeader = createElement({ className: 'viewer-and-mdl-header', container: this.container });
let viewerLoggerMdlH1 = createElement({ tagName: 'h1', textContent: '3D View', container: viewerLoggerMdlHeader });
// Viewer/Logger and MDL body
let viewerLoggerMdlBody = createElement({ className: 'viewer-and-mdl-body', container: this.container });
let viewerLogger = createElement({ className: 'viewer-and-console', container: viewerLoggerMdlBody });
this.mdl = createElement({ className: 'mdl hidden', container: viewerLoggerMdlBody });
// Viewer/Logger and MDL toggler
new Toggle('View in MDL', 'View in 3D', (e) => {
if (e.clicked) {
viewerLoggerMdlH1.textContent = 'MDL View';
hideElement(viewerLogger);
showElement(this.mdl);
if (!this.viewer.controls.animationToggle.clicked) {
this.viewer.controls.animationToggle.toggle();
}
} else {
viewerLoggerMdlH1.textContent = '3D View';
showElement(viewerLogger);
// If the page was resized in MDL view, the camera thinks the size of the canvas is 1x1.
// Need to resize now that the canvas is visible again and has a real size.
this.viewer.orbitCamera.onResize();
hideElement(this.mdl);
}
}, { container: viewerLoggerMdlHeader });
// Actual Viewer and Logger
this.logger = new Logger({ container: viewerLogger });
this.viewer = new Viewer(this, { container: viewerLogger });
// Append at the end to avoid re-renders.
parentElement.appendChild(this.container);
}
filterTests() {
let term = this.searchTests.value.toLowerCase();
for (let test of this.tests) {
if (test.name.toLowerCase().includes(term)) {
test.meta.show();
} else {
test.meta.hide();
}
}
}
filterResults() {
if (this.visibleTest && this.visibleTest.results) {
this.visibleTest.results.filter(this.unusedToggle.clicked, this.warningToggle.clicked, this.severeToggler.clicked, this.errorToggler.clicked);
}
}
// pathSolver is used for API tests.
test(name, buffer, render, pathSolver) {
this.logger.info(`Parsing ${name}`);
let test;
try {
test = new Test(this, name, buffer, pathSolver);
} catch (e) {
this.logger.error(`An error occured before the test could finish: ${e.stack}`)
}
this.tests.push(test);
this.testsElement.appendChild(test.meta.container);
test.meta.container.scrollIntoView();
if (test.results) {
this.resultsBody.appendChild(test.results.container);
}
if (test.mdl) {
this.mdl.appendChild(test.mdl.container);
}
this.viewer.load(test);
if (render) {
this.render(test);
} else {
test.hide();
}
}
render(test) {
if (test !== this.visibleTest) {
if (this.visibleTest) {
this.visibleTest.hide();
}
this.visibleTest = test;
this.filterResults();
test.show();
this.viewer.render(test);
}
}
loadMap(name, buffer) {
this.logger.info(`Parsing ${name}`);
let map = new War3Map();
try {
map.load(buffer);
} catch (e) {
this.logger.error(`Failed to parse ${name}: ${e}`);
return;
}
let pathSolver = (src, params) => {
let file = map.get(src);
if (file) {
return file.bytes();
}
return localOrHive(src, params);
};
let render = true;
for (let importName of map.getImportNames()) {
let ext = extname(importName);
if (ext === '.mdx' || ext === '.mdl' || ext === '.blp' || ext === '.dds' || ext === '.tga') {
let file = map.get(importName);
if (file) {
if (ext === '.mdx') {
this.test(`${name}:${importName}`, file.arrayBuffer(), render, pathSolver);
} else if (ext === '.mdl') {
this.test(`${name}:${importName}`, file.text(), render, pathSolver);
} else if (ext === '.blp' || ext === '.dds' || ext === '.tga') {
this.test(`${name}:${importName}`, file.arrayBuffer(), render);
}
render = false;
} else {
this.logger.error(`The map says it imports ${importName} but it couldn't be found`);
}
}
}
}
/**
* Load a file, e.g. resulting from a Drag & Drop action.
*/
async loadFile(file) {
let name = file.name;
let ext = extname(name);
if (ext === '.mdx' || ext === '.mdl' || ext === '.blp' || ext === '.dds' || ext === '.tga' || ext === '.w3x' || ext === '.w3m') {
this.logger.info(`Reading ${name}`);
let buffer = await readFile(file, ext === '.mdl');
if (ext === '.w3m' || ext === '.w3x') {
this.loadMap(name, buffer);
} else {
this.test(name, buffer, true);
}
} else {
this.logger.info(`${name} is not a supported file, skipping it`);
}
}
/**
* Load all of the entries from a data transfer, e.g. resulting from a Drag & Drop action.
*/
async loadDataTransfer(dataTransfer) {
let entries = await getAllFileEntries(dataTransfer);
let names = [];
let promises = [];
// First start reading all of the relevant files.
for (let entry of entries) {
let name = entry.name;
let ext = extname(name);
if (ext === '.mdx' || ext === '.mdl' || ext === '.blp' || ext === '.dds' || ext === '.tga' || ext === '.w3x' || ext === '.w3m') {
this.logger.info(`Reading ${name}`);
names.push(name.toLowerCase());
promises.push(readEntry(entry, ext === '.mdl'));
} else {
this.logger.info(`${name} is not a supported file, skipping it`);
}
}
// Finish reading...
let buffers = await Promise.all(promises);
// Now map from names to buffers.
let overrides = new Map();
for (let i = 0, l = names.length; i < l; i++) {
overrides.set(names[i], buffers[i]);
}
// Path solver to see if a resource that needs loading is one of the files in the data transfer.
let pathSolver = (src, params) => {
let override = overrides.get(basename(src).toLowerCase());
if (override) {
return override;
} else {
return localOrHive(src, params);
}
};
let render = true;
// Finally load the tests.
for (let [name, buffer] of overrides.entries()) {
if (name.endsWith('.w3m') || name.endsWith('.w3x')) {
this.loadMap(name, buffer);
} else {
this.test(name, buffer, render, pathSolver);
}
render = false;
}
}
/**
* Used by the Hiveworkshop to test resources.
*
* file=url&file=url2&override[path]=url3
*/
loadAPI(api) {
if (api !== '') {
let files = [];
let overrides = new Map();
for (let param of api.slice(1).split('&')) {
let [key, value] = param.split('=');
if (value !== undefined) {
// Test also overrides.
files.push(value);
if (key.startsWith('override')) {
// Discord changes \ to / in urls, ignoring escaping, so escape manually.
overrides.set(key.slice(9, -1).replace(/\//g, '\\'), value);
}
}
}
if (files.length) {
let pathSolver = (src, params) => {
let override = overrides.get(basename(src).toLowerCase());
if (override) {
return override;
} else {
return localOrHive(src, params);
}
};
let render = true;
for (let file of files) {
fetch(file)
.then(async (response) => {
let buffer;
if (file.endsWith('.mdl')) {
buffer = await response.text();
} else {
buffer = await response.arrayBuffer();
}
this.test(file, buffer, render, pathSolver);
render = false;
});
}
}
}
}
}
================================================
FILE: clients/sanitytest/components/teamcolors.js
================================================
export const TEAM_COLORS = [
{ name: 'Red', color: '#ff0402' },
{ name: 'Blue', color: '#0042ff' },
{ name: 'Teal', color: '#1be6ba' },
{ name: 'Purple', color: '#540081' },
{ name: 'Yellow', color: '#fffc00' },
{ name: 'Orange', color: '#ff8a0d' },
{ name: 'Green', color: '#20c000' },
{ name: 'Pink', color: '#e45bb0' },
{ name: 'Gray', color: '#949697' },
{ name: 'Light Blue', color: '#7ebff1' },
{ name: 'Dark Green', color: '#106247' },
{ name: 'Brown', color: '#4f2a05' },
{ name: 'Maroon', color: '#9c0000' },
{ name: 'Navy', color: '#0000c3' },
{ name: 'Turquoise', color: '#00ebff' },
{ name: 'Violet', color: '#bd00ff' },
{ name: 'Wheat', color: '#eccd86' },
{ name: 'Peach', color: '#f7a48b' },
{ name: 'Mint', color: '#c0ff80' },
{ name: 'Lavender', color: '#dcb9ec' },
{ name: 'Coal', color: '#4f4f55' },
{ name: 'Snow', color: '#ecf0ff' },
{ name: 'Emerald', color: '#00781e' },
{ name: 'Peanut', color: '#a46f33' },
{ name: 'Neutral', color: '#2e2d2e' },
];
================================================
FILE: clients/sanitytest/components/testmeta.js
================================================
import Component from "../../shared/component";
import { createElement } from "../../shared/domutils";
function singleOrPlural(name, count) {
if (count === 1) {
return name;
}
return `${name}s`;
}
export default class TestMeta extends Component {
constructor(name, parsingError, results, options) {
super({ ...options, className: 'clickable highlightable padded' });
this.name = createElement({ className: 'bold', textContent: name, container: this.container });
let container = createElement({ className: 'indent', container: this.container });
if (parsingError) {
createElement({ className: 'error', textContent: 'Parsing failed', container });
}
if (results.errors || results.severe || results.warnings || results.unused) {
if (results.errors) {
createElement({ className: 'error', textContent: `${results.errors} ${singleOrPlural('error', results.errors)}`, container });
}
if (results.severe) {
createElement({ className: 'severe', textContent: `${results.severe} ${singleOrPlural('severe warning', results.severe)}`, container });
}
if (results.warnings) {
createElement({ className: 'warning', textContent: `${results.warnings} ${singleOrPlural('warning', results.warnings)}`, container });
}
if (results.unused) {
createElement({ className: 'unused', textContent: `${results.unused} unused`, container });
}
} else {
createElement({ className: 'bold', textContent: 'Passed', container });
}
}
}
================================================
FILE: clients/sanitytest/components/testresults.js
================================================
import { imageDataToImage } from "../../../src/common/canvas";
import Component from "../../shared/component";
import { createElement } from "../../shared/domutils";
import getTooltip from "./tooltips";
import MdlxModel from '../../../src/parsers/mdlx/model';
import { BlpImage, CONTENT_JPG } from '../../../src/parsers/blp/image';
import { DdsImage, FOURCC_ATI2, FOURCC_DXT1, FOURCC_DXT3, FOURCC_DXT5 } from '../../../src/parsers/dds/image';
import TgaImage from '../../../src/parsers/tga/image';
import mdlxSanityTest from '../../../src/utils/mdlx/sanitytest/sanitytest';
import blpSanityTest from '../../../src/utils/blp/sanitytest';
import ddsSanityTest from '../../../src/utils/dds/sanitytest';
export default class TestResults extends Component {
constructor(parser) {
super();
this.nodes = [];
const container = this.container;
const isMdlx = parser instanceof MdlxModel;
const isBlp = parser instanceof BlpImage;
const isDds = parser instanceof DdsImage;
const isTga = parser instanceof TgaImage;
const isImage = isBlp || isDds || isTga;
if (isBlp || isDds || isTga) {
createElement({ textContent: `Width: ${parser.width}`, container });
createElement({ textContent: `Height: ${parser.height}`, container });
if (isBlp) {
if (parser.content === CONTENT_JPG) {
createElement({ textContent: `Content: JPG`, container });
} else {
createElement({ textContent: `Content: Palette`, container });
}
if (parser.alphaBits > 8) {
createElement({ textContent: `Alpha bits: ${parser.alphaBits} (fake)`, container });
} else {
createElement({ textContent: `Alpha bits: ${parser.alphaBits}`, container });
}
createElement({ textContent: `Mipmaps: ${parser.mipmaps()} (fake: ${parser.fakeMipmaps()})`, container });
} else if (isDds) {
if (parser.format === FOURCC_DXT1) {
createElement({ textContent: `Content: BC1 (DXT1)`, container });
} else if (parser.format === FOURCC_DXT3) {
createElement({ textContent: `Content: BC2 (DXT3)`, container });
} else if (parser.format === FOURCC_DXT5) {
createElement({ textContent: `Content: BC3 (DXT5)`, container });
} else if (parser.format === FOURCC_ATI2) {
createElement({ textContent: `Content: BC5 (ATI2)`, container });
} else {
createElement({ textContent: `Content: Not supported`, container });
}
createElement({ textContent: `Mipmaps: ${parser.mipmaps()}`, container });
}
createElement({ tagName: 'hr', container });
}
let results;
if (isMdlx) {
results = mdlxSanityTest(parser);
} else if (isBlp) {
results = blpSanityTest(parser);
} else if (isDds) {
results = ddsSanityTest(parser);
} else {
results = {};
}
if (results.nodes && results.nodes.length) {
for (let node of results.nodes) {
this.nodes.push(new TestResultsNode(node, container));
}
} else {
this.nodes.push(new TestResultsNode({ type: 'bold', message: 'Passed' }, container));
}
this.results = results;
if (isImage) {
createElement({ tagName: 'hr', container });
if (isBlp || isDds) {
for (let i = 0, l = parser.mipmaps(); i < l; i++) {
try {
let imageData;
if (isBlp) {
imageData = parser.getMipmap(i);
} else {
imageData = this.getDdsMipmap(parser, i);
}
this.addMipmap(imageData);
} catch (e) {
if (this.results.errors === undefined) {
this.results.errors = 1;
} else {
this.results.errors += 1;
}
this.nodes.push(new TestResultsNode({ type: 'error', message: `Mipmap ${i}: ${e}` }, this.container));
}
}
} else {
this.addMipmap(parser.data);
}
}
}
getDdsMipmap(parser, i) {
const mipmap = parser.getMipmap(i);
if (parser.format === FOURCC_ATI2) {
const imageData = new ImageData(mipmap.width, mipmap.height);
const inData = mipmap.data;
const outData = imageData.data;
for (let i = 0, l = mipmap.width * mipmap.height; i < l; i++) {
const offset2 = i * 2;
const offset4 = i * 4;
outData[offset4 + 0] = inData[offset2 + 0];
outData[offset4 + 1] = inData[offset2 + 1];
outData[offset4 + 2] = 0;
outData[offset4 + 3] = 255;
}
return imageData;
} else {
return new ImageData(new Uint8ClampedArray(mipmap.data.buffer), mipmap.width, mipmap.height);
}
}
addMipmap(imageData) {
const image = imageDataToImage(imageData);
image.className = 'padded';
this.container.appendChild(image);
}
filter(unused, warnings, severe, errors) {
for (let node of this.nodes) {
node.filter(unused, warnings, severe, errors);
}
}
}
class TestResultsNode extends Component {
constructor(node, parentElement) {
super();
let className = '';
let textContent = '';
let tooltip = '';
if (node.type === 'node') {
className = 'bold';
textContent = node.name;
} else {
className = node.type;
textContent = node.message;
tooltip = getTooltip(textContent);
if (tooltip.length) {
className += ' pointer';
}
}
const resultElement = createElement({ className, textContent, title: tooltip, container: this.container });
if (tooltip.length) {
createElement({ tagName: 'span', className: 'info_marker', textContent: 'tooltip', container: resultElement });
}
this.node = node;
this.nodes = [];
if (node.type === 'node') {
if (node.nodes.length || node.uses === 0) {
let container = createElement({ className: 'indent', container: this.container });
if (node.uses === 0) {
this.nodes.push(new TestResultsNode({ type: 'unused', message: 'Not used' }, container));
}
for (let child of node.nodes) {
this.nodes.push(new TestResultsNode(child, container));
}
}
}
parentElement.appendChild(this.container);
}
filter(unused, warnings, severe, errors) {
if (this.matchFilters(unused, warnings, severe, errors)) {
if (this.node.type === 'node') {
for (let child of this.nodes) {
child.filter(unused, warnings, severe, errors);
}
}
this.show();
} else {
this.hide();
}
}
matchFilters(unused, warnings, severe, errors) {
let node = this.node;
if (node.type === 'node') {
return ((node.unused || node.uses === 0) && !unused) || (node.warnings && !warnings) || (node.severe && !severe) || (node.errors && !errors);
} else {
let type = node.type;
return (type === 'unused' && !unused) || (type === 'warning' && !warnings) || (type === 'severe' && !severe) || (type === 'error' && !errors) || type === 'bold';
}
}
}
================================================
FILE: clients/sanitytest/components/tooltips.js
================================================
export default function getTooltip(message) {
if (message.includes('does not match the number of sequences')) { // Number of sequence extents (9) does not match the number of sequences (3)
return `Having the wrong amount of geoset extents can in some cases crash War 3 Model Editor (Magos).
This does not affect the game.`;
} else if (message.includes('has exactly the same value as tracks')) { // Track 3 at frame 1096 has exactly the same value as tracks 2 and 4
return 'A keyframe with the same value as the two keyframes sorrounding it is useless.';
} else if (message.includes('has roughly the same value as tracks')) { // Track 3 at frame 1096 has roughly the same value as tracks 2 and 4
return 'A keyframe with roughly the same value as the two keyframes sorrounding it is many times useless.';
} else if (message.includes('Missing opening track for sequence')) { // Missing opening track for sequence "Death" at frame 21000 where it is needed
return `When missing the opening keyframe for an animation, the game will wrap the animation and interpolate between the last and first keyframes.
However there is a bug in the game which causes the animation values to reverse.
To fix it, add a keyframe at the beginning of the animation.
`;
} else if (message.includes('has the same frame')) { // Track 7 has the same frame 1267 as track 6
return 'Remove one of the keyframes.'
} else if (message === 'Missing the Origin attachment point') { // Missing the Origin attachment point
return `Missing the Origin attachment stops many in-game effects from attaching to models.
Not relevant to portraits and special effects.`;
} else if (message.includes('is not in global sequence')) { // Track 17 at frame 4577 is not in global sequence 2
return `This keyframe uses a global sequence, but its frame is outside of the global sequence's range.`;
} else if (message === 'Missing "Stand" sequence') { // Missing "Stand" sequence
return `Missing the stand animation can cause issues for models that are used as units.
Not relevant to portraits.`;
} else if (message === 'Missing "Death" sequence') { // Missing "Death" sequence
return `Missing the death animation makes particles and other effects linger for a short time after an object using this model dies.
Not relevant to portraits.`;
} else if (message.endsWith('is not in any sequence')) {
return 'A keyframe that is not in any animation is useless.';
} else if (message.includes('is lower than the track before it at')) {
return 'A keyframe is not supposed to have a frame before the previous keyframe.';
} else if (message === 'There are no vertices attached to this bone') {
return 'Bones with no attached vertices should preferably be converted to helpers.'
} else {
//console.log('getTooltip', message)
}
return '';
}
================================================
FILE: clients/sanitytest/components/viewer.js
================================================
import ModelViewer from '../../../src/viewer/viewer';
import mdxHandler from '../../../src/viewer/handlers/mdx/handler';
import blpHandler from '../../../src/viewer/handlers/blp/handler';
import ddsHandler from '../../../src/viewer/handlers/dds/handler';
import tgaHandler from '../../../src/viewer/handlers/tga/handler';
import Component from "../../shared/component";
import { createElement } from "../../shared/domutils";
import localOrHive from "../../shared/localorhive";
import { setupCamera } from "../../shared/camera";
import ViewerControls from "./viewercontrols";
import createPrimitive from '../../../src/utils/mdlx/primitives/createprimitive';
import { createUnitRectangle, createUnitCube, createUnitSphere } from '../../../src/utils/mdlx/primitives/primitives';
import { filename } from '../../../src/common/path';
import Model from '../../../src/viewer/model';
import Texture from '../../../src/viewer/texture';
import MdxModel from '../../../src/viewer/handlers/mdx/model';
import { Shape } from '../../../src/parsers/mdlx/collisionshape';
export default class Viewer extends Component {
constructor(tester, options) {
super({ ...options, className: 'viewer' });
this.tester = tester;
this.messages = [];
this.canvas = createElement({ tagName: 'canvas', style: 'width:100%;height:100%', container: this.container });
this.controls = new ViewerControls(this, { container: this.container });
let viewer = new ModelViewer(this.canvas);
let scene = viewer.addScene();
this.viewer = viewer;
this.scene = scene;
this.visibleTest = null;
this.teamColor = 0;
scene.color.fill(0.2);
this.orbitCamera = setupCamera(scene, {
onManualChange: () => {
this.setCamera(-1);
this.controls.setCamera(-1);
},
});
viewer.on('loadstart', (e) => {
tester.logger.log(`[Viewer] Loading ${e.fetchUrl}`);
});
viewer.on('loadend', (e) => {
tester.logger.log(`[Viewer] Loaded ${e.fetchUrl}`);
});
viewer.on('error', (e) => {
if (e.fetchUrl) {
tester.logger.error(`[Viewer] ${e.error}: ${e.fetchUrl}`);
} else {
tester.logger.error(`[Viewer] ${e.error}: ${e.reason}`);
}
});
viewer.addHandler(mdxHandler, localOrHive, true);
viewer.addHandler(blpHandler);
viewer.addHandler(ddsHandler);
viewer.addHandler(tgaHandler);
this.textureModel = null;
this.boxModel = null;
this.sphereModel = null;
createPrimitive(viewer, createUnitRectangle(), { twoSided: true })
.then((model) => {
this.textureModel = model;
});
createPrimitive(viewer, createUnitCube(), { lines: true })
.then((model) => {
this.boxModel = model;
});
createPrimitive(viewer, createUnitSphere(12, 12), { lines: true })
.then((model) => {
this.sphereModel = model;
});
let lastTime = performance.now();
let step = () => {
requestAnimationFrame(step);
let now = performance.now();
let dt = now - lastTime;
lastTime = now;
if (this.controls.animationToggle.clicked) {
viewer.updateAndRender(0);
} else {
viewer.updateAndRender(dt);
}
if (this.visibleTest) {
let instance = this.visibleTest.instance;
if (instance.sequenceEnded) {
let sequence = instance.sequence;
if (!this.controls.cycleToggle.clicked) {
sequence += 1;
if (sequence === instance.model.sequences.length) {
sequence = 0;
}
this.setSequence(sequence);
}
}
this.controls.frame(instance.frame);
}
};
step();
}
async load(test) {
const modelOrTexture = await this.viewer.load(test.parser, (src, params) => {
if (src === test.parser) {
return src;
}
// Used for map and API tests.
if (test.pathSolver) {
return test.pathSolver(src, params);
}
return localOrHive(src, params);
});
if (!modelOrTexture) {
return;
}
let instance;
if (modelOrTexture instanceof MdxModel) {
instance = modelOrTexture.addInstance();
instance.setTeamColor(this.teamColor);
let boundingBox = this.boxModel.addInstance();
boundingBox.hide();
boundingBox.setScene(this.scene);
boundingBox.setParent(instance);
let boundingSphere = this.sphereModel.addInstance();
boundingSphere.hide();
boundingSphere.setScene(this.scene);
boundingSphere.setParent(instance);
test.boundingBox = boundingBox;
test.boundingSphere = boundingSphere;
// let cameraPromises = [];
// for (let camera of modelOrTexture.cameras) {
// console.log(camera)
// cameraPromises.push(ModelViewer.default.utils.mdlx.createPrimitive(this.viewer, ModelViewer.default.utils.mdlx.primitives.createFrustum(camera.fieldOfView, this.canvas.width / this.canvas.height, camera.nearClippingPlane, camera.farClippingPlane), { lines: true }));
// }
// Promise.all(cameraPromises)
// .then((cameraModels) => {
// for (let i = 0, l = cameraModels.length; i < l; i++) {
// let model = cameraModels[i];
// let instance = model.addInstance();
// //instance.hide();
// instance.setScene(this.scene);
// instance.setLocation(modelOrTexture.cameras[i].position);
// instance.face(modelOrTexture.cameras[i].targetPosition, [0, 0, 1]);
// test.cameras.push(instance);
// }
// });
for (let shape of modelOrTexture.collisionShapes) {
if (shape.type === 0) {
const shapeInstance = this.boxModel.addInstance();
const [min, max] = shape.vertices;
let x = (max[0] + min[0]) / 2;
let y = (max[1] + min[1]) / 2;
let z = (max[2] + min[2]) / 2;
let w = (max[0] - min[0]) / 2;
let d = (max[1] - min[1]) / 2;
let h = (max[2] - min[2]) / 2;
shapeInstance.hide();
shapeInstance.setLocation([x, y, z]);
shapeInstance.setScale([w, d, h]);
shapeInstance.dontInheritScaling = false;
shapeInstance.setParent(instance.nodes[shape.index]);
shapeInstance.setScene(this.scene);
test.collisions.push(shapeInstance);
} else if (shape.type === 2) {
const shapeInstance = this.sphereModel.addInstance();
shapeInstance.hide();
shapeInstance.setParent(instance.nodes[shape.index]);
shapeInstance.uniformScale(shape.boundsRadius);
shapeInstance.setScene(this.scene);
test.collisions.push(shapeInstance);
} else {
console.log('COLLISION SHAPE NOT SUPPOTED', shape)
}
}
} else {
instance = this.textureModel.addInstance();
instance.scale([modelOrTexture.width, modelOrTexture.height, 1]);
instance.setTexture(0, modelOrTexture);
}
instance.hide();
instance.setSequenceLoopMode(2);
instance.setScene(this.scene);
test.resource = modelOrTexture;
test.instance = instance;
this.tryToInjectCustomTextures(test);
if (test === this.tester.visibleTest) {
this.render(test);
}
}
render(test) {
if (test.instance) {
if (this.visibleTest) {
this.visibleTest.instance.hide();
if (this.visibleTest.boundingBox) {
this.visibleTest.boundingBox.hide();
this.visibleTest.boundingSphere.hide();
}
// for (let camera of this.visibleTest.cameras) {
// camera.hide();
// }
for (const collision of this.visibleTest.collisions) {
collision.hide();
}
}
this.visibleTest = test;
if (test.instance.model.sequences.length) {
this.controls.updateInstance(test.instance);
this.viewer.clearEmittedObjects();
if (test.instance.sequence === -1) {
this.setSequence(0);
} else {
this.setSequence(test.instance.sequence)
}
this.controls.show();
} else {
this.controls.hide();
}
test.instance.show();
this.updateExtents();
// for (let camera of test.cameras) {
// camera.show();
// }
if (this.controls.collisionsToggle.clicked) {
for (const collision of test.collisions) {
collision.show();
}
}
}
}
updateExtents() {
if (this.visibleTest && this.visibleTest.boundingBox) {
let mode = this.controls.extentElement.selectedIndex;
if (mode === 0 || mode === 2) {
this.visibleTest.boundingBox.hide();
} else {
this.visibleTest.boundingBox.show();
}
if (mode === 0 || mode === 1) {
this.visibleTest.boundingSphere.hide();
} else {
this.visibleTest.boundingSphere.show();
}
}
}
showCollisions(show) {
if (this.visibleTest) {
for (const collision of this.visibleTest.collisions) {
if (show) {
collision.show();
} else {
collision.hide();
}
}
}
}
setSequence(index) {
this.visibleTest.instance.setSequence(index);
if (this.visibleTest.boundingBox) {
let extent;
if (index === -1) {
extent = this.visibleTest.parser.extent;
} else {
extent = this.visibleTest.parser.sequences[index].extent;
let { max, min } = extent;
// If this sequence has no extent, use the model extent instead.
if (max[0] === 0 && max[1] === 0 && max[2] === 0 && min[0] === 0 && min[1] === 0 && min[2] === 0) {
extent = this.visibleTest.parser.extent;
}
}
let { max, min } = extent;
let x = (max[0] + min[0]) / 2;
let y = (max[1] + min[1]) / 2;
let z = (max[2] + min[2]) / 2;
let w = (max[0] - min[0]) / 2;
let d = (max[1] - min[1]) / 2;
let h = (max[2] - min[2]) / 2;
this.visibleTest.boundingBox.setLocation([x, y, z]);
this.visibleTest.boundingBox.setScale([w, d, h]);
this.visibleTest.boundingSphere.setLocation([x, y, z]);
this.visibleTest.boundingSphere.setUniformScale(extent.boundsRadius);
}
this.controls.setSequence(index);
}
setCamera(index) {
if (index === -1) {
this.orbitCamera.instance = null;
} else {
this.orbitCamera.applyInstanceCamera(this.visibleTest.instance);
}
}
setTeamColor(index) {
this.teamColor = index;
if (this.visibleTest) {
this.visibleTest.instance.setTeamColor(this.teamColor);
}
}
tryToInjectCustomTextures(customTest) {
// If the given test is a texture, inject it into all of the model tests.
if (customTest.resource instanceof Texture) {
for (let test of this.tester.tests) {
if (test !== customTest && test.instance && test.resource instanceof Model) {
let textures = test.parser.textures;
for (let i = 0, l = textures.length; i < l; i++) {
let a = filename(textures[i].path).toLowerCase();
let b = filename(customTest.name).toLowerCase();
if (a === b) {
test.instance.setTexture(i, customTest.resource);
this.tester.logger.info(`Injected ${customTest.name} as a custom texture for ${test.name}`);
}
}
}
}
} else {
// Otherwise, if it's a model test, inject all of the texture tests into it.
for (let test of this.tester.tests) {
if (test !== customTest && test.instance) {
if (test.resource instanceof Texture) {
let textures = customTest.parser.textures;
for (let i = 0, l = textures.length; i < l; i++) {
let a = filename(textures[i].path).toLowerCase();
let b = filename(test.name).toLowerCase();
if (a === b) {
customTest.instance.setTexture(i, test.resource);
this.tester.logger.info(`Injected ${test.name} as a custom texture for ${customTest.name}`);
}
}
} else {
// Inject this model into others.
let emitters = test.parser.particleEmitters;
let a = filename(customTest.name).toLowerCase();
for (let i = 0, l = emitters.length; i < l; i++) {
let b = filename(emitters[i].path).toLowerCase();
console.log('inject into other', a, b);
}
// Inject other models into this one.
emitters = customTest.parser.particleEmitters;
a = filename(customTest.name).toLowerCase();
for (let i = 0, l = emitters.length; i < l; i++) {
let b = filename(emitters[i].path).toLowerCase();
console.log('inject from other', a, b);
}
}
}
}
}
}
}
================================================
FILE: clients/sanitytest/components/viewercontrols.js
================================================
import { DebugRenderMode } from '../../../src/viewer/viewer';
import Component from "../../shared/component";
import Toggle from "../../shared/components/toggle";
import { clearSelect, createElement } from "../../shared/domutils";
import { TEAM_COLORS } from "./teamcolors";
export default class ViewerControls extends Component {
constructor(viewer, options) {
super({ ...options, className: 'viewer-controls' });
this.viewer = viewer;
// Team colors.
let container = createElement({ container: this.container });
createElement({ textContent: 'Team color:', container });
this.teamColorElement = createElement({ tagName: 'div', className: 'controls teamcolor', style: 'background-color:red', container });
this.teamColorsElement = createElement({
tagName: 'select', className: 'controls', onchange: () => {
this.viewer.setTeamColor(this.teamColorsElement.selectedIndex);
this.teamColorElement.style.backgroundColor = TEAM_COLORS[this.teamColorsElement.selectedIndex].color;
}, container
});
for (let teamColor of TEAM_COLORS) {
this.teamColorsElement.add(createElement({ tagName: 'option', textContent: teamColor.name }));
}
// Extents.
container = createElement({ container: this.container });
createElement({ textContent: 'Show extents:', container });
this.extentElement = createElement({
tagName: 'select', className: 'controls', onchange: () => this.viewer.updateExtents(), container
});
this.extentElement.add(createElement({ tagName: 'option', textContent: 'No' }));
this.extentElement.add(createElement({ tagName: 'option', textContent: 'Box' }));
this.extentElement.add(createElement({ tagName: 'option', textContent: 'Sphere' }));
this.extentElement.add(createElement({ tagName: 'option', textContent: 'Both' }));
this.extentElement.selectedIndex = 0;
// Collision shapes.
container = createElement({ container: this.container });
createElement({ textContent: 'Show collisions:', container });
this.collisionsToggle = new Toggle('No', 'Yes', (e) => {
this.viewer.showCollisions(e.clicked);
}, { className: 'controls', container });
// Run animations.
container = createElement({ container: this.container });
createElement({ textContent: 'Run Animations:', container });
this.animationToggle = new Toggle('Yes', 'No', (e) => {
if (e.clicked) {
this.viewer.viewer.frameTime = 0;
} else {
this.viewer.viewer.frameTime = 1000 / 60;
}
}, { className: 'controls', container });
// Cycle animations.
container = createElement({ container: this.container });
createElement({ textContent: 'Cycle Animations:', container });
this.cycleToggle = new Toggle('Yes', 'No', null, { className: 'controls', container });
// Select animations.
container = createElement({ container: this.container });
createElement({ textContent: 'Animations:', container });
this.sequencesElement = createElement({
tagName: 'select', className: 'controls', onchange: () => {
if (!this.cycleToggle.clicked) {
this.cycleToggle.toggle();
}
this.viewer.viewer.clearEmittedObjects();
this.viewer.setSequence(this.sequencesElement.selectedIndex - 1);
}, container
});
// Frame.
container = createElement({ container: this.container });
createElement({ textContent: 'Frame:', container });
this.frameElement = createElement({ container });
// Camera.
container = createElement({ container: this.container });
createElement({ textContent: 'Camera:', container });
this.camerasElement = createElement({ tagName: 'select', className: 'controls', onchange: () => this.viewer.setCamera(this.camerasElement.selectedIndex - 1), container });
// Debug modes.
container = createElement({ container: this.container });
createElement({ textContent: 'Debug Mode:', container });
this.debugRenderSelect = createElement({
tagName: 'select', className: 'controls', onchange: () => {
// Somewhat hacky way to treat an enum.
this.viewer.viewer.debugRenderMode = this.debugRenderSelect.selectedIndex;
}, container
});
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'None' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Diffuse' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Normal map' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Occlusion' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Roughness' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Metallic' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'TC Factor' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Emissive' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'TexCoords' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Normals' }));
this.debugRenderSelect.add(createElement({ tagName: 'option', textContent: 'Tangents' }));
}
frame(frame) {
this.frameElement.textContent = `${Math.floor(frame)}`;
}
updateInstance(instance) {
clearSelect(this.sequencesElement);
this.sequencesElement.add(createElement({ tagName: 'option', textContent: 'None' }));
for (let sequence of instance.model.sequences) {
this.sequencesElement.add(createElement({ tagName: 'option', textContent: sequence.name }));
}
clearSelect(this.camerasElement);
this.camerasElement.add(createElement({ tagName: 'option', textContent: 'None' }));
for (let camera of instance.model.cameras) {
this.camerasElement.add(createElement({ tagName: 'option', textContent: camera.name }));
}
}
setSequence(sequence) {
if (this.sequencesElement.options.length === 1) {
sequence = -1;
}
this.sequencesElement.selectedIndex = sequence + 1;
}
setCamera(camera) {
this.camerasElement.selectedIndex = camera + 1;
}
}
================================================
FILE: clients/sanitytest/index.css
================================================
html,
body {
padding: 0;
margin: 0;
font-family: monaco, monospace;
font-size: 14px;
}
.client {
display: grid;
width: 100%;
height: 100vh;
grid-template-rows: auto 1fr;
grid-template-columns: 200px 0.9fr 1.1fr;
grid-template-areas: "tests-header results-header viewer-and-mdl-header" "tests results viewer-and-mdl";
padding: 5px;
grid-gap: 5px;
box-sizing: border-box;
color: #d8cba7;
background-color: black;
}
.client>* {
/* Anything inside a grid has min-height: auto and min-width: auto which means it expands to its size, we need to fix that. */
min-height: 0;
min-width: 0;
}
.welcome {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #404040;
box-sizing: border-box;
}
.welcome>* {
width: 50%;
}
.welcome * {
padding: 10px;
}
h1 {
font-size: 16px;
margin: 0;
padding: 0;
text-align: center;
}
.tests-header, .results-header, .viewer-and-mdl-header {
background-color: #151515;
}
.tests-header {
grid-area: tests-header;
}
.tests-body {
grid-area: tests;
display: grid;
grid-template-rows: auto 1fr;
grid-auto-columns: 1fr;
grid-template-areas: "search-tests" "tests";
grid-gap: 5px;
box-sizing: border-box;
}
.tests {
overflow-y: auto;
overflow-x: hidden;
overflow-wrap: break-word;
background-color: #202020;
}
.results-header {
grid-area: results-header;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
.results-body {
grid-area: results;
overflow-y: auto;
overflow-x: hidden;
overflow-wrap: break-word;
background-color: #202020;
padding: 5px;
}
.viewer-and-mdl-header {
grid-area: viewer-and-mdl-header;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
.viewer-and-mdl-body {
grid-area: viewer-and-mdl;
}
.viewer-and-console {
display: grid;
width: 100%;
height: 100%;
grid-template-rows: 1fr 200px;
grid-template-columns: 1fr;
grid-template-areas: "viewer" "console";
grid-gap: 5px;
box-sizing: border-box;
}
.viewer-and-console>* {
/* Anything inside a grid has min-height: auto and min-width: auto which means it expands to its size, we need to fix that. */
min-height: 0;
min-width: 0;
}
.viewer {
grid-area: viewer;
display: grid;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
grid-template-areas: 'viewer-and-controls';
}
.viewer>* {
grid-area: viewer-and-controls;
min-height: 0;
min-width: 0;
}
.viewer-controls {
display: flex;
flex-direction: column;
gap: 2px;
z-index: 1;
pointer-events: none;
background-color: transparent;
padding: 5px;
}
.viewer-controls>* {
display: flex;
gap: 5px;
}
.controls {
pointer-events: all;
}
.console {
grid-area: console;
display: grid;
grid-template-rows: auto 1fr;
grid-gap: 5px;
box-sizing: border-box;
}
.console .tabs {
display: flex;
flex-direction: row;
align-items: center;
padding: 2px;
gap: 5px;
background-color: #202020;
}
.console .tab-contents {
min-height: 0;
min-width: 0;
overflow-y: auto;
overflow-x: hidden;
overflow-wrap: break-word;
background-color: #202020;
padding: 5px;
}
.mdl {
width: 100%;
height: 100%;
}
.mdl-view {
display: grid;
width: 100%;
height: 100%;
grid-auto-rows: 1fr;
grid-template-columns: 40% 1fr;
grid-template-areas: "mdl-structure mdl-source";
grid-gap: 5px;
box-sizing: border-box;
}
.mdl-view>* {
/* Anything inside a grid has min-height: auto and min-width: auto which means it expands to its size, we need to fix that. */
min-height: 0;
min-width: 0;
}
.mdl-structure {
grid-area: mdl-structure;
overflow-y: auto;
background-color: #202020;
padding: 5px;
}
.mdl-source {
grid-area: mdl-source;
overflow-y: auto;
background-color: #202020;
padding: 5px;
}
pre {
white-space: pre-wrap;
margin: 0;
}
table {
border-spacing: 0;
}
.indent {
margin-left: 1em;
}
.bold {
font-weight: bold;
}
.log {
color: #777777;
}
.info {}
.warning {
color: rgb(240, 204, 0);
}
.severe {
color: rgb(201, 110, 0);
}
.error {
color: rgb(200, 0, 0);
}
.unused {
color: rgb(80, 136, 2);
}
.clickable {
cursor: pointer;
}
.highlightable:hover {
background-color: #151515;
}
.highlighted {
background-color: #151515;
border-left: 3px solid #6f0d10;
}
.highlighted:hover {
background-color: #151515;
}
.center {
text-align: center;
}
.hidden {
display: none;
}
.padded {
padding: 5px;
}
.teamcolor {
width: 20px;
height: 20px;
}
.info_marker {
color: grey;
padding-left: 5px;
font-size: 9px;
}
.pointer {
cursor: pointer;
}
================================================
FILE: clients/sanitytest/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Sanity Test</title>
<meta charset="utf-8" />
<link href="index.css" rel="stylesheet">
</head>
<body>
<script src="/clients/sanitytest.min.js"></script>
</body>
</html>
================================================
FILE: clients/sanitytest/index.js
================================================
import SanityTester from './components/sanitytester';
const tester = new SanityTester(document.body);
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
tester.loadDataTransfer(e.dataTransfer);
});
tester.loadAPI(window.location.search);
// For debugging etc.
window.tester = tester;
================================================
FILE: clients/sanitytest/test.js
================================================
import { basename, extname } from "../../src/common/path";
import MdlxModel from '../../src/parsers/mdlx/model';
import { BlpImage } from '../../src/parsers/blp/image';
import { DdsImage } from '../../src/parsers/dds/image';
import TgaImage from '../../src/parsers/tga/image';
import TestResults from "./components/testresults";
import TestMeta from "./components/testmeta";
import MdlView from "./components/mdlview";
export default class Test {
constructor(tester, name, buffer, pathSolver) {
let ext = extname(name);
let isMdlx = ext === '.mdx' || ext === '.mdl';
let isBlp = ext === '.blp';
let isDds = ext === '.dds';
this.name = name;
this.shortName = basename(name);
this.parsingError = false;
this.results = null;
this.mdl = null;
this.pathSolver = pathSolver;
// Loaded and set by the viewer component.
this.resource = null;
this.instance = null;
this.boundingBox = null;
this.boundingSphere = null;
// this.cameras = [];
this.collisions = [];
if (isMdlx) {
this.parser = new MdlxModel();
} else if (isBlp) {
this.parser = new BlpImage();
} else if (isDds) {
this.parser = new DdsImage();
} else {
this.parser = new TgaImage();
}
try {
this.parser.load(buffer);
} catch (e) {
this.parsingError = true;
tester.logger.error(`Failed to parse ${name}: ${e}. The test will attempt to run on whatever data loaded`);
}
this.results = new TestResults(this.parser);
if (isMdlx) {
this.mdl = new MdlView(this.parser);
}
this.meta = new TestMeta(this.shortName, this.parsingError, this.results.results, { onclick: () => tester.render(this) });
}
show() {
this.meta.highlight();
if (this.results) {
this.results.show();
}
if (this.mdl) {
this.mdl.show();
}
}
hide() {
this.meta.normal();
if (this.results) {
this.results.hide();
}
if (this.mdl) {
this.mdl.hide();
}
}
}
================================================
FILE: clients/shared/camera.js
================================================
import { vec3, quat } from 'gl-matrix';
// Backwards compat with existing clients.
export function setupCamera(scene, options = {}) {
return new SimpleOrbitCamera(scene, options);
}
const vecHeap = vec3.create();
const vecHeap2 = vec3.create();
const quatHeap = quat.create();
const twistHeap = new Float32Array(1);
// Get the vector length between two touches.
function getTouchesLength(touch1, touch2) {
let dx = touch2.clientX - touch1.clientX;
let dy = touch2.clientY - touch1.clientY;
return Math.sqrt(dx * dx + dy * dy);
}
// Touch modes.
const TOUCH_MODE_INVALID = -1;
const TOUCH_MODE_ROTATE = 0;
const TOUCH_MODE_ZOOM = 1;
// An orbit camera setup example.
// Left mouse button controls the orbit itself.
// The right mouse button allows to move the camera and the point it's looking at on the XY plane.
// Scrolling zooms in and out.
export class SimpleOrbitCamera {
constructor(scene, options = {}) {
this.scene = scene;
this.canvas = scene.viewer.canvas;
this.camera = scene.camera;
// Movement per pixel of movement.
this.moveSpeed = options.moveSpeed || 2;
// Rotation in radians per pixel of movement.
this.rotationSpeed = options.rotationSpeed || (Math.PI / 180);
// Zoom factor per scroll.
this.zoomFactor = options.zoomFactor || 0.1;
this.horizontalAngle = options.horizontalAngle || Math.PI / 2;
this.verticalAngle = options.verticalAngle || Math.PI / 4;
this.distance = options.distance || 500;
this.position = options.position || vec3.create();
// What the camera is looking at.
this.target = options.target || vec3.create();
// The twist angle of the camera, which affects the "up" direction.
// For example, a twist of 180 degrees, i.e. PI, will flip everything upside down.
this.twist = options.twist || 0;
// Mouse.
this.mouse = { buttons: [false, false, false], x: 0, y: 0, x2: 0, y2: 0 };
// Touches.
this.touchMode = TOUCH_MODE_INVALID;
this.touches = [];
this.instance = null;
this.onManualChange = options.onManualChange || null;
this.fov = options.fov || Math.PI / 4;
this.nearClipPlane = options.nearClipPlane || 1;
this.farClipPlane = options.farClipPlane || 200000;
this.update();
window.addEventListener('resize', (e) => this.onResize());
setTimeout(() => this.onResize(), 0);
// Disable the context menu when right-clicking.
this.canvas.addEventListener('contextmenu', (e) => e.preventDefault());
this.canvas.addEventListener('selectstart', (e) => e.preventDefault());
// Track mouse clicks.
this.canvas.addEventListener('mousedown', (e) => {
e.preventDefault();
this.mouse.buttons[e.button] = true;
});
// And mouse unclicks.
// On the whole document rather than the canvas to stop annoying behavior when moving the mouse out of the canvas.
document.addEventListener('mouseup', (e) => {
e.preventDefault();
this.mouse.buttons[e.button] = false;
});
// Handle rotating and moving the camera when the mouse moves.
window.addEventListener('mousemove', (e) => {
this.mouse.x2 = this.mouse.x;
this.mouse.y2 = this.mouse.y;
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
let dx = this.mouse.x - this.mouse.x2;
let dy = this.mouse.y - this.mouse.y2;
if (this.mouse.buttons[0]) {
this.rotate(dx, dy);
}
if (this.mouse.buttons[2]) {
this.move(-dx, dy);
}
});
// Handle zooming when the mouse scrolls.
this.canvas.addEventListener('wheel', (e) => {
e.preventDefault();
let deltaY = e.deltaY;
if (e.deltaMode === 1) {
deltaY = deltaY / 3 * 100;
}
this.zoom(deltaY / 100);
});
// Listen to touches.
// Supports 1 or 2 touch points.
this.canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
let targetTouches = e.targetTouches;
if (targetTouches.length === 1) {
this.touchMode = TOUCH_MODE_ROTATE;
} else if (targetTouches.length == 2) {
this.touchMode = TOUCH_MODE_ZOOM;
} else {
this.touchMode = TOUCH_MODE_INVALID;
}
this.touches.length = 0;
this.touches.push(...targetTouches);
});
this.canvas.addEventListener('touchend', (e) => {
e.preventDefault();
this.touchMode = TOUCH_MODE_INVALID;
});
this.canvas.addEventListener('touchcancel', (e) => {
e.preventDefault();
this.touchMode = TOUCH_MODE_INVALID;
});
// Rotate or zoom based on the touch mode.
this.canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
let targetTouches = e.targetTouches;
if (this.touchMode === TOUCH_MODE_ROTATE) {
let oldTouch = this.touches[0];
let newTouch = targetTouches[0];
let dx = newTouch.clientX - oldTouch.clientX;
let dy = newTouch.clientY - oldTouch.clientY;
this.rotate(dx, dy);
} else if (this.touchMode === TOUCH_MODE_ZOOM) {
let len1 = getTouchesLength(this.touches[0], this.touches[1]);
let len2 = getTouchesLength(targetTouches[0], targetTouches[1]);
this.zoom((len1 - len2) / 50);
}
this.touches.length = 0;
this.touches.push(...targetTouches);
});
}
update() {
if (this.instance) {
let instance = this.instance;
let mdxCamera = instance.model.cameras[0];
mdxCamera.getTranslation(vecHeap, instance.sequence, instance.frame, instance.counter);
vec3.add(vecHeap, vecHeap, mdxCamera.position);
mdxCamera.getTargetTranslation(vecHeap2, instance.sequence, instance.frame, instance.counter);
vec3.add(vecHeap2, vecHeap2, mdxCamera.targetPosition);
mdxCamera.getRotation(twistHeap, instance.sequence, instance.frame, instance.counter);
this.twist = twistHeap[0];
// Change to world space in case the instance was moved in any way.
// I am not sure how well this will handle scales, twists, and other things.
vec3.transformMat4(vecHeap, vecHeap, instance.worldMatrix);
vec3.transformMat4(vecHeap2, vecHeap2, instance.worldMatrix);
this.moveToAndFace(vecHeap, vecHeap2);
} else {
this.updateInternalCamera();
}
}
// Move the camera and the target on the XY plane.
move(x, y) {
let dirX = this.camera.directionX;
let dirY = this.camera.directionY;
let w = this.canvas.width;
let h = this.canvas.height;
let aspect = w / h;
let sw = (x / w) * this.distance * aspect;
let sh = (y / h) * this.distance;
vec3.add(this.target, this.target, vec3.scale(vecHeap, vec3.normalize(vecHeap, vec3.set(vecHeap, dirX[0], dirX[1], 0)), sw));
vec3.add(this.target, this.target, vec3.scale(vecHeap, vec3.normalize(vecHeap, vec3.set(vecHeap, dirY[0], dirY[1], 0)), sh));
this.manualChange();
}
// Rotate the camera around the target.
rotate(x, y) {
this.horizontalAngle -= x * this.rotationSpeed;
this.verticalAngle -= y * this.rotationSpeed;
this.manualChange();
}
// Zoom the camera by changing the distance from the target.
zoom(factor) {
this.distance = Math.max(1, this.distance * (1 + factor * this.zoomFactor));
this.manualChange();
}
manualChange() {
this.updateInternalCamera();
if (this.instance) {
this.instance = null;
if (this.onManualChange) {
this.onManualChange();
}
}
}
// Resize the canvas automatically and update the camera.
onResize() {
let width = Math.max(this.canvas.clientWidth, 1);
let height = Math.max(this.canvas.clientHeight, 1);
this.canvas.width = width;
this.canvas.height = height;
this.scene.viewport[2] = width;
this.scene.viewport[3] = height;
this.camera.perspective(this.fov, width / height, this.nearClipPlane, this.farClipPlane);
}
moveToAndFace(position, target) {
vec3.sub(vecHeap, position, target);
let r = vec3.length(vecHeap);
let theta = Math.atan2(vecHeap[1], vecHeap[0]);
let phi = Math.acos(vecHeap[2] / r);
vec3.copy(this.target, target);
this.verticalAngle = phi;
this.horizontalAngle = theta + Math.PI / 2;
this.distance = r;
this.updateInternalCamera();
}
updateInternalCamera() {
// Limit the vertical angle so it doesn't flip.
// Since the camera uses a quaternion, flips don't matter to it, but this feels better.
this.verticalAngle = Math.min(Math.max(0.01, this.verticalAngle), Math.PI - 0.01);
quat.identity(quatHeap);
quat.rotateZ(quatHeap, quatHeap, this.horizontalAngle);
quat.rotateX(quatHeap, quatHeap, this.verticalAngle);
vec3.set(this.position, 0, 0, 1);
vec3.transformQuat(this.position, this.position, quatHeap);
vec3.scale(this.position, this.position, this.distance);
vec3.add(this.position, this.position, this.target);
let twist = this.twist - Math.PI / 2;
vec3.set(vecHeap, 0, -Math.cos(twist), -Math.sin(twist));
this.camera.moveToAndFace(this.position, this.target, vecHeap);
}
applyInstanceCamera(instance) {
this.instance = instance;
this.fov = instance.model.cameras[0].fieldOfView;
this.onResize();
this.update();
}
}
================================================
FILE: clients/shared/component.js
================================================
import { createElement, hideElement, showElement } from './domutils';
export default class Component {
constructor(options) {
this.container = createElement({ ...options, component: this });
}
hide() {
hideElement(this.container);
}
show() {
showElement(this.container);
}
highlight() {
this.container.classList.add('highlighted');
}
normal() {
this.container.classList.remove('highlighted');
}
}
================================================
FILE: clients/shared/components/toggle.js
================================================
import Component from "../component";
export default class Toggle extends Component {
constructor(offName, onName, callback, options) {
super({ ...options, tagName: 'button', textContent: offName, onclick: () => this.toggle() });
this.offName = offName;
this.onName = onName;
this.callback = callback;
this.clicked = false;
}
toggle() {
this.clicked = !this.clicked;
if (this.clicked) {
this.container.textContent = this.onName;
} else {
this.container.textContent = this.offName;
}
if (this.callback) {
this.callback(this);
}
}
}
================================================
FILE: clients/shared/domutils.js
================================================
export function createElement(options) {
let tagName = 'div';
if (options && options.tagName) {
tagName = options.tagName;
}
let element = document.createElement(tagName);
if (options) {
if (options.style) {
element.style = options.style;
}
if (options.className) {
element.className = options.className;
}
if (options.textContent) {
element.textContent = options.textContent;
}
if (options.placeholder) {
element.placeholder = options.placeholder;
}
if (options.readonly) {
element.readonly = true;
}
if (options.href) {
element.href = options.href;
}
if (options.target) {
element.target = options.target;
}
if (options.title) {
element.title = options.title;
}
if (options.onclick) {
element.addEventListener('click', (e) => options.onclick(e, options.component));
}
if (options.onchange) {
element.addEventListener('change', (e) => options.onchange(e, options.component));
}
if (options.oninput) {
element.addEventListener('input', (e) => options.oninput(e, options.component));
}
if (options.container) {
options.container.appendChild(element);
}
}
return element;
}
export function hideElement(element) {
element.classList.add('hidden');
}
export function showElement(element) {
element.classList.remove('hidden');
}
export function scrollToBottom(element) {
element.scrollTop = element.scrollHeight;
}
export function scrolledToBottom(element) {
return element.scrollHeight - element.clientHeight === element.scrollTop;
}
export function addTextToRow(row, text) {
let cell = row.insertCell();
cell.appendChild(document.createTextNode(text));
return cell;
}
export function addElementToRow(row, element) {
let cell = row.insertCell();
cell.appendChild(element);
return cell;
}
export function clearSelect(element) {
for (let l = element.options.length - 1, i = l; i >= 0; i--) {
element.remove(i);
}
}
================================================
FILE: clients/shared/localorhive.js
================================================
import urlWithParams from '../../src/common/urlwithparams';
export default function localOrHive(src, params) {
src = src.toLowerCase();
if (window.location.hostname === '127.0.0.1') {
return urlWithParams(`${window.location.origin}/assets?path=${src}`, params);
} else {
// if (params && (params.reforged || params.sc2)) {
return `https://www.hiveworkshop.com/casc-contents?path=${src}`;
// } else {
//return `https://www.hiveworkshop.com/data/static_assets/mpq/tft/${src}`;
// }
}
}
================================================
FILE: clients/shared/utils.js
================================================
// Returns a promise that will resolve in the next VM event loop step.
// Used to force the VM to wait, allowing the DOM to update between heavy operations.
export function aFrame() {
return new Promise((resolve) => {
setTimeout(() => resolve(), 0);
});
}
export async function getAllFileEntries(dataTransfer) {
const items = dataTransfer.items;
let files = [];
let queue = [];
for (let i = 0; i < items.length; i++) {
queue.push(items[i].webkitGetAsEntry());
}
while (queue.length > 0) {
let entry = queue.shift();
if (entry.isFile) {
files.push(entry);
} else if (entry.isDirectory) {
queue.push(...await readAllDirectoryEntries(entry.createReader()));
}
}
return files;
}
async function readAllDirectoryEntries(directoryReader) {
let entries = [];
let readEntries = await readEntriesPromise(directoryReader);
while (readEntries.length > 0) {
entries.push(...readEntries);
readEntries = await readEntriesPromise(directoryReader);
}
return entries;
}
async function readEntriesPromise(directoryReader) {
try {
return await new Promise((resolve, reject) => {
directoryReader.readEntries(resolve, reject);
});
} catch (err) {
console.log(err);
}
}
export async function readFile(file, asText) {
return new Promise((resolve) => {
let reader = new FileReader();
reader.addEventListener('loadend', (e) => {
resolve(e.target.result);
});
if (asText) {
reader.readAsText(file);
} else {
reader.readAsArrayBuffer(file);
}
});
}
export async function readEntry(entry, asText) {
return new Promise((resolve) => entry.file(async (file) => resolve(await readFile(file, asText))));
}
================================================
FILE: clients/tests/README.md
================================================
The unit tester.
By definition, a test is comprised of an input scene, defined by the resources it needs and the setup script, and the output is the rendered image.
The output image is compared against a previously generated image, using the same setup, which was created when the viewer was deemed to work "correctly".
================================================
FILE: clients/tests/components/unittester.js
================================================
import { version } from '../../../src/version';
import UnitTester from '../unittester';
import Component from '../../shared/component';
import { createElement, showElement, hideElement, addElementToRow, addTextToRow } from '../../shared/domutils';
import { wc3Solver } from '../solvers';
import { mdxTests } from '../tests/mdx';
import { mdxPrimitivesTests } from '../tests/mdxprimitives';
import { m3Tests } from '../tests/m3';
import { baseTests } from '../tests/base';
export default class UnitTesterComponent extends Component {
constructor(parentElement) {
super();
this.mismatchPercentageForFailure = 1;
this.passed = 0;
let unitTester = new UnitTester(wc3Solver);
unitTester.add(mdxTests);
unitTester.add(mdxPrimitivesTests);
unitTester.add(m3Tests);
unitTester.add(baseTests);
this.unitTester = unitTester;
createElement({ tagName: 'b', textContent: `Viewer version ${version}`, container: this.container });
createElement({ tagName: 'hr', container: this.container });
let controls = createElement({ container: this.container });
this.runButton = createElement({ tagName: 'button', textContent: 'Run', onclick: () => this.run(), container: controls });
this.downloadButton = createElement({ tagName: 'button', textContent: 'Download', onclick: () => this.download(), container: controls });
createElement({ tagName: 'hr', container: this.container });
this.resultsContainer = createElement({ className: 'hidden', container: this.container });
this.resultsMeta = createElement({ container: this.resultsContainer });
let resultsTable = createElement({ tagName: 'table', container: this.resultsContainer });
this.tbody = resultsTable.createTBody();
let thead = resultsTable.createTHead();
let header = thead.insertRow();
addElementToRow(header, createElement({ className: 'bold', textContent: 'Name' }));
this.headerResult = addElementToRow(header, createElement({ className: 'bold', textContent: 'Result' }));
this.headerNew = addElementToRow(header, createElement({ className: 'bold', textContent: 'New' }));
this.headerOld = addElementToRow(header, createElement({ className: 'bold', textContent: 'Old' }));
parentElement.appendChild(this.container);
}
clear() {
let section = this.tbody;
for (let l = section.rows.length - 1, i = l; i >= 0; i--) {
section.deleteRow(i);
}
}
result(result) {
let row = this.tbody.insertRow();
addTextToRow(row, result.name);
if (result.mismatchPercentage !== undefined) {
let passed = result.mismatchPercentage < this.mismatchPercentageForFailure;
if (passed) {
this.passed += 1;
}
let total = this.unitTester.tests.length;
let ran = this.tbody.rows.length;
let className = 'passed';
if (this.passed < ran) {
className = 'failed';
}
this.resultsMeta.className = className;
this.resultsMeta.textContent = `${this.passed} / ${ran} (${total} total)`;
let name = passed ? 'passed' : 'failed';
addElementToRow(row, createElement({ className: name, textContent: name }))
if (result.testImage) {
let wrapper = createElement({ tagName: 'a', className: 'center', href: result.testImage.src, target: '_blank' });
wrapper.appendChild(result.testImage);
addElementToRow(row, wrapper);
} else {
addTextToRow(row, '');
}
if (result.comparisonImage) {
let wrapper = createElement({ tagName: 'a', className: 'center', href: result.comparisonImage.src, target: '_blank' });
wrapper.appendChild(result.comparisonImage);
addElementToRow(row, wrapper);
} else {
addTextToRow(row, '');
}
}
}
run() {
this.passed = 0;
this.runButton.disabled = true;
this.downloadButton.disabled = true;
this.clear();
// In case they were hidden.
showElement(this.headerResult);
showElement(this.headerNew);
showElement(this.headerOld);
// In case it was hidden.
showElement(this.resultsContainer);
this.unitTester.test((entry) => {
if (!entry.done) {
let result = entry.value;
if (result.result < 1) {
this.passed++;
}
this.result(result);
} else {
this.runButton.disabled = false;
this.downloadButton.disabled = false;
}
});
}
download() {
this.passed = 0;
this.runButton.disabled = true;
this.downloadButton.disabled = true;
this.clear();
// In case they were shown.
hideElement(this.headerResult);
hideElement(this.headerNew);
hideElement(this.headerOld);
// In case it was hidden.
showElement(this.resultsContainer);
let zip = new JSZip();
this.unitTester.download((entry) => {
if (!entry.done) {
let result = entry.value;
this.result(result);
if (result.blob) {
this.passed++;
zip.file(`${result.name}.png`, result.blob);
} else {
console.log(`Skipping ${result.name} because it has no blob`);
}
} else {
this.runButton.disabled = false;
this.downloadButton.disabled = false;
zip.generateAsync({ type: 'blob' })
.then((blob) => {
saveAs(blob, `compare_${version}.zip`);
});
}
});
}
}
================================================
FILE: clients/tests/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Unit Tests</title>
<meta charset="utf-8" />
<style>
button {
margin-left: 2px;
margin-right: 2px;
}
td {
padding-left: 4px;
padding-right: 4px;
}
.center {
display: flex;
justify-content: center;
align-items: center;
}
img {
width: 20px;
height: 20px;
}
.bold {
font-weight: bold;
}
.passed {
color: green;
}
.failed {
color: red;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<script src="../thirdparty/jszip.min.js"></script>
<script src="../thirdparty/filesaver.js"></script>
<script src="/clients/tests.min.js"></script>
</body>
</html>
================================================
FILE: clients/tests/index.js
================================================
import UnitTester from './components/unittester';
const tester = new UnitTester(document.body);
// For debugging etc.
window.tester = tester;
================================================
FILE: clients/tests/solvers.js
================================================
import localOrHive from "../shared/localorhive";
export const wc3Solver = (path, params) => {
path = localOrHive(path, params);
// GREAT JOB BLIZZARD. AWESOME PATCHES.
if (path.endsWith('orcbloodriderlesswyvernrider.mdx') && path.includes('hiveworkshop')) {
path = path.replace('orcbloodriderlesswyvernrider.mdx', 'ordbloodriderlesswyvernrider.mdx');
}
return path;
};
export const sc2Solver = localOrHive;
================================================
FILE: clients/tests/tests/base.js
================================================
import { wc3Solver, sc2Solver } from "../solvers";
export const baseTests = {
name: 'base',
tests: [
{
name: 'attachments',
load(viewer) {
return [
viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver),
viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver),
];
},
test(viewer, scene, camera, models) {
let mountainKing = models[0];
let baneling = models[1];
camera.moveToAndFace([450, 0, 160], [0, 0, 160], [0, 0, 1]);
let instance1 = mountainKing.addInstance().setSequence(1);
let instance3 = mountainKing.addInstance().setSequence(1);
let instance5 = mountainKing.addInstance().setSequence(1);
let instance2 = baneling.addInstance().setSequence(0).uniformScale(100);
let instance4 = baneling.addInstance().setSequence(0).uniformScale(100);
let instance6 = baneling.addInstance().setSequence(0).uniformScale(100);
instance2.setParent(instance1.getAttachment(3));
instance3.setParent(instance2.getAttachment(4));
instance4.setParent(instance3.getAttachment(3));
instance5.setParent(instance4.getAttachment(4));
instance6.setParent(instance5.getAttachment(3));
scene.addInstance(instance1);
scene.addInstance(instance2);
scene.addInstance(instance3);
scene.addInstance(instance4);
scene.addInstance(instance5);
scene.addInstance(instance6);
},
},
],
};
================================================
FILE: clients/tests/tests/m3.js
================================================
import { sc2Solver } from "../solvers";
export const m3Tests = {
name: 'm3',
tests: [
{
name: 'base',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 100], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50);
scene.addInstance(instance);
},
},
{
name: 'sequence',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 100], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50).setSequence(0);
instance.frame = 800;
scene.addInstance(instance);
},
},
{
name: 'team-color',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 100], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50).setTeamColor(1);
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 100], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50).setVertexColor([1, 0, 0, 1]);
scene.addInstance(instance);
},
},
{
name: 'vertex-and-team-colors',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 100], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50).setVertexColor([1, 0, 0, 1]).setTeamColor(1);
scene.addInstance(instance);
},
},
{
name: 'texture-overriding',
load(viewer) {
return viewer.load('Assets/Units/Zerg/Baneling/Baneling.m3', sc2Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 5, 140], [0, 5, 0], [0, 1, 0]);
let instance = model.addInstance().uniformScale(50).move([25, 0, 0]);
let instance2 = model.addInstance().uniformScale(50).move([-25, 0, 0]);
let material = model.materials[1][0];
instance.setTexture(0, 0, material.layers[10].texture.texture);
scene.addInstance(instance);
scene.addInstance(instance2);
},
},
],
};
================================================
FILE: clients/tests/tests/mdx.js
================================================
import { quat } from "gl-matrix";
import { wc3Solver } from "../solvers";
export const mdxTests = {
name: 'mdx',
tests: [
{
name: 'base',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
{
name: 'sequence',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance().setSequence(0);
instance.frame = 800;
scene.addInstance(instance);
},
},
{
name: 'team-color',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance().setTeamColor(1);
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance().setVertexColor([1, 0, 0, 1]);
scene.addInstance(instance);
},
},
{
name: 'vertex-and-team-colors',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance().setVertexColor([1, 0, 0, 1]).setTeamColor(1);
scene.addInstance(instance);
},
},
{
name: 'texture-animation',
tests: [
{
name: 'translation-and-slot',
load(viewer) {
return viewer.load('Units/Human/WaterElemental/WaterElemental.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([200, 0, 85], [0, 0, 85], [0, 0, 1]);
let instance = model.addInstance().setSequence(0);
instance.frame = 800;
scene.addInstance(instance);
},
},
{
name: 'rotation',
load(viewer) {
return viewer.load('UI/Feedback/Cooldown/UI-Cooldown-Indicator.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([40, 40, 100], [40, 40, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(0).uniformScale(2100).setSequenceLoopMode(2);
instance.frame = 600;
scene.addInstance(instance);
},
},
{
name: 'scale',
load(viewer) {
return viewer.load('Abilities/Spells/Other/Volcano/Volcano.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([400, 0, 50], [0, 0, 50], [0, 0, 1]);
let instance = model.addInstance().setSequence(1);
scene.addInstance(instance);
},
},
],
},
{
name: 'billboarding',
tests: [
{
name: 'standard',
load(viewer) {
return viewer.load('Units/Creeps/Gnoll/Gnoll.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([120, -50, 75], [0, 0, 40], [0, 0, 1]);
let instance = model.addInstance().setSequence(1).setSequenceLoopMode(2);
// Rotate also the instance, to be sure billboarding works in all cases.
// It happened in a past implementation that billboaring worked as long as the instance isn't rotated.
// Needless to say, it took a long time to find that bug.
instance.rotate(quat.setAxisAngle([], [0, 1, 0], -0.785398));
instance.frame = 800;
scene.addInstance(instance);
viewer.update();
},
},
{
name: 'x-axis',
load(viewer) {
return viewer.load('SharedModels/NEBirth.MDX', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([200, -200, 400], [0, 0, 300], [0, 0, 1]);
let instance = model.addInstance().setSequence(0).rotate(quat.setAxisAngle([], [0, 0, 1], -0.785398));
instance.frame += 30000;
scene.addInstance(instance);
},
},
],
},
{
name: 'attachment-model',
load(viewer) {
return viewer.load('Buildings/Undead/HauntedMine/HauntedMine.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 0, 620], [0, 0, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(0);
scene.addInstance(instance);
instance.frame = 20000;
// update() is used here, because when an attachment becomes visible for the first time, the parent instance resets its sequence.
// If the attachment's frame was set without first updating, it will just get reset to the sequence's beginning.
viewer.update();
let attachment = instance.attachments[0].internalInstance;
attachment.frame = instance.frame;
},
},
{
name: 'particle-emitter',
load(viewer) {
return viewer.load('Units/Creeps/AzureDragon/AzureDragon.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([50, -35, 250], [50, -35, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(5);
scene.addInstance(instance);
for (let i = 0; i < 30; i++) {
viewer.update();
}
},
},
{
name: 'particle-2-emitter',
tests: [
{
name: 'base',
load(viewer) {
return viewer.load('Units/Creeps/AzureDragon/AzureDragon.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([300, 0, -20], [0, 0, -20], [0, 0, 1]);
let instance = model.addInstance().setSequence(1);
scene.addInstance(instance);
for (let i = 0; i < 90; i++) {
viewer.update();
}
},
},
{
name: 'squirt',
load(viewer) {
return viewer.load('Abilities/Spells/Human/Thunderclap/ThunderclapCaster.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 0, 250], [0, 0, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(1);
scene.addInstance(instance);
for (let i = 0; i < 4; i++) {
viewer.update();
}
},
},
{
name: 'line-emitter',
load(viewer) {
return viewer.load('Abilities/Spells/Human/Thunderclap/ThunderclapCaster.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([200, 0, 50], [0, 0, 50], [0, 0, 1]);
let instance = model.addInstance().setSequence(1);
scene.addInstance(instance);
for (let i = 0; i < 4; i++) {
viewer.update();
}
},
},
{
name: 'tail',
load(viewer) {
return viewer.load('Doodads/Dungeon/Props/ForceWall/ForceWall.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([700, 0, 100], [0, 0, 100], [0, 0, 1]);
let instance = model.addInstance().setSequence(0).setSequenceLoopMode(2);
scene.addInstance(instance);
for (let i = 0; i < 100; i++) {
viewer.update();
}
},
},
{
name: 'repeat',
load(viewer) {
return viewer.load('Doodads/Cinematic/EnergyField/EnergyField.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 600, 100], [0, 0, 50], [0, 0, 1]);
let instance = model.addInstance().setSequence(0).setSequenceLoopMode(2);
scene.addInstance(instance);
for (let i = 0; i < 50; i++) {
viewer.update();
}
},
},
{
name: 'xy-quad',
load(viewer) {
return viewer.load('Units/Orc/SpiritWyvern/SpiritWyvern.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 300, 100], [0, 0, 50], [0, 0, 1]);
let instance = model.addInstance().setSequence(9).setSequenceLoopMode(2);
scene.addInstance(instance);
for (let i = 0; i < 50; i++) {
viewer.update();
}
},
},
],
},
{
name: 'ribbon-emitter',
load(viewer) {
return viewer.load('Units/Human/HeroPaladin/HeroPaladin.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([225, -45, 70], [0, 0, 70], [0, 0, 1]);
let instance = model.addInstance().setSequence(4).setSequenceLoopMode(2);
scene.addInstance(instance);
for (let i = 0; i < 24; i++) {
viewer.update();
}
},
},
{
name: 'event-object',
tests: [
{
name: 'spn',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([-40, 0, 100], [-40, 0, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(9);
scene.addInstance(instance);
for (let i = 0; i < 50; i++) {
viewer.update();
}
},
},
{
name: 'spl',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 0, 80], [0, 0, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(9);
scene.addInstance(instance);
for (let i = 0; i < 170; i++) {
viewer.update();
}
},
},
{
name: 'ubr',
load(viewer) {
return viewer.load('Abilities/Spells/Human/Thunderclap/ThunderclapCaster.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([0, 0, 500], [0, 0, 0], [0, 1, 0]);
let instance = model.addInstance().setSequence(1);
scene.addInstance(instance);
for (let i = 0; i < 20; i++) {
viewer.update();
}
},
},
],
},
{
name: 'texture-overriding',
load(viewer) {
return viewer.load('Units/Human/Footman/Footman.mdx', wc3Solver);
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([220, 0, 45], [0, 0, 45], [0, 0, 1]);
let instance = model.addInstance().move([0, 40, 0]);
let instance2 = model.addInstance().move([0, -40, 0]);
instance.setTexture(0, model.textures[2].texture);
scene.addInstance(instance);
scene.addInstance(instance2);
},
},
],
};
================================================
FILE: clients/tests/tests/mdxprimitives.js
================================================
import { quat } from "gl-matrix";
import createPrimitive from "../../../src/utils/mdlx/primitives/createprimitive";
import { createUnitRectangle, createUnitCube, createUnitSphere, createUnitCylinder, createFrustum } from "../../../src/utils/mdlx/primitives/primitives";
export const mdxPrimitivesTests = {
name: 'mdx-primitives',
tests: [
{
name: 'rectangle',
tests: [
{
name: 'faces',
load(viewer) {
return createPrimitive(viewer, createUnitRectangle());
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edges',
load(viewer) {
return createPrimitive(viewer, createUnitRectangle(), { lines: true });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return createPrimitive(viewer, createUnitRectangle(), { color: new Float32Array([1, 0, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edge-color',
load(viewer) {
return createPrimitive(viewer, createUnitRectangle(), { lines: true, color: new Float32Array([0, 1, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'texture',
load(viewer) {
let texture = viewer.load('resources/checkers.jpg');
return createPrimitive(viewer, createUnitRectangle(), { texture });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
],
},
{
name: 'cube',
tests: [
{
name: 'faces',
load(viewer) {
return createPrimitive(viewer, createUnitCube());
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 160]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edges',
load(viewer) {
return createPrimitive(viewer, createUnitCube(), { lines: true });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 160]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return createPrimitive(viewer, createUnitCube(), { color: new Float32Array([1, 0, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 160]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edge-color',
load(viewer) {
return createPrimitive(viewer, createUnitCube(), { lines: true, color: new Float32Array([0, 1, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 160]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'texture',
load(viewer) {
let texture = viewer.load('resources/checkers.jpg');
return createPrimitive(viewer, createUnitCube(), { texture });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 160]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
],
},
{
name: 'sphere',
tests: [
{
name: 'faces',
load(viewer) {
return createPrimitive(viewer, createUnitSphere(20, 20));
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edges',
load(viewer) {
return createPrimitive(viewer, createUnitSphere(20, 20), { lines: true });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return createPrimitive(viewer, createUnitSphere(20, 20), { color: new Float32Array([1, 0, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edge-color',
load(viewer) {
return createPrimitive(viewer, createUnitSphere(20, 20), { lines: true, color: new Float32Array([0, 1, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'texture',
load(viewer) {
let texture = viewer.load('resources/checkers.jpg');
return createPrimitive(viewer, createUnitSphere(20, 20), { texture });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 120]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
],
},
{
name: 'cylinder',
tests: [
{
name: 'faces',
load(viewer) {
return createPrimitive(viewer, createUnitCylinder(20));
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 150]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edges',
load(viewer) {
return createPrimitive(viewer, createUnitCylinder(20), { lines: true });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 150]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return createPrimitive(viewer, createUnitCylinder(20), { color: new Float32Array([1, 0, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 150]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'edge-color',
load(viewer) {
return createPrimitive(viewer, createUnitCylinder(20), { lines: true, color: new Float32Array([0, 1, 0]) });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 150]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
{
name: 'texture',
load(viewer) {
let texture = viewer.load('resources/checkers.jpg');
return createPrimitive(viewer, createUnitCylinder(), { texture });
},
test(viewer, scene, camera, model) {
camera.move([0, 0, 150]);
let instance = model.addInstance().uniformScale(40).rotate(quat.setAxisAngle([], [1, 0, 0], Math.PI / 8));
scene.addInstance(instance);
},
},
],
},
{
name: 'frustum',
tests: [
{
name: 'faces',
load(viewer) {
return createPrimitive(viewer, createFrustum(Math.PI / 4, 0.75, 8, 120));
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 200], [0, 0, 60], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
{
name: 'edges',
load(viewer) {
return createPrimitive(viewer, createFrustum(Math.PI / 4, 0.75, 8, 120), { lines: true });
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 200], [0, 0, 60], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
{
name: 'vertex-color',
load(viewer) {
return createPrimitive(viewer, createFrustum(Math.PI / 4, 0.75, 8, 120), { color: new Float32Array([1, 0, 0]) });
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 200], [0, 0, 60], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
{
name: 'edge-color',
load(viewer) {
return createPrimitive(viewer, createFrustum(Math.PI / 4, 0.75, 8, 120), { lines: true, color: new Float32Array([0, 1, 0]) });
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 200], [0, 0, 60], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
{
name: 'texture',
load(viewer) {
let texture = viewer.load('resources/checkers.jpg');
return createPrimitive(viewer, createFrustum(Math.PI / 4, 0.75, 8, 120), { texture });
},
test(viewer, scene, camera, model) {
camera.moveToAndFace([150, 0, 200], [0, 0, 60], [0, 0, 1]);
let instance = model.addInstance();
scene.addInstance(instance);
},
},
],
},
],
};
================================================
FILE: clients/tests/unittester.js
================================================
import * as resemble from '../thirdparty/resemble';
import seededRandom from '../../src/common/seededrandom';
import { blobToImage } from '../../src/common/canvas';
import ModelViewer from '../../src/viewer/viewer';
import mdxHandler from '../../src/viewer/handlers/mdx/handler';
import blpHandler from '../../src/viewer/handlers/blp/handler';
import ddsHandler from '../../src/viewer/handlers/dds/handler';
import tgaHandler from '../../src/viewer/handlers/tga/handler';
import m3Handler from '../../src/viewer/handlers/m3/handler';
/**
* A unit tester designed for the model viewer.
* The input of each test is a pre-defined scene, and the output is the rendered image.
* The image is then compared to another image generated from the same test, at a time when rendering it was considered "correct".
*/
export default class UnitTester {
constructor(wc3PathSolver) {
let canvas = document.createElement('canvas');
canvas.width = canvas.height = 256;
let viewer = new ModelViewer(canvas, { alpha: false, antialias: false });
viewer.gl.clearColor(0.05, 0.05, 0.05, 1);
viewer.on('error', (e) => console.log(e));
viewer.addHandler(mdxHandler, wc3PathSolver);
viewer.addHandler(blpHandler);
viewer.addHandler(ddsHandler);
viewer.addHandler(tgaHandler);
viewer.addHandler(m3Handler);
this.viewer = viewer;
this.mathRandom = Math.random;
this.tests = [];
}
/**
* Add a test or a hierarchy of tests.
*/
add(test) {
if (test.tests) {
this.addBaseName(test.tests, test.name);
} else {
this.tests.push({ name: test.name, test });
}
}
/**
* Run all of the tests that were added.
* The callback will be called with the result of each one.
* The results look like iterators: {done: true/false, value: undefine/result }.
*/
async test(callback) {
for (let test of this.tests) {
let testBlob = await this.getTestBlob(test);
let comparisonBlob = await this.getComparisonBlob(test);
if (testBlob && comparisonBlob) {
let comparisonResult = await new Promise((resolve) => resemble(testBlob).compareTo(comparisonBlob).ignoreColors().onComplete((data) => resolve(data)));
let testImage = await blobToImage(testBlob);
let comparisonImage = await blobToImage(comparisonBlob);
callback({ done: false, value: { name: test.name, testImage, comparisonImage, mismatchPercentage: comparisonResult.rawMisMatchPercentage } });
} else {
// Fail modes.
// 1) The test blob exists, but comparison doesn't. This happens when adding new tests.
// 2) The comparison blob exists, but the test doesn't. This happens when having issues with fetching the files needed for the tests.
// 3) Neither exists.
if (testBlob) {
callback({ done: false, value: { name: test.name, testImage: await blobToImage(testBlob), mismatchPercentage: 100 } });
} else if (comparisonBlob) {
callback({ done: false, value: { name: test.name, comparisonImage: await blobToImage(comparisonBlob), mismatchPercentage: 100 } });
} else {
callback({ done: false, value: { name: test.name, mismatchPercentage: 100 } });
}
}
}
callback({ done: true });
}
/**
* Run all of the tests that were added, and download them.
* The tests are not compared against anything.
* This is used to update the "correct" results.
*/
async download(callback) {
for (let test of this.tests) {
let name = test.name;
let blob = await this.getTestBlob(test);
if (blob) {
callback({ done: false, value: { name, blob } });
} else {
callback({ done: false, value: { name } });
}
}
callback({ done: true });
}
/**
* Is the given resource or array of resources ok?
*/
isDataAGo(data) {
if (data) {
if (Array.isArray(data)) {
for (let resource of data) {
if (!resource) {
return false;
}
}
}
return true;
}
return false;
}
/**
* Given a test, return a promise that will resolve to the blob that resulted from running the test.
*/
async getTestBlob(test) {
let loadHandler = test.test.load;
let testHandler = test.test.test;
let viewer = this.viewer;
// Clear the viewer
viewer.clear();
let scene = viewer.addScene();
scene.color.fill(0.05);
// Start loading the test.
let data = loadHandler(viewer);
// Wait until everything loaded.
await viewer.whenAllLoaded();
if (Array.isArray(data)) {
data = await Promise.all(data);
} else {
data = await data;
}
if (this.isDataAGo(data)) {
// Replace Math.random with a custom seeded random generator.
// This allows to run the viewer in a deterministic environment for tests.
// For example, particles have some randomized data, which can make tests mismatch.
Math.random = seededRandom(6);
// Run the test.
testHandler(viewer, scene, scene.camera, data);
// Update and render.
viewer.updateAndRender();
// Put back Math.random in its place.
Math.random = this.mathRandom;
// Return the viewer's canvas' blob.
return await viewer.toBlob();
}
}
/**
* Given a test, return a promise that will resolve to the comparison image of this test.
*/
async getComparisonBlob(test) {
let response = await fetch(`compare/${test.name}.png`);
if (response.ok) {
return await response.blob();
}
}
/**
* Adds tests from an hierarchy while appending their names.
* Called automatically by add() if needed.
*/
addBaseName(tests, baseName) {
for (let test of tests) {
if (test.tests) {
this.addBaseName(test.tests, baseName + '-' + test.name);
} else {
this.tests.push({ name: baseName + '-' + test.name, test });
}
}
}
}
================================================
FILE: clients/textureatlas/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>KEKW</title>
<meta charset="utf-8" />
<style>
.row {
display: flex;
flex-direction: row;
gap: 5px;
}
.column {
display: flex;
flex-direction: column;
gap: 5px;
}
.padding5 {
padding: 5px;
}
.border {
border: 1px solid black;
box-sizing: border-box;
}
.bold {
font-weight: bold;
}
#input_canvas {
width: 256px;
height: 256px;
}
#work_canvas {
width: 100px;
height: 100px;
}
#output_canvas {
width: 256px;
height: 256px;
}
</style>
</head>
<body>
<div class="row">
<div class="column">
<div class="row">
<div class="border padding5">
<canvas id="input_canvas"></canvas>
</div>
<div class="column">
<div class="column border padding5">
<div class="bold">Input</div>
<div class="row">
Width:
<div id="input_width"></div>
</div>
<div class="row">
Height:
<div id="input_height"></div>
</div>
</div>
<div class="column border padding5">
<div class="bold">Output</div>
<div class="row">
Width
<input id="output_width" type="number" value="256" />
</div>
<div class="row">
Height
<input id="output_height" type="number" value="256" />
</div>
<div class="row">
Columns
<input id="output_columns" type="number" value="8" />
</div>
<div class="row">
Rows
<input id="output_rows" type="number" value="8" />
</div>
<div class="row">
Revolutions
<input id="output_revolutions" type="number" value="1" />
</div>
<div class="row">
Cell Width:
<div id="output_cell_width">32px</div>
</div>
<div class="row">
Cell Height:
<div id="output_cell_height">32px</div>
</div>
</div>
</div>
</div>
<div class="row border padding5">
<div id="status"></div>
</div>
</div>
<div class="border padding5">
<canvas id="work_canvas"></canvas>
</div>
<div class="border padding5">
<canvas id="output_canvas"></canvas>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
================================================
FILE: clients/textureatlas/index.js
================================================
class TextureAtlasGenerator {
constructor() {
this.inputWidthElement = document.getElementById('input_width');
this.inputHeightElement = document.getElementById('input_height');
this.outputCellWidthElement = document.getElementById('output_cell_width');
this.outputCellHeightElement = document.getElementById('output_cell_height');
this.statusElement = document.getElementById('status');
this.inputCanvas = document.getElementById('input_canvas');
this.workCanvas = document.getElementById('work_canvas');
this.outputCanvas = document.getElementById('output_canvas');
this.inputCtx = this.inputCanvas.getContext('2d');
this.workCtx = this.workCanvas.getContext('2d');
this.outputCtx = this.outputCanvas.getContext('2d');
this.image = null;
this.inputWidth = 0;
this.inputHeight = 0;
this.width = 256;
this.height = 256;
this.columns = 8;
this.rows = 8;
this.revolutions = 1;
this.cellWidth = 32;
this.cellHeight = 32;
document.getElementById('output_width').addEventListener('change', (e) => this.setWidth(e.target.value));
document.getElementById('output_height').addEventListener('change', (e) => this.setHeight(e.target.value));
document.getElementById('output_columns').addEventListener('change', (e) => this.setColumns(e.target.value));
document.getElementById('output_rows').addEventListener('change', (e) => this.setRows(e.target.value));
document.getElementById('output_revolutions').addEventListener('change', (e) => this.setRevolutions(e.target.value));
document.addEventListener('dragover', e => {
e.preventDefault();
});
document.addEventListener('dragend', e => {
e.preventDefault();
});
document.addEventListener('drop', e => {
e.preventDefault();
let file = e.dataTransfer.files[0];
let reader = new FileReader();
reader.addEventListener('loadend', (e) => {
let image = new Image();
image.onload = (e) => this.setImage(image);
image.onerror = (e) => this.error('Failed to load the file');
image.src = e.target.result;
});
reader.readAsDataURL(file);
});
this.status('Drag & drop an image anywhere on the page');
}
status(status) {
this.statusElement.textContent = status;
}
error(status) {
const { workCtx, workCanvas, outputCtx, outputCanvas } = this;
workCtx.clearRect(0, 0, workCanvas.width, workCanvas.height);
outputCtx.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
this.status(status);
}
setImage(image) {
const { inputCanvas, inputCtx, inputWidthElement, inputHeightElement } = this;
this.image = image;
inputCanvas.width = image.width;
inputCanvas.height = image.height;
inputCtx.drawImage(image, 0, 0);
inputWidthElement.textContent = `${image.width}px`;
inputHeightElement.textContent = `${image.height}px`;
this.update();
}
setWidth(width) {
this.width = width;
this.update();
}
setHeight(height) {
this.height = height;
this.update();
}
setColumns(columns) {
this.columns = columns;
this.update();
}
setRows(rows) {
this.rows = rows;
this.update();
}
setRevolutions(revolutions) {
this.revolutions = revolutions;
this.update();
}
update() {
const { image, width, height, columns, rows, revolutions } = this;
if (!image) {
this.error('Upload an image');
return;
}
if (width < 1 || height < 1 || columns < 1 || rows < 1) {
this.error('No negative values');
return;
}
this.cellWidth = width / columns;
this.cellHeight = height / rows;
const { outputCellWidthElement, outputCellHeightElement, cellWidth, cellHeight } = this;
outputCellWidthElement.textContent = `${cellWidth}px`;
outputCellHeightElement.textContent = `${cellHeight}px`;
if (cellWidth !== (cellWidth | 0) || cellHeight !== (cellHeight | 0)) {
this.error('No fractional cell sizes');
return;
}
const { workCanvas, outputCanvas, workCtx, outputCtx } = this;
const step = (revolutions * Math.PI * 2) / (columns * rows);
workCanvas.width = cellWidth;
workCanvas.height = cellHeight;
outputCanvas.width = width;
outputCanvas.height = height;
let angle = 0;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < columns; x++) {
workCtx.clearRect(0, 0, cellWidth, cellHeight);
workCtx.save();
workCtx.translate(cellWidth / 2, cellHeight / 2);
workCtx.rotate(angle);
workCtx.translate(-cellWidth / 2, -cellHeight / 2);
workCtx.drawImage(image, 0, 0, cellWidth, cellHeight);
workCtx.restore();
outputCtx.drawImage(workCanvas, x * cellWidth, y * cellHeight);
angle += step;
}
}
this.status('Right click on the texture atlas to download it, or adjust values and regenerate it');
}
}
new TextureAtlasGenerator();
================================================
FILE: clients/thirdparty/filesaver.js
================================================
/* FileSaver.js
* A saveAs() & saveTextAs() FileSaver implementation.
* 2014-06-24
*
* Modify by Brian Chen
* Author: Eli Grey, http://eligrey.com
* License: X11/MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs
// IE 10+ (native saveAs)
|| (typeof navigator !== "undefined" &&
navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
// Everyone else
|| (function (view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof navigator !== "undefined" &&
/MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet
, get_URL = function () {
return view.URL || view.webkitURL || view;
}
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = !view.externalHost && "download" in save_link
, click = function (node) {
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, false, view, 0, 0, 0, 0, 0
, false, false, false, false, 0, null
);
node.dispatchEvent(event);
}
, webkit_req_fs = view.webkitRequestFileSystem
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
, throw_outside = function (ex) {
(view.setImmediate || view.setTimeout)(function () {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
, fs_min_size = 0
, deletion_queue = []
, process_deletion_queue = function () {
var i = deletion_queue.length;
while (i--) {
var file = deletion_queue[i];
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
}
deletion_queue.length = 0; // clear queue
}
, dispatch = function (filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, FileSaver = function (blob, name) {
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, blob_changed = false
, object_url
, target_view
, get_object_url = function () {
var object_url = get_URL().createObjectURL(blob);
deletion_queue.push(object_url);
return object_url;
}
, dispatch_all = function () {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function () {
// don't create more object URLs than needed
if (blob_changed || !object_url) {
object_url = get_object_url(blob);
}
if (target_view) {
target_view.location.href = object_url;
} else {
window.open(object_url, "_blank");
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
}
, abortable = function (func) {
return function () {
if (filesaver.readyState !== filesaver.DONE) {
return func.apply(this, arguments);
}
};
}
, create_if_not_found = { create: true, exclusive: false }
, slice
;
filesaver.readyState = filesaver.INIT;
if (!name) {
name = "download";
}
if (can_use_save_link) {
object_url = get_object_url(blob);
save_link.href = object_url;
save_link.download = name;
click(save_link);
filesaver.readyState = filesaver.DONE;
dispatch_all();
return;
}
// Object and web filesystem URLs have a problem saving in Google Chrome when
// viewed in a tab, so I force save with application/octet-stream
// http://code.google.com/p/chromium/issues/detail?id=91158
if (view.chrome && type && type !== force_saveable_type) {
slice = blob.slice || blob.webkitSlice;
blob = slice.call(blob, 0, blob.size, force_saveable_type);
blob_changed = true;
}
// Since I can't be sure that the guessed media type will trigger a download
// in WebKit, I append .download to the filename.
// https://bugs.webkit.org/show_bug.cgi?id=65440
if (webkit_req_fs && name !== "download") {
name += ".download";
}
if (type === force_saveable_type || webkit_req_fs) {
target_view = view;
}
if (!req_fs) {
fs_error();
return;
}
fs_min_size += blob.size;
req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) {
fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) {
var save = function () {
dir.getFile(name, create_if_not_found, abortable(function (file) {
file.createWriter(abortable(function (writer) {
writer.onwriteend = function (event) {
target_view.location.href = file.toURL();
deletion_queue.push(file);
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "writeend", event);
};
writer.onerror = function () {
var error = writer.error;
if (error.code !== error.ABORT_ERR) {
fs_error();
}
};
"writestart progress write abort".split(" ").forEach(function (event) {
writer["on" + event] = filesaver["on" + event];
});
writer.write(blob);
filesaver.abort = function () {
writer.abort();
filesaver.readyState = filesaver.DONE;
};
filesaver.readyState = filesaver.WRITING;
}), fs_error);
}), fs_error);
};
dir.getFile(name, { create: false }, abortable(function (file) {
// delete file if it already exists
file.remove();
save();
}), abortable(function (ex) {
if (ex.code === ex.NOT_FOUND_ERR) {
save();
} else {
fs_error();
}
}));
}), fs_error);
}), fs_error);
}
, FS_proto = FileSaver.prototype
, saveAs = function (blob, name) {
return new FileSaver(blob, name);
}
;
FS_proto.abort = function () {
var filesaver = this;
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "abort");
};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
view.addEventListener("unload", process_deletion_queue, false);
saveAs.unload = function () {
process_deletion_queue();
view.removeEventListener("unload", process_deletion_queue, false);
};
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module !== null) {
module.exports = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
define([], function () {
return saveAs;
});
}
String.prototype.endsWithAny = function () {
var strArray = Array.prototype.slice.call(arguments),
$this = this.toLowerCase().toString();
for (var i = 0; i < strArray.length; i++) {
if ($this.indexOf(strArray[i], $this.length - strArray[i].length) !== -1) return true;
}
return false;
};
var saveTextAs = saveTextAs
|| (function (textContent, fileName, charset) {
fileName = fileName || 'download.txt';
charset = charset || 'utf-8';
textContent = (textContent || '').replace(/\r?\n/g, "\r\n");
if (saveAs && Blob) {
var blob = new Blob([textContent], { type: "text/plain;charset=" + charset });
saveAs(blob, fileName);
return true;
} else {//IE9-
var saveTxtWindow = window.frames.saveTxtWindow;
if (!saveTxtWindow) {
saveTxtWindow = document.createElement('iframe');
saveTxtWindow.id = 'saveTxtWindow';
saveTxtWindow.style.display = 'none';
document.body.insertBefore(saveTxtWindow, null);
saveTxtWindow = window.frames.saveTxtWindow;
if (!saveTxtWindow) {
saveTxtWindow = window.open('', '_temp', 'width=100,height=100');
if (!saveTxtWindow) {
window.alert('Sorry, download file could not be created.');
return false;
}
}
}
var doc = saveTxtWindow.document;
doc.open('text/html', 'replace');
doc.charset = charset;
if (fileName.endsWithAny('.htm', '.html')) {
doc.close();
doc.body.innerHTML = '\r\n' + textContent + '\r\n';
} else {
if (!fileName.endsWithAny('.txt')) fileName += '.txt';
doc.write(textContent);
doc.close();
}
var retValue = doc.execCommand('SaveAs', null, fileName);
saveTxtWindow.close();
return retValue;
}
})
================================================
FILE: clients/thirdparty/resemble.js
================================================
// NOTE: require("canvas-prebuilt") was commented because it makes webpack throw annoying errors, since my code is running in a browser, not nodejs.
/*
James Cryer / Huddle
URL: https://github.com/Huddle/Resemble.js
*/
(function(root, factory) {
"use strict";
if (typeof define === "function" && define.amd) {
define([], factory);
} else if (typeof module === "object" && module.exports) {
module.exports = factory();
} else {
root.resemble = factory();
}
})(this, function() {
"use strict";
var Img;
var Canvas;
if (typeof Image !== "undefined") {
Img = Image;
} else {
// Canvas = require("canvas-prebuilt"); // eslint-disable-line global-require
Img = Canvas.Image;
}
var document =
typeof window !== "undefined"
? window.document
: {
createElement: function() {
// This will work as long as only createElement is used on window.document
return new Canvas();
}
};
var oldGlobalSettings = {};
var globalOutputSettings = oldGlobalSettings;
function setGlobalOutputSettings(settings) {
var msg =
"warning resemble.outputSettings mutates global state, and " +
"will be removed in 3.0.0";
console.warn(msg);
globalOutputSettings = settings;
return this;
}
var resemble = function(fileData) {
var pixelTransparency = 1;
var errorPixelColor = {
// Color for Error Pixels. Between 0 and 255.
red: 255,
green: 0,
blue: 255,
alpha: 255
};
var targetPix = {r: 0, g: 0, b: 0, a: 0}; // isAntialiased
function colorsDistance(c1, c2) {
return (
(Math.abs(c1.r - c2.r) +
Math.abs(c1.g - c2.g) +
Math.abs(c1.b - c2.b)) /
3
);
}
function withinBoundingBox(x, y, width, height, box) {
return (
x > (box.left || 0) &&
x < (box.right || width) &&
y > (box.top || 0) &&
y < (box.bottom || height)
);
}
function withinComparedArea(x, y, width, height) {
var isIncluded = true;
if (
boundingBox !== undefined &&
!withinBoundingBox(x, y, width, height, boundingBox)
) {
isIncluded = false;
}
if (
ignoredBox !== undefined &&
gitextract_a23fu6lt/ ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── Viewer.code-workspace ├── Viewer.sublime-project ├── clean.js ├── clients/ │ ├── README.md │ ├── downgrader/ │ │ ├── index.html │ │ └── index.js │ ├── example/ │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ └── resources/ │ │ ├── SmileyGW_004.mdx │ │ └── Textures/ │ │ └── SmileyGW.blp │ ├── map/ │ │ ├── README.md │ │ ├── index.html │ │ └── index.js │ ├── mdlx/ │ │ ├── index.html │ │ └── index.js │ ├── mdlxoptimizer/ │ │ ├── index.html │ │ └── index.ts │ ├── melee/ │ │ ├── README.md │ │ ├── index.html │ │ └── index.js │ ├── rebuild/ │ │ ├── README.md │ │ ├── components/ │ │ │ └── rebuilder.js │ │ ├── index.html │ │ └── index.js │ ├── recorder/ │ │ ├── README.md │ │ ├── index.html │ │ └── index.js │ ├── sanitytest/ │ │ ├── README.md │ │ ├── components/ │ │ │ ├── logger.js │ │ │ ├── mdlview.js │ │ │ ├── sanitytester.js │ │ │ ├── teamcolors.js │ │ │ ├── testmeta.js │ │ │ ├── testresults.js │ │ │ ├── tooltips.js │ │ │ ├── viewer.js │ │ │ └── viewercontrols.js │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── test.js │ ├── shared/ │ │ ├── camera.js │ │ ├── component.js │ │ ├── components/ │ │ │ └── toggle.js │ │ ├── domutils.js │ │ ├── localorhive.js │ │ └── utils.js │ ├── tests/ │ │ ├── README.md │ │ ├── components/ │ │ │ └── unittester.js │ │ ├── index.html │ │ ├── index.js │ │ ├── solvers.js │ │ ├── tests/ │ │ │ ├── base.js │ │ │ ├── m3.js │ │ │ ├── mdx.js │ │ │ └── mdxprimitives.js │ │ └── unittester.js │ ├── textureatlas/ │ │ ├── index.html │ │ └── index.js │ ├── thirdparty/ │ │ ├── filesaver.js │ │ └── resemble.js │ └── weu/ │ ├── README.md │ ├── TriggerDataCustom.txt │ ├── TriggerDataPTR129.txt │ ├── TriggerDataWEU.txt │ ├── TriggerDataYDWE.txt │ ├── components/ │ │ ├── weuchanges.js │ │ ├── weuconverter.js │ │ └── weumeta.js │ ├── index.css │ ├── index.html │ └── index.js ├── package.json ├── src/ │ ├── common/ │ │ ├── arrayunique.ts │ │ ├── audio.ts │ │ ├── binarystream.ts │ │ ├── bitstream.ts │ │ ├── bytesof.ts │ │ ├── canvas.ts │ │ ├── convertbitrange.ts │ │ ├── dxt.ts │ │ ├── fetchdatatype.ts │ │ ├── gl-matrix-addon.ts │ │ ├── index.ts │ │ ├── isformat.ts │ │ ├── math.ts │ │ ├── path.ts │ │ ├── searches.ts │ │ ├── seededrandom.ts │ │ ├── sstrhash2.ts │ │ ├── stringreverse.ts │ │ ├── typecast.ts │ │ ├── urlwithparams.ts │ │ └── utf8.ts │ ├── index.ts │ ├── parsers/ │ │ ├── blp/ │ │ │ ├── image.ts │ │ │ ├── index.ts │ │ │ ├── isformat.ts │ │ │ └── jpg.js │ │ ├── dds/ │ │ │ ├── image.ts │ │ │ ├── index.ts │ │ │ └── isformat.ts │ │ ├── index.ts │ │ ├── ini/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── m3/ │ │ │ ├── animationreference.ts │ │ │ ├── attachmentpoint.ts │ │ │ ├── batch.ts │ │ │ ├── bone.ts │ │ │ ├── boundingshape.ts │ │ │ ├── boundingsphere.ts │ │ │ ├── camera.ts │ │ │ ├── division.ts │ │ │ ├── event.ts │ │ │ ├── index.ts │ │ │ ├── indexentry.ts │ │ │ ├── isformat.ts │ │ │ ├── layer.ts │ │ │ ├── light.ts │ │ │ ├── materialreference.ts │ │ │ ├── md34.ts │ │ │ ├── model.ts │ │ │ ├── modelheader.ts │ │ │ ├── reference.ts │ │ │ ├── region.ts │ │ │ ├── sd.ts │ │ │ ├── sequence.ts │ │ │ ├── standardmaterial.ts │ │ │ ├── stc.ts │ │ │ ├── stg.ts │ │ │ ├── sts.ts │ │ │ └── unsupportedentry.ts │ │ ├── mdlx/ │ │ │ ├── animatedobject.ts │ │ │ ├── animationmap.ts │ │ │ ├── animations.ts │ │ │ ├── attachment.ts │ │ │ ├── bone.ts │ │ │ ├── camera.ts │ │ │ ├── collisionshape.ts │ │ │ ├── eventobject.ts │ │ │ ├── extent.ts │ │ │ ├── faceeffect.ts │ │ │ ├── genericobject.ts │ │ │ ├── geoset.ts │ │ │ ├── geosetanimation.ts │ │ │ ├── helper.ts │ │ │ ├── index.ts │ │ │ ├── isformat.ts │ │ │ ├── layer.ts │ │ │ ├── light.ts │ │ │ ├── material.ts │ │ │ ├── model.ts │ │ │ ├── particleemitter.ts │ │ │ ├── particleemitter2.ts │ │ │ ├── particleemitterpopcorn.ts │ │ │ ├── ribbonemitter.ts │ │ │ ├── sequence.ts │ │ │ ├── texture.ts │ │ │ ├── textureanimation.ts │ │ │ ├── tokenstream.ts │ │ │ └── unknownchunk.ts │ │ ├── mpq/ │ │ │ ├── adpcm.ts │ │ │ ├── archive.ts │ │ │ ├── block.ts │ │ │ ├── blocktable.ts │ │ │ ├── constants.ts │ │ │ ├── crypto.ts │ │ │ ├── explode.ts │ │ │ ├── file.ts │ │ │ ├── hash.ts │ │ │ ├── hashtable.ts │ │ │ ├── index.ts │ │ │ └── isarchive.ts │ │ ├── slk/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── tga/ │ │ │ ├── image.ts │ │ │ ├── index.ts │ │ │ └── isformat.ts │ │ └── w3x/ │ │ ├── doo/ │ │ │ ├── doodad.ts │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ ├── randomitem.ts │ │ │ ├── randomitemset.ts │ │ │ └── terraindoodad.ts │ │ ├── imp/ │ │ │ ├── file.ts │ │ │ ├── import.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── map.ts │ │ ├── mmp/ │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ └── minimapicon.ts │ │ ├── shd/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── unitsdoo/ │ │ │ ├── droppeditem.ts │ │ │ ├── droppeditemset.ts │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ ├── inventoryitem.ts │ │ │ ├── modifiedability.ts │ │ │ ├── randomunit.ts │ │ │ └── unit.ts │ │ ├── w3c/ │ │ │ ├── camera.ts │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── w3d/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── w3e/ │ │ │ ├── corner.ts │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── w3f/ │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ ├── maporder.ts │ │ │ └── maptitle.ts │ │ ├── w3i/ │ │ │ ├── file.ts │ │ │ ├── force.ts │ │ │ ├── index.ts │ │ │ ├── player.ts │ │ │ ├── randomitem.ts │ │ │ ├── randomitemset.ts │ │ │ ├── randomitemtable.ts │ │ │ ├── randomunit.ts │ │ │ ├── randomunittable.ts │ │ │ ├── techavailabilitychange.ts │ │ │ └── upgradeavailabilitychange.ts │ │ ├── w3o/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── w3r/ │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ └── region.ts │ │ ├── w3s/ │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ └── sound.ts │ │ ├── w3u/ │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ ├── modification.ts │ │ │ ├── modificationtable.ts │ │ │ └── modifiedobject.ts │ │ ├── wct/ │ │ │ ├── customtexttrigger.ts │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── wpm/ │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── wtg/ │ │ │ ├── eca.ts │ │ │ ├── file.ts │ │ │ ├── index.ts │ │ │ ├── parameter.ts │ │ │ ├── subparameters.ts │ │ │ ├── trigger.ts │ │ │ ├── triggercategory.ts │ │ │ ├── triggerdata.ts │ │ │ └── variable.ts │ │ └── wts/ │ │ ├── file.ts │ │ └── index.ts │ ├── utils/ │ │ ├── blp/ │ │ │ ├── index.ts │ │ │ └── sanitytest.ts │ │ ├── dds/ │ │ │ ├── index.ts │ │ │ └── sanitytest.ts │ │ ├── index.ts │ │ ├── jass2/ │ │ │ ├── compilenatives.ts │ │ │ ├── constanthandles.ts │ │ │ ├── context.ts │ │ │ ├── index.ts │ │ │ ├── jass2lua.ts │ │ │ ├── natives.ts │ │ │ ├── thread.ts │ │ │ ├── tokenstream.ts │ │ │ └── types/ │ │ │ ├── agent.ts │ │ │ ├── aidifficulty.ts │ │ │ ├── alliancetype.ts │ │ │ ├── animtype.ts │ │ │ ├── attacktype.ts │ │ │ ├── blendmode.ts │ │ │ ├── camerafield.ts │ │ │ ├── camerasetup.ts │ │ │ ├── damagetype.ts │ │ │ ├── dialogevent.ts │ │ │ ├── effecttype.ts │ │ │ ├── enum.ts │ │ │ ├── eventid.ts │ │ │ ├── fgamestate.ts │ │ │ ├── fogstate.ts │ │ │ ├── force.ts │ │ │ ├── gamedifficulty.ts │ │ │ ├── gameevent.ts │ │ │ ├── gamespeed.ts │ │ │ ├── gamestate.ts │ │ │ ├── gametype.ts │ │ │ ├── group.ts │ │ │ ├── handle.ts │ │ │ ├── hashtable.ts │ │ │ ├── igamestate.ts │ │ │ ├── index.ts │ │ │ ├── itemtype.ts │ │ │ ├── limitop.ts │ │ │ ├── location.ts │ │ │ ├── mapcontrol.ts │ │ │ ├── mapdensity.ts │ │ │ ├── mapflag.ts │ │ │ ├── mapsetting.ts │ │ │ ├── mapvisibility.ts │ │ │ ├── mousebuttontype.ts │ │ │ ├── pathingtype.ts │ │ │ ├── placement.ts │ │ │ ├── player.ts │ │ │ ├── playercolor.ts │ │ │ ├── playerevent.ts │ │ │ ├── playergameresult.ts │ │ │ ├── playerscore.ts │ │ │ ├── playerslotstate.ts │ │ │ ├── playerstate.ts │ │ │ ├── playerunitevent.ts │ │ │ ├── race.ts │ │ │ ├── racepreference.ts │ │ │ ├── raritycontrol.ts │ │ │ ├── rect.ts │ │ │ ├── region.ts │ │ │ ├── soundtype.ts │ │ │ ├── startlocprio.ts │ │ │ ├── subanimtype.ts │ │ │ ├── texmapflags.ts │ │ │ ├── timer.ts │ │ │ ├── trigger.ts │ │ │ ├── unit.ts │ │ │ ├── unitevent.ts │ │ │ ├── unitstate.ts │ │ │ ├── unittype.ts │ │ │ ├── version.ts │ │ │ ├── volumegroup.ts │ │ │ ├── weapontype.ts │ │ │ ├── weathereffect.ts │ │ │ ├── widget.ts │ │ │ └── widgetevent.ts │ │ ├── mappeddata.ts │ │ ├── mdlx/ │ │ │ ├── index.ts │ │ │ ├── mdlstructure.ts │ │ │ ├── primitives/ │ │ │ │ ├── createprimitive.ts │ │ │ │ └── primitives.ts │ │ │ └── sanitytest/ │ │ │ ├── data.ts │ │ │ ├── sanitytest.ts │ │ │ ├── testers.ts │ │ │ ├── tracks.ts │ │ │ └── utils.ts │ │ └── w3x/ │ │ ├── generatelistfile.ts │ │ ├── index.ts │ │ └── weu/ │ │ ├── conversions.ts │ │ ├── data.ts │ │ ├── parsewtg.ts │ │ ├── processing.ts │ │ ├── transformations/ │ │ │ ├── blz.ts │ │ │ ├── functions.ts │ │ │ ├── presets.ts │ │ │ ├── specific.ts │ │ │ └── transformer.ts │ │ ├── utils.ts │ │ └── weu.ts │ ├── version.ts │ └── viewer/ │ ├── bounds.ts │ ├── camera.ts │ ├── cell.ts │ ├── emittedobject.ts │ ├── emittedobjectupdater.ts │ ├── emitter.ts │ ├── genericresource.ts │ ├── gl/ │ │ ├── clientbuffer.ts │ │ ├── clientdatatexture.ts │ │ ├── datatexture.ts │ │ ├── gl.ts │ │ ├── index.ts │ │ └── shader.ts │ ├── grid.ts │ ├── handlerresource.ts │ ├── handlers/ │ │ ├── blp/ │ │ │ ├── handler.ts │ │ │ └── texture.ts │ │ ├── dds/ │ │ │ ├── handler.ts │ │ │ └── texture.ts │ │ ├── index.ts │ │ ├── m3/ │ │ │ ├── attachment.ts │ │ │ ├── batch.ts │ │ │ ├── bone.ts │ │ │ ├── boundingshape.ts │ │ │ ├── camera.ts │ │ │ ├── handler.ts │ │ │ ├── layer.ts │ │ │ ├── model.ts │ │ │ ├── modelinstance.ts │ │ │ ├── node.ts │ │ │ ├── region.ts │ │ │ ├── sd.ts │ │ │ ├── sequence.ts │ │ │ ├── shaders/ │ │ │ │ ├── layers.glsl.ts │ │ │ │ ├── standard.frag.ts │ │ │ │ └── standard.vert.ts │ │ │ ├── skeleton.ts │ │ │ ├── standardmaterial.ts │ │ │ ├── stc.ts │ │ │ ├── stg.ts │ │ │ ├── sts.ts │ │ │ └── texture.ts │ │ ├── mdx/ │ │ │ ├── animatedobject.ts │ │ │ ├── attachment.ts │ │ │ ├── attachmentinstance.ts │ │ │ ├── batch.ts │ │ │ ├── batchgroup.ts │ │ │ ├── bone.ts │ │ │ ├── camera.ts │ │ │ ├── collisionshape.ts │ │ │ ├── emitter.ts │ │ │ ├── emittergroup.ts │ │ │ ├── eventobjectemitter.ts │ │ │ ├── eventobjectemitterobject.ts │ │ │ ├── eventobjectsnd.ts │ │ │ ├── eventobjectsndemitter.ts │ │ │ ├── eventobjectsplemitter.ts │ │ │ ├── eventobjectsplubr.ts │ │ │ ├── eventobjectspn.ts │ │ │ ├── eventobjectspnemitter.ts │ │ │ ├── eventobjectubremitter.ts │ │ │ ├── filtermode.ts │ │ │ ├── genericobject.ts │ │ │ ├── geometryemitterfuncs.ts │ │ │ ├── geoset.ts │ │ │ ├── geosetanimation.ts │ │ │ ├── handler.ts │ │ │ ├── helper.ts │ │ │ ├── layer.ts │ │ │ ├── light.ts │ │ │ ├── material.ts │ │ │ ├── model.ts │ │ │ ├── modelinstance.ts │ │ │ ├── node.ts │ │ │ ├── particle.ts │ │ │ ├── particle2.ts │ │ │ ├── particleemitter.ts │ │ │ ├── particleemitter2.ts │ │ │ ├── particleemitter2object.ts │ │ │ ├── particleemitterobject.ts │ │ │ ├── replaceableids.ts │ │ │ ├── ribbon.ts │ │ │ ├── ribbonemitter.ts │ │ │ ├── ribbonemitterobject.ts │ │ │ ├── sd.ts │ │ │ ├── sequence.ts │ │ │ ├── setupgeosets.ts │ │ │ ├── setupgroups.ts │ │ │ ├── shaders/ │ │ │ │ ├── hd.frag.ts │ │ │ │ ├── hd.vert.ts │ │ │ │ ├── particles.frag.ts │ │ │ │ ├── particles.vert.ts │ │ │ │ ├── sd.frag.ts │ │ │ │ ├── sd.vert.ts │ │ │ │ └── transforms.glsl.ts │ │ │ ├── texture.ts │ │ │ └── textureanimation.ts │ │ ├── shaders/ │ │ │ ├── bonetexture.glsl.ts │ │ │ ├── precision.glsl.ts │ │ │ └── quattransform.glsl.ts │ │ ├── tga/ │ │ │ ├── handler.ts │ │ │ └── texture.ts │ │ └── w3x/ │ │ ├── doodad.ts │ │ ├── map.ts │ │ ├── shaders/ │ │ │ ├── cliffs.frag.ts │ │ │ ├── cliffs.vert.ts │ │ │ ├── ground.frag.ts │ │ │ ├── ground.vert.ts │ │ │ ├── water.frag.ts │ │ │ └── water.vert.ts │ │ ├── standsequence.ts │ │ ├── terraindoodad.ts │ │ ├── terrainmodel.ts │ │ ├── unit.ts │ │ ├── variations.ts │ │ ├── viewer.ts │ │ └── widget.ts │ ├── imagetexture.ts │ ├── index.ts │ ├── model.ts │ ├── modelinstance.ts │ ├── node.ts │ ├── resource.ts │ ├── scene.ts │ ├── skeletalnode.ts │ ├── texture.ts │ └── viewer.ts ├── tsconfig.json ├── types/ │ ├── fengari.d.ts │ └── tga-js.d.ts └── webpack.config.js
Showing preview only (300K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3241 symbols across 383 files)
FILE: clean.js
function deleteFolderRecursive (line 5) | function deleteFolderRecursive(path) {
FILE: clients/example/index.js
function pathSolver (line 41) | function pathSolver(src) {
FILE: clients/map/index.js
function updateStatus (line 16) | function updateStatus() {
FILE: clients/mdlxoptimizer/index.ts
type Value (line 9) | type Value = Uint32Array | Float32Array;
type Entry (line 11) | type Entry = [number, Value, Value, Value];
constant FRAME (line 12) | const FRAME = 0;
constant VALUE (line 13) | const VALUE = 1;
constant INTAN (line 14) | const INTAN = 2;
constant OUTTAN (line 15) | const OUTTAN = 3;
function optimizeAnimation (line 17) | function optimizeAnimation(model: MdlxModel, animation: Animation) {
function optimizeAnimations (line 138) | function optimizeAnimations(model: MdlxModel, animations: Animation[]) {
function optimizeMaterials (line 148) | function optimizeMaterials(model: MdlxModel) {
function optimizeObjects (line 160) | function optimizeObjects(model: MdlxModel, objects: AnimatedObject[]) {
function optimizeModel (line 170) | function optimizeModel(name: string, buffer: ArrayBuffer) {
function optimizeDataTransfer (line 202) | async function optimizeDataTransfer(dataTransfer: DataTransfer) {
FILE: clients/melee/index.js
function onLocalLoaded (line 3) | function onLocalLoaded(e, name) {
function onFileDrop (line 36) | function onFileDrop(e) {
FILE: clients/rebuild/components/rebuilder.js
class Rebuilder (line 12) | class Rebuilder extends Component {
method constructor (line 13) | constructor(parentElement) {
method load (line 25) | async load() {
method clear (line 45) | clear() {
method text (line 49) | text(text) {
method rebuildFile (line 53) | rebuildFile(file) {
FILE: clients/recorder/index.js
function runNextSequence (line 64) | function runNextSequence(e) {
function normalizePath (line 88) | function normalizePath(path) {
function onLocalFileLoaded (line 93) | function onLocalFileLoaded(name, buffer) {
function onFileDrop (line 131) | function onFileDrop(e) {
FILE: clients/sanitytest/components/logger.js
class Logger (line 5) | class Logger extends Component {
method constructor (line 6) | constructor(options) {
method message (line 23) | message(type, message) {
method log (line 41) | log(message) {
method info (line 45) | info(message) {
method error (line 49) | error(message) {
method filter (line 53) | filter() {
class LoggerMessage (line 68) | class LoggerMessage extends Component {
method constructor (line 69) | constructor(type, message) {
method matchFilters (line 75) | matchFilters(logs, info, errors) {
method filter (line 81) | filter(logs, info, errors) {
FILE: clients/sanitytest/components/mdlview.js
class MdlView (line 5) | class MdlView extends Component {
method constructor (line 6) | constructor(parser) {
method showNode (line 22) | showNode(node) {
class MdlViewNode (line 35) | class MdlViewNode extends Component {
method constructor (line 36) | constructor(view, node, parentElement) {
FILE: clients/sanitytest/components/sanitytester.js
class SanityTester (line 12) | class SanityTester extends Component {
method constructor (line 13) | constructor(parentElement) {
method filterTests (line 80) | filterTests() {
method filterResults (line 92) | filterResults() {
method test (line 99) | test(name, buffer, render, pathSolver) {
method render (line 132) | render(test) {
method loadMap (line 147) | loadMap(name, buffer) {
method loadFile (line 198) | async loadFile(file) {
method loadDataTransfer (line 220) | async loadDataTransfer(dataTransfer) {
method loadAPI (line 280) | loadAPI(api) {
FILE: clients/sanitytest/components/teamcolors.js
constant TEAM_COLORS (line 1) | const TEAM_COLORS = [
FILE: clients/sanitytest/components/testmeta.js
function singleOrPlural (line 4) | function singleOrPlural(name, count) {
class TestMeta (line 12) | class TestMeta extends Component {
method constructor (line 13) | constructor(name, parsingError, results, options) {
FILE: clients/sanitytest/components/testresults.js
class TestResults (line 13) | class TestResults extends Component {
method constructor (line 14) | constructor(parser) {
method getDdsMipmap (line 116) | getDdsMipmap(parser, i) {
method addMipmap (line 140) | addMipmap(imageData) {
method filter (line 148) | filter(unused, warnings, severe, errors) {
class TestResultsNode (line 155) | class TestResultsNode extends Component {
method constructor (line 156) | constructor(node, parentElement) {
method filter (line 202) | filter(unused, warnings, severe, errors) {
method matchFilters (line 216) | matchFilters(unused, warnings, severe, errors) {
FILE: clients/sanitytest/components/tooltips.js
function getTooltip (line 1) | function getTooltip(message) {
FILE: clients/sanitytest/components/viewer.js
class Viewer (line 19) | class Viewer extends Component {
method constructor (line 20) | constructor(tester, options) {
method load (line 128) | async load(test) {
method render (line 242) | render(test) {
method updateExtents (line 295) | updateExtents() {
method showCollisions (line 313) | showCollisions(show) {
method setSequence (line 325) | setSequence(index) {
method setCamera (line 362) | setCamera(index) {
method setTeamColor (line 370) | setTeamColor(index) {
method tryToInjectCustomTextures (line 378) | tryToInjectCustomTextures(customTest) {
FILE: clients/sanitytest/components/viewercontrols.js
class ViewerControls (line 7) | class ViewerControls extends Component {
method constructor (line 8) | constructor(viewer, options) {
method frame (line 123) | frame(frame) {
method updateInstance (line 127) | updateInstance(instance) {
method setSequence (line 145) | setSequence(sequence) {
method setCamera (line 153) | setCamera(camera) {
FILE: clients/sanitytest/test.js
class Test (line 10) | class Test {
method constructor (line 11) | constructor(tester, name, buffer, pathSolver) {
method show (line 59) | show() {
method hide (line 71) | hide() {
FILE: clients/shared/camera.js
function setupCamera (line 4) | function setupCamera(scene, options = {}) {
function getTouchesLength (line 14) | function getTouchesLength(touch1, touch2) {
constant TOUCH_MODE_INVALID (line 22) | const TOUCH_MODE_INVALID = -1;
constant TOUCH_MODE_ROTATE (line 23) | const TOUCH_MODE_ROTATE = 0;
constant TOUCH_MODE_ZOOM (line 24) | const TOUCH_MODE_ZOOM = 1;
class SimpleOrbitCamera (line 30) | class SimpleOrbitCamera {
method constructor (line 31) | constructor(scene, options = {}) {
method update (line 174) | update() {
method move (line 200) | move(x, y) {
method rotate (line 217) | rotate(x, y) {
method zoom (line 225) | zoom(factor) {
method manualChange (line 231) | manualChange() {
method onResize (line 244) | onResize() {
method moveToAndFace (line 257) | moveToAndFace(position, target) {
method updateInternalCamera (line 273) | updateInternalCamera() {
method applyInstanceCamera (line 293) | applyInstanceCamera(instance) {
FILE: clients/shared/component.js
class Component (line 3) | class Component {
method constructor (line 4) | constructor(options) {
method hide (line 8) | hide() {
method show (line 12) | show() {
method highlight (line 16) | highlight() {
method normal (line 20) | normal() {
FILE: clients/shared/components/toggle.js
class Toggle (line 3) | class Toggle extends Component {
method constructor (line 4) | constructor(offName, onName, callback, options) {
method toggle (line 13) | toggle() {
FILE: clients/shared/domutils.js
function createElement (line 1) | function createElement(options) {
function hideElement (line 63) | function hideElement(element) {
function showElement (line 67) | function showElement(element) {
function scrollToBottom (line 71) | function scrollToBottom(element) {
function scrolledToBottom (line 75) | function scrolledToBottom(element) {
function addTextToRow (line 79) | function addTextToRow(row, text) {
function addElementToRow (line 87) | function addElementToRow(row, element) {
function clearSelect (line 95) | function clearSelect(element) {
FILE: clients/shared/localorhive.js
function localOrHive (line 3) | function localOrHive(src, params) {
FILE: clients/shared/utils.js
function aFrame (line 3) | function aFrame() {
function getAllFileEntries (line 9) | async function getAllFileEntries(dataTransfer) {
function readAllDirectoryEntries (line 31) | async function readAllDirectoryEntries(directoryReader) {
function readEntriesPromise (line 44) | async function readEntriesPromise(directoryReader) {
function readFile (line 54) | async function readFile(file, asText) {
function readEntry (line 70) | async function readEntry(entry, asText) {
FILE: clients/tests/components/unittester.js
class UnitTesterComponent (line 11) | class UnitTesterComponent extends Component {
method constructor (line 12) | constructor(parentElement) {
method clear (line 56) | clear() {
method result (line 64) | result(result) {
method run (line 114) | run() {
method download (line 146) | download() {
FILE: clients/tests/tests/base.js
method load (line 8) | load(viewer) {
method test (line 14) | test(viewer, scene, camera, models) {
FILE: clients/tests/tests/m3.js
method load (line 8) | load(viewer) {
method test (line 11) | test(viewer, scene, camera, model) {
method load (line 22) | load(viewer) {
method test (line 25) | test(viewer, scene, camera, model) {
method load (line 38) | load(viewer) {
method test (line 41) | test(viewer, scene, camera, model) {
method load (line 52) | load(viewer) {
method test (line 55) | test(viewer, scene, camera, model) {
method load (line 66) | load(viewer) {
method test (line 69) | test(viewer, scene, camera, model) {
method load (line 80) | load(viewer) {
method test (line 83) | test(viewer, scene, camera, model) {
FILE: clients/tests/tests/mdx.js
method load (line 9) | load(viewer) {
method test (line 12) | test(viewer, scene, camera, model) {
method load (line 23) | load(viewer) {
method test (line 26) | test(viewer, scene, camera, model) {
method load (line 39) | load(viewer) {
method test (line 42) | test(viewer, scene, camera, model) {
method load (line 53) | load(viewer) {
method test (line 56) | test(viewer, scene, camera, model) {
method load (line 67) | load(viewer) {
method test (line 70) | test(viewer, scene, camera, model) {
method load (line 84) | load(viewer) {
method test (line 87) | test(viewer, scene, camera, model) {
method load (line 100) | load(viewer) {
method test (line 103) | test(viewer, scene, camera, model) {
method load (line 116) | load(viewer) {
method test (line 119) | test(viewer, scene, camera, model) {
method load (line 135) | load(viewer) {
method test (line 138) | test(viewer, scene, camera, model) {
method load (line 158) | load(viewer) {
method test (line 161) | test(viewer, scene, camera, model) {
method load (line 176) | load(viewer) {
method test (line 179) | test(viewer, scene, camera, model) {
method load (line 200) | load(viewer) {
method test (line 203) | test(viewer, scene, camera, model) {
method load (line 221) | load(viewer) {
method test (line 224) | test(viewer, scene, camera, model) {
method load (line 239) | load(viewer) {
method test (line 242) | test(viewer, scene, camera, model) {
method load (line 257) | load(viewer) {
method test (line 260) | test(viewer, scene, camera, model) {
method load (line 275) | load(viewer) {
method test (line 278) | test(viewer, scene, camera, model) {
method load (line 293) | load(viewer) {
method test (line 296) | test(viewer, scene, camera, model) {
method load (line 311) | load(viewer) {
method test (line 314) | test(viewer, scene, camera, model) {
method load (line 332) | load(viewer) {
method test (line 335) | test(viewer, scene, camera, model) {
method load (line 353) | load(viewer) {
method test (line 356) | test(viewer, scene, camera, model) {
method load (line 371) | load(viewer) {
method test (line 374) | test(viewer, scene, camera, model) {
method load (line 389) | load(viewer) {
method test (line 392) | test(viewer, scene, camera, model) {
method load (line 409) | load(viewer) {
method test (line 412) | test(viewer, scene, camera, model) {
FILE: clients/tests/tests/mdxprimitives.js
method load (line 13) | load(viewer) {
method test (line 16) | test(viewer, scene, camera, model) {
method load (line 27) | load(viewer) {
method test (line 30) | test(viewer, scene, camera, model) {
method load (line 41) | load(viewer) {
method test (line 44) | test(viewer, scene, camera, model) {
method load (line 55) | load(viewer) {
method test (line 58) | test(viewer, scene, camera, model) {
method load (line 69) | load(viewer) {
method test (line 74) | test(viewer, scene, camera, model) {
method load (line 90) | load(viewer) {
method test (line 93) | test(viewer, scene, camera, model) {
method load (line 104) | load(viewer) {
method test (line 107) | test(viewer, scene, camera, model) {
method load (line 118) | load(viewer) {
method test (line 121) | test(viewer, scene, camera, model) {
method load (line 132) | load(viewer) {
method test (line 135) | test(viewer, scene, camera, model) {
method load (line 146) | load(viewer) {
method test (line 151) | test(viewer, scene, camera, model) {
method load (line 167) | load(viewer) {
method test (line 170) | test(viewer, scene, camera, model) {
method load (line 181) | load(viewer) {
method test (line 184) | test(viewer, scene, camera, model) {
method load (line 195) | load(viewer) {
method test (line 198) | test(viewer, scene, camera, model) {
method load (line 209) | load(viewer) {
method test (line 212) | test(viewer, scene, camera, model) {
method load (line 223) | load(viewer) {
method test (line 228) | test(viewer, scene, camera, model) {
method load (line 244) | load(viewer) {
method test (line 247) | test(viewer, scene, camera, model) {
method load (line 258) | load(viewer) {
method test (line 261) | test(viewer, scene, camera, model) {
method load (line 272) | load(viewer) {
method test (line 275) | test(viewer, scene, camera, model) {
method load (line 286) | load(viewer) {
method test (line 289) | test(viewer, scene, camera, model) {
method load (line 300) | load(viewer) {
method test (line 305) | test(viewer, scene, camera, model) {
method load (line 321) | load(viewer) {
method test (line 324) | test(viewer, scene, camera, model) {
method load (line 335) | load(viewer) {
method test (line 338) | test(viewer, scene, camera, model) {
method load (line 349) | load(viewer) {
method test (line 352) | test(viewer, scene, camera, model) {
method load (line 363) | load(viewer) {
method test (line 366) | test(viewer, scene, camera, model) {
method load (line 377) | load(viewer) {
method test (line 382) | test(viewer, scene, camera, model) {
FILE: clients/tests/unittester.js
class UnitTester (line 16) | class UnitTester {
method constructor (line 17) | constructor(wc3PathSolver) {
method add (line 42) | add(test) {
method test (line 55) | async test(callback) {
method download (line 89) | async download(callback) {
method isDataAGo (line 107) | isDataAGo(data) {
method getTestBlob (line 126) | async getTestBlob(test) {
method getComparisonBlob (line 173) | async getComparisonBlob(test) {
method addBaseName (line 185) | addBaseName(tests, baseName) {
FILE: clients/textureatlas/index.js
class TextureAtlasGenerator (line 1) | class TextureAtlasGenerator {
method constructor (line 2) | constructor() {
method status (line 60) | status(status) {
method error (line 64) | error(status) {
method setImage (line 73) | setImage(image) {
method setWidth (line 89) | setWidth(width) {
method setHeight (line 94) | setHeight(height) {
method setColumns (line 99) | setColumns(columns) {
method setRows (line 104) | setRows(rows) {
method setRevolutions (line 109) | setRevolutions(revolutions) {
method update (line 114) | update() {
FILE: clients/thirdparty/resemble.js
function setGlobalOutputSettings (line 43) | function setGlobalOutputSettings(settings) {
function colorsDistance (line 65) | function colorsDistance(c1, c2) {
function withinBoundingBox (line 74) | function withinBoundingBox(x, y, width, height, box) {
function withinComparedArea (line 83) | function withinComparedArea(x, y, width, height) {
function triggerDataUpdate (line 176) | function triggerDataUpdate() {
function loop (line 186) | function loop(w, h, callback) {
function parseImage (line 197) | function parseImage(sourceImageData, width, height) {
function loadImageData (line 243) | function loadImageData(fileDataForImage, callback) {
function isColorSimilar (line 325) | function isColorSimilar(a, b, color) {
function isPixelBrightnessSimilar (line 343) | function isPixelBrightnessSimilar(d1, d2) {
function getBrightness (line 353) | function getBrightness(r, g, b) {
function isRGBSame (line 357) | function isRGBSame(d1, d2) {
function isRGBSimilar (line 364) | function isRGBSimilar(d1, d2) {
function isContrasting (line 373) | function isContrasting(d1, d2) {
function getHue (line 380) | function getHue(red, green, blue) {
function isAntialiased (line 411) | function isAntialiased(
function copyPixel (line 474) | function copyPixel(px, offset, pix) {
function copyGrayScalePixel (line 485) | function copyGrayScalePixel(px, offset, pix) {
function getPixelInfo (line 496) | function getPixelInfo(dst, pix, offset) {
function addBrightnessInfo (line 509) | function addBrightnessInfo(pix) {
function addHueInfo (line 513) | function addHueInfo(pix) {
function analyseImages (line 517) | function analyseImages(img1, img2, width, height) {
function addLabel (line 675) | function addLabel(text, context, hiddenCanvas) {
function normalise (line 702) | function normalise(img, w, h) {
function outputSettings (line 718) | function outputSettings(options) {
function compare (line 765) | function compare(one, two) {
function getCompareApi (line 821) | function getCompareApi(param) {
function applyIgnore (line 968) | function applyIgnore(api, ignore) {
FILE: clients/weu/components/weuchanges.js
class WeuChanges (line 4) | class WeuChanges extends Component {
method constructor (line 5) | constructor(converter, changes) {
FILE: clients/weu/components/weuconverter.js
class WeuConverter (line 13) | class WeuConverter extends Component {
method constructor (line 14) | constructor(parentElement) {
method load (line 33) | async load() {
method clear (line 66) | clear() {
method indent (line 71) | indent() {
method deindent (line 75) | deindent() {
method text (line 79) | text(text) {
method error (line 85) | error(text) {
method results (line 91) | results(results) {
method showChanges (line 97) | showChanges(meta) {
method hideChanges (line 107) | hideChanges() {
method convertMap (line 115) | convertMap(name, buffer) {
method convertCampaign (line 153) | async convertCampaign(name, buffer) {
method convertFile (line 200) | convertFile(file) {
FILE: clients/weu/components/weumeta.js
class WeuMeta (line 7) | class WeuMeta extends Component {
method constructor (line 8) | constructor(converter, results) {
FILE: src/common/arrayunique.ts
function unique (line 4) | function unique<T>(a: T[]): T[] {
FILE: src/common/audio.ts
function decodeAudioData (line 11) | async function decodeAudioData(buffer: ArrayBuffer): Promise<AudioBuffer...
FILE: src/common/binarystream.ts
class BinaryStream (line 12) | class BinaryStream {
method constructor (line 19) | constructor(buffer: ArrayBuffer | Uint8Array, byteOffset?: number, byt...
method substream (line 37) | substream(byteLength: number): BinaryStream {
method skip (line 52) | skip(bytes: number): void {
method seek (line 64) | seek(index: number): void {
method read (line 77) | read(bytes: number): string {
method readNull (line 99) | readNull(): string {
method readBinary (line 123) | readBinary(bytes: number): string {
method readInt8 (line 145) | readInt8(): number {
method readInt16 (line 163) | readInt16(): number {
method readInt32 (line 181) | readInt32(): number {
method readUint8 (line 200) | readUint8(): number {
method readUint16 (line 216) | readUint16(): number {
method readUint32 (line 234) | readUint32(): number {
method readFloat32 (line 252) | readFloat32(): number {
method readFloat64 (line 270) | readFloat64(): number {
method readInt8Array (line 288) | readInt8Array(view: number | Int8Array): Int8Array {
method readInt16Array (line 313) | readInt16Array(view: number | Int16Array): Int16Array {
method readInt32Array (line 340) | readInt32Array(view: number | Int32Array): Int32Array {
method readUint8Array (line 367) | readUint8Array(view: number | Uint8Array): Uint8Array {
method readUint16Array (line 392) | readUint16Array(view: number | Uint16Array): Uint16Array {
method readUint32Array (line 419) | readUint32Array(view: number | Uint32Array): Uint32Array {
method readFloat32Array (line 446) | readFloat32Array(view: number | Float32Array): Float32Array {
method readFloat64Array (line 473) | readFloat64Array(view: number | Float64Array): Float64Array {
method write (line 502) | write(utf8: string): number {
method writeNull (line 515) | writeNull(utf8: string): number {
method writeBinary (line 527) | writeBinary(value: string): void {
method writeInt8 (line 542) | writeInt8(value: number): void {
method writeInt16 (line 550) | writeInt16(value: number): void {
method writeInt32 (line 565) | writeInt32(value: number): void {
method writeUint8 (line 582) | writeUint8(value: number): void {
method writeUint16 (line 590) | writeUint16(value: number): void {
method writeUint32 (line 605) | writeUint32(value: number): void {
method writeFloat32 (line 622) | writeFloat32(value: number): void {
method writeFloat64 (line 639) | writeFloat64(value: number): void {
method writeInt8Array (line 660) | writeInt8Array(view: Int8Array): void {
method writeInt16Array (line 674) | writeInt16Array(view: Int16Array): void {
method writeInt32Array (line 693) | writeInt32Array(view: Int32Array): void {
method writeUint8Array (line 714) | writeUint8Array(view: Uint8Array): void {
method writeUint16Array (line 728) | writeUint16Array(view: Uint16Array): void {
method writeUint32Array (line 747) | writeUint32Array(view: Uint32Array): void {
method writeFloat32Array (line 768) | writeFloat32Array(view: Float32Array): void {
method writeFloat64Array (line 789) | writeFloat64Array(view: Float64Array): void {
FILE: src/common/bitstream.ts
class BitStream (line 6) | class BitStream {
method constructor (line 14) | constructor(buffer: ArrayBuffer | Uint8Array, byteOffset?: number, byt...
method peekBits (line 31) | peekBits(bits: number): number {
method readBits (line 40) | readBits(bits: number): number {
method skipBits (line 52) | skipBits(bits: number): void {
method loadBits (line 62) | loadBits(bits: number): void {
FILE: src/common/bytesof.ts
function bytesOf (line 8) | function bytesOf(buffer: ArrayBuffer | Uint8Array | string | number[]): ...
FILE: src/common/canvas.ts
function blobToImage (line 14) | function blobToImage(blob: Blob): Promise<HTMLImageElement> {
function blobToImageData (line 31) | function blobToImageData(blob: Blob): Promise<ImageData> {
function imageDataToBlob (line 55) | function imageDataToBlob(imageData: ImageData): Promise<Blob | null> {
function imageDataToDataUrl (line 68) | function imageDataToDataUrl(imageData: ImageData): string {
function imageDataToImage (line 77) | function imageDataToImage(imageData: ImageData): HTMLImageElement {
function imageToImageData (line 85) | function imageToImageData(image: TexImageSource): ImageData {
function resizeImageData (line 97) | function resizeImageData(data: TexImageSource, width: number, height: nu...
FILE: src/common/convertbitrange.ts
function convertBitRange (line 8) | function convertBitRange(fromBits: number, toBits: number): number {
FILE: src/common/dxt.ts
function dx1Colors (line 12) | function dx1Colors(out: Uint8Array, color0: number, color1: number): void {
function dx3Colors (line 52) | function dx3Colors(out: Uint8Array, color0: number, color1: number): void {
function dx5Alphas (line 77) | function dx5Alphas(out: Uint8Array, alpha0: number, alpha1: number): void {
function rgColors (line 100) | function rgColors(out: Uint8Array, color0: number, color1: number): void {
function decodeDxt1 (line 128) | function decodeDxt1(src: Uint8Array, width: number, height: number): Uin...
function decodeDxt3 (line 169) | function decodeDxt3(src: Uint8Array, width: number, height: number): Uin...
function decodeDxt5 (line 212) | function decodeDxt5(src: Uint8Array, width: number, height: number): Uin...
function decodeRgtc (line 270) | function decodeRgtc(src: Uint8Array, width: number, height: number): Uin...
FILE: src/common/fetchdatatype.ts
type FetchDataTypeName (line 4) | type FetchDataTypeName = 'image' | 'text' | 'arrayBuffer' | 'bytes' | 'b...
type FetchDataType (line 9) | type FetchDataType = HTMLImageElement | string | ArrayBuffer | Uint8Arra...
type FetchResult (line 14) | interface FetchResult {
function fetchDataType (line 31) | async function fetchDataType(path: string, dataType: FetchDataTypeName):...
FILE: src/common/gl-matrix-addon.ts
constant VEC3_UNIT_X (line 3) | const VEC3_UNIT_X = vec3.fromValues(1, 0, 0);
constant VEC3_UNIT_Y (line 4) | const VEC3_UNIT_Y = vec3.fromValues(0, 1, 0);
constant VEC3_UNIT_Z (line 5) | const VEC3_UNIT_Z = vec3.fromValues(0, 0, 1);
constant VEC3_ZERO (line 6) | const VEC3_ZERO = vec3.create();
constant VEC3_ONE (line 7) | const VEC3_ONE = vec3.fromValues(1, 1, 1);
constant QUAT_ZERO (line 8) | const QUAT_ZERO = quat.fromValues(0, 0, 0, 0);
constant QUAT_DEFAULT (line 9) | const QUAT_DEFAULT = quat.create();
function unproject (line 13) | function unproject(out: vec3, v: vec3, inverseMatrix: mat4, viewport: ve...
function distanceToPlane (line 30) | function distanceToPlane(plane: vec4, point: vec3): number {
function distanceToPlane2 (line 39) | function distanceToPlane2(plane: vec4, x: number, y: number): number {
function distanceToPlane3 (line 48) | function distanceToPlane3(plane: vec4, x: number, y: number, z: number):...
function testSphere (line 59) | function testSphere(planes: vec4[], x: number, y: number, z: number, r: ...
function testCell (line 82) | function testCell(planes: vec4[], left: number, right: number, bottom: n...
function planeLength (line 102) | function planeLength(plane: vec4): number {
function normalizePlane (line 111) | function normalizePlane(out: vec4, plane: vec4): void {
function unpackPlanes (line 123) | function unpackPlanes(planes: vec4[], m: mat4): void {
function quatLookAt (line 190) | function quatLookAt(out: quat, from: vec3, to: vec3, worldUp: vec3): quat {
FILE: src/common/isformat.ts
function isPng (line 6) | function isPng(bytes: unknown): boolean {
function isJpeg (line 25) | function isJpeg(bytes: unknown): boolean {
function isGif (line 44) | function isGif(bytes: unknown): boolean {
function isWebP (line 63) | function isWebP(bytes: unknown): boolean {
FILE: src/common/math.ts
function degToRad (line 4) | function degToRad(degrees: number): number {
function radToDeg (line 11) | function radToDeg(radians: number): number {
function randomInRange (line 18) | function randomInRange(a: number, b: number): number {
function clamp (line 25) | function clamp(x: number, minVal: number, maxVal: number): number {
function lerp (line 32) | function lerp(a: number, b: number, t: number): number {
function hermite (line 39) | function hermite(a: number, b: number, c: number, d: number, t: number):...
function bezier (line 52) | function bezier(a: number, b: number, c: number, d: number, t: number): ...
function copysign (line 67) | function copysign(x: number, y: number): number {
function powerOfTwo (line 86) | function powerOfTwo(x: number): number {
function isPowerOfTwo (line 101) | function isPowerOfTwo(x: number): boolean {
FILE: src/common/path.ts
function basename (line 6) | function basename(path: string): string {
function extname (line 31) | function extname(path: string): string {
function filename (line 50) | function filename(path: string): string {
FILE: src/common/searches.ts
function isStringInBytes (line 1) | function isStringInBytes(buffer: Uint8Array, target: string, offset = 0,...
function isStringInString (line 27) | function isStringInString(buffer: string, target: string, offset = 0, le...
function boundIndexOf (line 53) | function boundIndexOf(buffer: Uint8Array, target: number, offset = 0, le...
FILE: src/common/seededrandom.ts
function seededRandom (line 5) | function seededRandom(seed: number) {
FILE: src/common/sstrhash2.ts
function hash (line 1) | function hash(buffer: Uint8Array): number {
function sstrhash2 (line 73) | function sstrhash2(key: string): number {
FILE: src/common/stringreverse.ts
function reverse (line 4) | function reverse(s: string): string {
FILE: src/common/typecast.ts
function uint8ToInt8 (line 14) | function uint8ToInt8(a: number): number {
function uint8ToInt16 (line 23) | function uint8ToInt16(a: number, b: number): number {
function uint8ToInt24 (line 33) | function uint8ToInt24(a: number, b: number, c: number): number {
function uint8ToInt32 (line 45) | function uint8ToInt32(a: number, b: number, c: number, d: number): number {
function uint8ToUint16 (line 57) | function uint8ToUint16(a: number, b: number): number {
function uint8ToUint24 (line 67) | function uint8ToUint24(a: number, b: number, c: number): number {
function uint8ToUint32 (line 79) | function uint8ToUint32(a: number, b: number, c: number, d: number): numb...
function uint8ToFloat32 (line 91) | function uint8ToFloat32(a: number, b: number, c: number, d: number): num...
function uint8ToFloat64 (line 103) | function uint8ToFloat64(a: number, b: number, c: number, d: number, e: n...
function int8ToUint8 (line 119) | function int8ToUint8(a: number): number {
function int16ToUint8 (line 130) | function int16ToUint8(out: Uint8Array, a: number): Uint8Array {
function int24ToUint8 (line 144) | function int24ToUint8(out: Uint8Array, a: number): Uint8Array {
function int32ToUint8 (line 159) | function int32ToUint8(out: Uint8Array, a: number): Uint8Array {
function uint16ToUint8 (line 175) | function uint16ToUint8(out: Uint8Array, a: number): Uint8Array {
function uint24ToUint8 (line 189) | function uint24ToUint8(out: Uint8Array, a: number): Uint8Array {
function uint32ToUint8 (line 204) | function uint32ToUint8(out: Uint8Array, a: number): Uint8Array {
function float32ToUint8 (line 220) | function float32ToUint8(out: Uint8Array, a: number): Uint8Array {
function float64ToUint8 (line 236) | function float64ToUint8(out: Uint8Array, a: number): Uint8Array {
function numberToUint32 (line 254) | function numberToUint32(number: number): number {
function stringToBase256 (line 263) | function stringToBase256(string: string): number {
function base256ToString (line 276) | function base256ToString(number: number): string {
FILE: src/common/urlwithparams.ts
function urlWithParams (line 6) | function urlWithParams(src: string, params: {[key: string]: string }): s...
FILE: src/common/utf8.ts
function decodeUtf8 (line 7) | function decodeUtf8(buffer: ArrayBuffer | Uint8Array): string {
function encodeUtf8 (line 14) | function encodeUtf8(utf8: string): Uint8Array {
function byteLengthUtf8 (line 23) | function byteLengthUtf8(str: string): number {
function splitUtf8ByteLength (line 42) | function splitUtf8ByteLength(str: string, chunkBytelength: number): stri...
FILE: src/parsers/blp/image.ts
constant BLP1_MAGIC (line 6) | const BLP1_MAGIC = 0x31504c42;
constant CONTENT_JPG (line 7) | const CONTENT_JPG = 0x0;
class BlpImage (line 13) | class BlpImage {
method load (line 32) | load(buffer: ArrayBuffer | Uint8Array): void {
method getMipmap (line 64) | getMipmap(level: number): ImageData {
method mipmaps (line 126) | mipmaps(): number {
method fakeMipmaps (line 138) | fakeMipmaps(): number {
FILE: src/parsers/blp/isformat.ts
function isBlp (line 4) | function isBlp(bytes: unknown): boolean {
FILE: src/parsers/blp/jpg.js
function JpegError (line 29) | function JpegError(msg) {
function buildHuffmanTable (line 48) | function buildHuffmanTable(codeLengths, values) {
function getBlockBufferOffset (line 93) | function getBlockBufferOffset(component, row, col) {
function decodeScan (line 96) | function decodeScan(data, offset, frame, components, resetInterval, spec...
function quantizeAndInverse (line 353) | function quantizeAndInverse(component, blockBufferOffset, p) {
function buildComponentData (line 502) | function buildComponentData(frame, component) {
function clamp0to255 (line 514) | function clamp0to255(a) {
function findNextFileMarker (line 517) | function findNextFileMarker(data, currentPos, startPos) {
class JpegImage (line 548) | class JpegImage {
method constructor (line 549) | constructor() {
method parse (line 556) | parse(data) {
method getData (line 792) | getData(imageData) {
FILE: src/parsers/dds/image.ts
constant DDS_MAGIC (line 5) | const DDS_MAGIC = 0x20534444;
constant DDSD_MIPMAPCOUNT (line 6) | const DDSD_MIPMAPCOUNT = 0x20000;
constant DDPF_FOURCC (line 7) | const DDPF_FOURCC = 0x4;
constant FOURCC_DXT1 (line 9) | const FOURCC_DXT1 = 0x31545844;
constant FOURCC_DXT3 (line 10) | const FOURCC_DXT3 = 0x33545844;
constant FOURCC_DXT5 (line 11) | const FOURCC_DXT5 = 0x35545844;
constant FOURCC_ATI2 (line 12) | const FOURCC_ATI2 = 0x32495441;
constant FOURCC_DX10 (line 14) | const FOURCC_DX10 = 0x30315844;
constant DXGI_FORMAT_BC1_UNORM (line 15) | const DXGI_FORMAT_BC1_UNORM = 0x00000047;
constant DXGI_FORMAT_BC2_UNORM (line 16) | const DXGI_FORMAT_BC2_UNORM = 0x0000004A;
constant DXGI_FORMAT_BC3_UNORM (line 17) | const DXGI_FORMAT_BC3_UNORM = 0x0000004D;
constant DXGI_FORMAT_BC5_UNORM (line 18) | const DXGI_FORMAT_BC5_UNORM = 0x00000053;
class DdsImage (line 23) | class DdsImage {
method load (line 31) | load(buffer: ArrayBuffer | Uint8Array): void {
method mipmaps (line 104) | mipmaps(): number {
method getMipmap (line 108) | getMipmap(level: number, raw = false): { width: number, height: number...
FILE: src/parsers/dds/isformat.ts
function isDds (line 4) | function isDds(bytes: unknown): boolean {
FILE: src/parsers/ini/file.ts
type IniSection (line 4) | type IniSection = Map<string, string>;
class IniFile (line 9) | class IniFile {
method load (line 13) | load(buffer: string): void {
method save (line 54) | save(): string {
method getSection (line 72) | getSection(name: string): IniSection | undefined {
FILE: src/parsers/m3/animationreference.ts
method load (line 15) | load(stream: BinaryStream): void {
class PixelAnimationReference (line 29) | class PixelAnimationReference extends AnimationReference {
method readInitNullValues (line 30) | readInitNullValues(stream: BinaryStream): void {
class Uint16AnimationReference (line 39) | class Uint16AnimationReference extends AnimationReference {
method readInitNullValues (line 40) | readInitNullValues(stream: BinaryStream): void {
class Uint32AnimationReference (line 49) | class Uint32AnimationReference extends AnimationReference {
method readInitNullValues (line 50) | readInitNullValues(stream: BinaryStream): void {
class Float32AnimationReference (line 59) | class Float32AnimationReference extends AnimationReference {
method readInitNullValues (line 60) | readInitNullValues(stream: BinaryStream): void {
class Vector2AnimationReference (line 69) | class Vector2AnimationReference extends AnimationReference {
method readInitNullValues (line 70) | readInitNullValues(stream: BinaryStream): void {
class Vector3AnimationReference (line 79) | class Vector3AnimationReference extends AnimationReference {
method readInitNullValues (line 80) | readInitNullValues(stream: BinaryStream): void {
class Vector4AnimationReference (line 89) | class Vector4AnimationReference extends AnimationReference {
method readInitNullValues (line 90) | readInitNullValues(stream: BinaryStream): void {
FILE: src/parsers/m3/attachmentpoint.ts
class AttachmentPoint (line 8) | class AttachmentPoint {
method load (line 14) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/batch.ts
class Batch (line 7) | class Batch {
method load (line 15) | load(stream: BinaryStream, version: number, _index: IndexEntry[]): void {
FILE: src/parsers/m3/bone.ts
class Bone (line 9) | class Bone {
method load (line 21) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/boundingshape.ts
class BoundingShape (line 6) | class BoundingShape {
method load (line 19) | load(stream: BinaryStream): void {
FILE: src/parsers/m3/boundingsphere.ts
class BoundingSphere (line 6) | class BoundingSphere {
method load (line 11) | load(stream: BinaryStream): void {
FILE: src/parsers/m3/camera.ts
class Camera (line 9) | class Camera {
method load (line 23) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/division.ts
class Division (line 8) | class Division {
method load (line 16) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/event.ts
class Event (line 8) | class Event {
method load (line 22) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/indexentry.ts
type EntryType (line 91) | type EntryType = Md34[] | ModelHeader[] | Sequence[] | Stc[] | Stg[] | S...
type SingleEntryType (line 92) | type SingleEntryType = Md34 | ModelHeader | Sequence | Stc | Stg | Sts |...
class IndexEntry (line 97) | class IndexEntry {
method constructor (line 104) | constructor(stream: BinaryStream, index: IndexEntry[]) {
FILE: src/parsers/m3/isformat.ts
function isM3 (line 4) | function isM3(bytes: unknown): boolean {
FILE: src/parsers/m3/layer.ts
class Layer (line 9) | class Layer {
method load (line 55) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/light.ts
class Light (line 8) | class Light {
method load (line 26) | load(stream: BinaryStream, version: number, _index: IndexEntry[]): void {
FILE: src/parsers/m3/materialreference.ts
class MaterialReference (line 7) | class MaterialReference {
method load (line 12) | load(stream: BinaryStream, version: number, _index: IndexEntry[]): void {
FILE: src/parsers/m3/md34.ts
class Md34 (line 9) | class Md34 {
method load (line 16) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/model.ts
class Model (line 9) | class Model {
method load (line 13) | load(src: ArrayBuffer | Uint8Array): void {
FILE: src/parsers/m3/modelheader.ts
class ModelHeader (line 10) | class ModelHeader {
method constructor (line 66) | constructor() {
method load (line 72) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/reference.ts
class Reference (line 7) | class Reference {
method load (line 13) | load(stream: BinaryStream, index: IndexEntry[]): void {
method get (line 23) | get(): EntryType | undefined {
method first (line 34) | first(): SingleEntryType | undefined {
FILE: src/parsers/m3/region.ts
class Region (line 7) | class Region {
method load (line 25) | load(stream: BinaryStream, version: number, _index: IndexEntry[]): void {
FILE: src/parsers/m3/sd.ts
class Sd (line 8) | class Sd {
method load (line 15) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/sequence.ts
class Sequence (line 9) | class Sequence {
method load (line 18) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/standardmaterial.ts
class StandardMaterial (line 9) | class StandardMaterial {
method load (line 52) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/stc.ts
class Stc (line 8) | class Stc {
method constructor (line 19) | constructor() {
method load (line 25) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/stg.ts
class Stg (line 8) | class Stg {
method load (line 13) | load(stream: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/sts.ts
class Sts (line 8) | class Sts {
method load (line 12) | load(reader: BinaryStream, version: number, index: IndexEntry[]): void {
FILE: src/parsers/m3/unsupportedentry.ts
class UnsupportedEntry (line 10) | class UnsupportedEntry {
method constructor (line 15) | constructor(stream: BinaryStream, version: number, index: IndexEntry[]) {
FILE: src/parsers/mdlx/animatedobject.ts
class AnimatedObject (line 9) | class AnimatedObject {
method readAnimations (line 12) | readAnimations(stream: BinaryStream, size: number): void {
method writeAnimations (line 25) | writeAnimations(stream: BinaryStream): void {
method readAnimatedBlock (line 36) | * readAnimatedBlock(stream: TokenStream): Generator<string> {
method readAnimation (line 46) | readAnimation(stream: TokenStream, name: string): void {
method writeAnimation (line 54) | writeAnimation(stream: TokenStream, name: string): boolean {
method getByteLength (line 68) | getByteLength(_version = 0): number {
FILE: src/parsers/mdlx/animations.ts
type InterpolationType (line 4) | const enum InterpolationType {
method readMdx (line 27) | readMdx(stream: BinaryStream, name: string): void {
method writeMdx (line 50) | writeMdx(stream: BinaryStream): void {
method readMdl (line 74) | readMdl(stream: TokenStream, name: string): void {
method writeMdl (line 123) | writeMdl(stream: TokenStream, name: string): void {
method getByteLength (line 165) | getByteLength(): number {
class UintAnimation (line 187) | class UintAnimation extends Animation {
method readMdxValue (line 188) | readMdxValue(stream: BinaryStream): Uint32Array {
method writeMdxValue (line 192) | writeMdxValue(stream: BinaryStream, value: Uint32Array): void {
method readMdlValue (line 196) | readMdlValue(stream: TokenStream): Uint32Array {
method writeMdlValue (line 200) | writeMdlValue(stream: TokenStream, name: string, value: Uint32Array): ...
class FloatAnimation (line 208) | class FloatAnimation extends Animation {
method readMdxValue (line 209) | readMdxValue(stream: BinaryStream): Float32Array {
method writeMdxValue (line 213) | writeMdxValue(stream: BinaryStream, value: Float32Array): void {
method readMdlValue (line 217) | readMdlValue(stream: TokenStream): Float32Array {
method writeMdlValue (line 221) | writeMdlValue(stream: TokenStream, name: string, value: Float32Array):...
class Vector3Animation (line 229) | class Vector3Animation extends Animation {
method readMdxValue (line 230) | readMdxValue(stream: BinaryStream): Float32Array {
method writeMdxValue (line 234) | writeMdxValue(stream: BinaryStream, value: Float32Array): void {
method readMdlValue (line 238) | readMdlValue(stream: TokenStream): Float32Array {
method writeMdlValue (line 242) | writeMdlValue(stream: TokenStream, name: string, value: Float32Array):...
class Vector4Animation (line 250) | class Vector4Animation extends Animation {
method readMdxValue (line 251) | readMdxValue(stream: BinaryStream): Float32Array {
method writeMdxValue (line 255) | writeMdxValue(stream: BinaryStream, value: Float32Array): void {
method readMdlValue (line 259) | readMdlValue(stream: TokenStream): Float32Array {
method writeMdlValue (line 263) | writeMdlValue(stream: TokenStream, name: string, value: Float32Array):...
FILE: src/parsers/mdlx/attachment.ts
class Attachment (line 8) | class Attachment extends GenericObject {
method constructor (line 12) | constructor() {
method readMdx (line 16) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 28) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 39) | readMdl(stream: TokenStream): void {
method writeMdl (line 53) | writeMdl(stream: TokenStream): void {
method getByteLength (line 69) | override getByteLength(): number {
FILE: src/parsers/mdlx/bone.ts
class Bone (line 8) | class Bone extends GenericObject {
method constructor (line 12) | constructor() {
method readMdx (line 16) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 23) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 30) | readMdl(stream: TokenStream): void {
method writeMdl (line 54) | writeMdl(stream: TokenStream): void {
method getByteLength (line 74) | override getByteLength(): number {
FILE: src/parsers/mdlx/camera.ts
class Camera (line 8) | class Camera extends AnimatedObject {
method readMdx (line 16) | readMdx(stream: BinaryStream): void {
method writeMdx (line 29) | writeMdx(stream: BinaryStream): void {
method readMdl (line 41) | readMdl(stream: TokenStream): void {
method writeMdl (line 73) | writeMdl(stream: TokenStream): void {
method getByteLength (line 91) | override getByteLength(): number {
FILE: src/parsers/mdlx/collisionshape.ts
type Shape (line 5) | const enum Shape {
class CollisionShape (line 15) | class CollisionShape extends GenericObject {
method constructor (line 20) | constructor() {
method readMdx (line 24) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 40) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 55) | readMdl(stream: TokenStream): void {
method writeMdl (line 85) | writeMdl(stream: TokenStream): void {
method getByteLength (line 124) | override getByteLength(): number {
FILE: src/parsers/mdlx/eventobject.ts
class EventObject (line 8) | class EventObject extends GenericObject {
method constructor (line 12) | constructor() {
method readMdx (line 16) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 27) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 35) | readMdl(stream: TokenStream): void {
method writeMdl (line 61) | writeMdl(stream: TokenStream): void {
method getByteLength (line 81) | override getByteLength(): number {
FILE: src/parsers/mdlx/extent.ts
class Extent (line 7) | class Extent {
method readMdx (line 12) | readMdx(stream: BinaryStream): void {
method writeMdx (line 18) | writeMdx(stream: BinaryStream): void {
method writeMdl (line 24) | writeMdl(stream: TokenStream): void {
FILE: src/parsers/mdlx/faceeffect.ts
class FaceEffect (line 7) | class FaceEffect {
method readMdx (line 11) | readMdx(stream: BinaryStream): void {
method writeMdx (line 16) | writeMdx(stream: BinaryStream): void {
method readMdl (line 21) | readMdl(stream: TokenStream): void {
method writeMdl (line 33) | writeMdl(stream: TokenStream): void {
FILE: src/parsers/mdlx/genericobject.ts
type Flags (line 6) | const enum Flags {
method constructor (line 30) | constructor(flags = Flags.None) {
method readMdx (line 36) | readMdx(stream: BinaryStream): void {
method writeMdx (line 47) | writeMdx(stream: BinaryStream): void {
method writeNonGenericAnimationChunks (line 59) | writeNonGenericAnimationChunks(stream: BinaryStream): void {
method readGenericBlock (line 65) | * readGenericBlock(stream: TokenStream): Generator<string> {
method writeGenericHeader (line 105) | writeGenericHeader(stream: TokenStream): void {
method writeGenericAnimations (line 145) | writeGenericAnimations(stream: TokenStream): void {
method eachAnimation (line 154) | * eachAnimation(wantGeneric: boolean): Generator<Animation> {
method getGenericByteLength (line 170) | getGenericByteLength(): number {
method getByteLength (line 180) | override getByteLength(): number {
FILE: src/parsers/mdlx/geoset.ts
class Geoset (line 8) | class Geoset {
method readMdx (line 47) | readMdx(stream: BinaryStream, version: number): void {
method writeMdx (line 108) | writeMdx(stream: BinaryStream, version: number): void {
method readMdl (line 175) | readMdl(stream: TokenStream): void {
method writeMdl (line 271) | writeMdl(stream: TokenStream, version: number): void {
method getByteLength (line 348) | getByteLength(version: number): number {
FILE: src/parsers/mdlx/geosetanimation.ts
class GeosetAnimation (line 8) | class GeosetAnimation extends AnimatedObject {
method readMdx (line 14) | readMdx(stream: BinaryStream): void {
method writeMdx (line 25) | writeMdx(stream: BinaryStream): void {
method readMdl (line 35) | readMdl(stream: TokenStream): void {
method writeMdl (line 57) | writeMdl(stream: TokenStream): void {
method getByteLength (line 79) | override getByteLength(): number {
FILE: src/parsers/mdlx/helper.ts
class Helper (line 7) | class Helper extends GenericObject {
method readMdl (line 8) | readMdl(stream: TokenStream): void {
method writeMdl (line 14) | writeMdl(stream: TokenStream): void {
FILE: src/parsers/mdlx/isformat.ts
function isMdx (line 6) | function isMdx(bytes: unknown): boolean {
function isMdl (line 27) | function isMdl(bytes: unknown): boolean {
FILE: src/parsers/mdlx/layer.ts
type FilterMode (line 5) | const enum FilterMode {
type Flags (line 15) | const enum Flags {
function stringToMode (line 28) | function stringToMode(s: string): FilterMode {
function modeToString (line 39) | function modeToString(m: FilterMode): string {
class Layer (line 53) | class Layer extends AnimatedObject {
method readMdx (line 77) | readMdx(stream: BinaryStream, version: number): void {
method writeMdx (line 99) | writeMdx(stream: BinaryStream, version: number): void {
method readMdl (line 119) | readMdl(stream: TokenStream): void {
method writeMdl (line 171) | writeMdl(stream: TokenStream, version: number): void {
method getByteLength (line 243) | override getByteLength(version: number): number {
FILE: src/parsers/mdlx/light.ts
type LightType (line 5) | const enum LightType {
class Light (line 15) | class Light extends GenericObject {
method constructor (line 23) | constructor() {
method readMdx (line 27) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 43) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 58) | readMdl(stream: TokenStream): void {
method writeMdl (line 98) | writeMdl(stream: TokenStream): void {
method getByteLength (line 140) | override getByteLength(): number {
FILE: src/parsers/mdlx/material.ts
type Flags (line 5) | const enum Flags {
class Material (line 17) | class Material {
method readMdx (line 26) | readMdx(stream: BinaryStream, version: number): void {
method writeMdx (line 47) | writeMdx(stream: BinaryStream, version: number): void {
method readMdl (line 64) | readMdl(stream: TokenStream): void {
method writeMdl (line 92) | writeMdl(stream: TokenStream, version: number): void {
method getByteLength (line 132) | getByteLength(version: number): number {
FILE: src/parsers/mdlx/model.ts
type MdxStaticObject (line 28) | type MdxStaticObject = Sequence | Texture | FaceEffect;
type MdxDynamicObject (line 29) | type MdxDynamicObject = Material | TextureAnimation | Geoset | GeosetAni...
type MdlNumberedObject (line 30) | type MdlNumberedObject = Sequence | Texture | Material | TextureAnimation;
type MdlObject (line 31) | type MdlObject = Geoset | GeosetAnimation | Bone | Light | Helper | Atta...
class Model (line 37) | class Model {
method load (line 95) | load(buffer: ArrayBuffer | Uint8Array | string): void {
method loadMdx (line 116) | loadMdx(buffer: ArrayBuffer | Uint8Array): void {
method loadVersionChunk (line 179) | loadVersionChunk(stream: BinaryStream): void {
method loadModelChunk (line 183) | loadModelChunk(stream: BinaryStream): void {
method loadStaticObjects (line 190) | loadStaticObjects<T extends MdxStaticObject>(out: T[], constructor: ne...
method loadGlobalSequenceChunk (line 200) | loadGlobalSequenceChunk(stream: BinaryStream, size: number): void {
method loadDynamicObjects (line 206) | loadDynamicObjects<T extends MdxDynamicObject>(out: T[], constructor: ...
method loadPivotPointChunk (line 218) | loadPivotPointChunk(stream: BinaryStream, size: number): void {
method loadBindPoseChunk (line 224) | loadBindPoseChunk(stream: BinaryStream, _size: number): void {
method saveMdx (line 233) | saveMdx(): Uint8Array {
method saveVersionChunk (line 275) | saveVersionChunk(stream: BinaryStream): void {
method saveModelChunk (line 281) | saveModelChunk(stream: BinaryStream): void {
method saveStaticObjectChunk (line 290) | saveStaticObjectChunk(stream: BinaryStream, name: string, objects: (Se...
method saveGlobalSequenceChunk (line 301) | saveGlobalSequenceChunk(stream: BinaryStream): void {
method saveDynamicObjectChunk (line 312) | saveDynamicObjectChunk(stream: BinaryStream, name: string, objects: (M...
method savePivotPointChunk (line 323) | savePivotPointChunk(stream: BinaryStream): void {
method saveBindPoseChunk (line 334) | saveBindPoseChunk(stream: BinaryStream): void {
method loadMdl (line 349) | loadMdl(buffer: string): void {
method loadVersionBlock (line 406) | loadVersionBlock(stream: TokenStream): void {
method loadModelBlock (line 416) | loadModelBlock(stream: TokenStream): void {
method loadNumberedObjectBlock (line 453) | loadNumberedObjectBlock<T extends MdlNumberedObject>(out: T[], constru...
method loadGlobalSequenceBlock (line 469) | loadGlobalSequenceBlock(stream: TokenStream): void {
method loadObject (line 481) | loadObject<T extends MdlObject>(out: T[], constructor: new () => T, st...
method loadPivotPointBlock (line 489) | loadPivotPointBlock(stream: TokenStream): void {
method loadBindPoseBlock (line 501) | loadBindPoseBlock(stream: TokenStream): void {
method saveMdl (line 522) | saveMdl(): string {
method saveVersionBlock (line 559) | saveVersionBlock(stream: TokenStream): void {
method saveModelBlock (line 565) | saveModelBlock(stream: TokenStream): void {
method saveStaticObjectsBlock (line 578) | saveStaticObjectsBlock(stream: TokenStream, name: string, objects: (Se...
method saveGlobalSequenceBlock (line 590) | saveGlobalSequenceBlock(stream: TokenStream): void {
method saveObjects (line 602) | saveObjects(stream: TokenStream, objects: (Geoset | GeosetAnimation | ...
method savePivotPointBlock (line 608) | savePivotPointBlock(stream: TokenStream): void {
method saveBindPoseBlock (line 620) | saveBindPoseBlock(stream: TokenStream): void {
method getByteLength (line 639) | getByteLength(): number {
method getObjectsByteLength (line 676) | getObjectsByteLength(objects: (Material | TextureAnimation | Geoset | ...
method getDynamicObjectsChunkByteLength (line 686) | getDynamicObjectsChunkByteLength(objects: (Material | TextureAnimation...
method getStaticObjectsChunkByteLength (line 694) | getStaticObjectsChunkByteLength(objects: (Sequence | number | Texture ...
method getBindPoseChunkByteLength (line 702) | getBindPoseChunkByteLength(): number {
FILE: src/parsers/mdlx/particleemitter.ts
type Flags (line 5) | const enum Flags {
class ParticleEmitter (line 13) | class ParticleEmitter extends GenericObject {
method constructor (line 22) | constructor() {
method readMdx (line 26) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 43) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 59) | readMdl(stream: TokenStream): void {
method writeMdl (line 103) | writeMdl(stream: TokenStream): void {
method getByteLength (line 153) | override getByteLength(): number {
FILE: src/parsers/mdlx/particleemitter2.ts
type Flags (line 5) | const enum Flags {
type FilterMode (line 14) | const enum FilterMode {
type HeadOrTail (line 22) | const enum HeadOrTail {
class ParticleEmitter2 (line 31) | class ParticleEmitter2 extends GenericObject {
method readMdx (line 56) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 93) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 129) | readMdl(stream: TokenStream): void {
method writeMdl (line 234) | writeMdl(stream: TokenStream): void {
method getByteLength (line 350) | override getByteLength(): number {
FILE: src/parsers/mdlx/particleemitterpopcorn.ts
type Flags (line 5) | const enum Flags {
class ParticleEmitterPopcorn (line 17) | class ParticleEmitterPopcorn extends GenericObject {
method readMdx (line 27) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 45) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 62) | readMdl(stream: TokenStream): void {
method writeMdl (line 104) | writeMdl(stream: TokenStream): void {
method getByteLength (line 158) | override getByteLength(): number {
FILE: src/parsers/mdlx/ribbonemitter.ts
class RibbonEmitter (line 8) | class RibbonEmitter extends GenericObject {
method constructor (line 21) | constructor() {
method readMdx (line 25) | override readMdx(stream: BinaryStream): void {
method writeMdx (line 46) | override writeMdx(stream: BinaryStream): void {
method readMdl (line 66) | readMdl(stream: TokenStream): void {
method writeMdl (line 108) | writeMdl(stream: TokenStream): void {
method getByteLength (line 149) | override getByteLength(): number {
FILE: src/parsers/mdlx/sequence.ts
class Sequence (line 8) | class Sequence {
method readMdx (line 17) | readMdx(stream: BinaryStream): void {
method writeMdx (line 27) | writeMdx(stream: BinaryStream): void {
method readMdl (line 37) | readMdl(stream: TokenStream): void {
method writeMdl (line 61) | writeMdl(stream: TokenStream): void {
FILE: src/parsers/mdlx/texture.ts
type WrapMode (line 4) | const enum WrapMode {
class Texture (line 14) | class Texture {
method readMdx (line 19) | readMdx(stream: BinaryStream): void {
method writeMdx (line 25) | writeMdx(stream: BinaryStream): void {
method readMdl (line 31) | readMdl(stream: TokenStream): void {
method writeMdl (line 47) | writeMdl(stream: TokenStream): void {
FILE: src/parsers/mdlx/textureanimation.ts
class TextureAnimation (line 8) | class TextureAnimation extends AnimatedObject {
method readMdx (line 9) | readMdx(stream: BinaryStream): void {
method writeMdx (line 15) | writeMdx(stream: BinaryStream): void {
method readMdl (line 20) | readMdl(stream: TokenStream): void {
method writeMdl (line 34) | writeMdl(stream: TokenStream): void {
method getByteLength (line 42) | override getByteLength(): number {
FILE: src/parsers/mdlx/tokenstream.ts
class TokenStream (line 4) | class TokenStream {
method constructor (line 11) | constructor(buffer?: string) {
method clear (line 18) | clear(): void {
method readToken (line 48) | readToken(): string | undefined {
method read (line 110) | read(): string {
method peek (line 123) | peek(): string {
method readInt (line 135) | readInt(): number {
method readFloat (line 142) | readFloat(): number {
method readVector (line 149) | readVector<T extends Uint8Array | Uint16Array | Uint32Array | Float32A...
method readVectorsBlock (line 168) | readVectorsBlock<T extends Uint16Array | Float32Array>(view: T, size: ...
method readColor (line 187) | readColor(view: Float32Array): Float32Array {
method readBlock (line 213) | * readBlock(): Generator<string> {
method writeLine (line 229) | writeLine(line: string): void {
method writeFlag (line 236) | writeFlag(flag: string): void {
method writeFlagAttrib (line 243) | writeFlagAttrib(name: string, flag: string): void {
method writeNumberAttrib (line 250) | writeNumberAttrib(name: string, value: number): void {
method writeStringAttrib (line 257) | writeStringAttrib(name: string, value: string): void {
method writeVectorAttrib (line 264) | writeVectorAttrib(name: string, value: Uint8Array | Uint32Array | Floa...
method writeColor (line 276) | writeColor(name: string, value: Float32Array): void {
method writeVector (line 287) | writeVector(value: Uint16Array | Float32Array): void {
method writeVectorArrayBlock (line 298) | writeVectorArrayBlock(name: string, view: Float32Array, size: number):...
method startBlock (line 315) | startBlock(name: string, ...headers: (string | number)[]): void {
method startObjectBlock (line 331) | startObjectBlock(header: string, name: string): void {
method endBlock (line 340) | endBlock(): void {
method endBlockComma (line 349) | endBlockComma(): void {
method indent (line 357) | indent(): void {
method unindent (line 364) | unindent(): void {
method floatDecimals (line 374) | floatDecimals(value: number): string {
method floatArrayDecimals (line 381) | floatArrayDecimals(value: Uint8Array | Uint16Array | Uint32Array | Flo...
FILE: src/parsers/mdlx/unknownchunk.ts
class UnknownChunk (line 6) | class UnknownChunk {
method constructor (line 10) | constructor(stream: BinaryStream, size: number, tag: string) {
method writeMdx (line 15) | writeMdx(stream: BinaryStream): void {
method getByteLength (line 21) | getByteLength(): number {
FILE: src/parsers/mpq/adpcm.ts
constant MAX_ADPCM_CHANNEL_COUNT (line 3) | const MAX_ADPCM_CHANNEL_COUNT = 2;
constant INITIAL_ADPCM_STEP_INDEX (line 4) | const INITIAL_ADPCM_STEP_INDEX = 0x2C;
function GetNextStepIndex (line 28) | function GetNextStepIndex(StepIndex: number, EncodedSample: number): num...
function UpdatePredictedSample (line 40) | function UpdatePredictedSample(PredictedSample: number, EncodedSample: n...
function DecodeSample (line 58) | function DecodeSample(PredictedSample: number, EncodedSample: number, St...
function DecompressADPCM (line 86) | function DecompressADPCM(pvInBuffer: Uint8Array, ChannelCount: number): ...
FILE: src/parsers/mpq/archive.ts
class MpqArchive (line 14) | class MpqArchive {
method constructor (line 23) | constructor() {
method load (line 37) | load(buffer: ArrayBuffer | Uint8Array, readonly = false): void {
method save (line 116) | save(): Uint8Array | null {
method saveMemory (line 215) | saveMemory(): number {
method removeBlock (line 255) | removeBlock(blockIndex: number): void {
method getFileNames (line 270) | getFileNames(): string[] {
method countUnresolved (line 285) | countUnresolved(): number {
method applyListfile (line 300) | applyListfile(listfile: Iterable<string>): void {
method set (line 312) | set(name: string, buffer: ArrayBuffer | Uint8Array | string): boolean {
method get (line 347) | get(name: string): MpqFile | null {
method has (line 375) | has(name: string): boolean {
method delete (line 387) | delete(name: string): boolean {
method rename (line 414) | rename(name: string, newName: string): boolean {
method resizeHashtable (line 441) | resizeHashtable(size: number): boolean {
FILE: src/parsers/mpq/block.ts
class Block (line 4) | class Block {
method load (line 10) | load(bytes: Uint32Array): void {
method save (line 17) | save(bytes: Uint32Array): void {
FILE: src/parsers/mpq/blocktable.ts
class BlockTable (line 8) | class BlockTable {
method constructor (line 12) | constructor(c: MpqCrypto) {
method add (line 17) | add(buffer: ArrayBuffer): MpqBlock {
method clear (line 27) | clear(): void {
method addEmpties (line 31) | addEmpties(howMany: number): void {
method load (line 37) | load(bytes: Uint8Array): void {
method save (line 53) | save(bytes: Uint8Array): void {
FILE: src/parsers/mpq/constants.ts
constant MAGIC (line 1) | const MAGIC = 0x1A51504D;
constant HASH_TABLE_KEY (line 2) | const HASH_TABLE_KEY = 0xC3AF3770;
constant HASH_TABLE_INDEX (line 3) | const HASH_TABLE_INDEX = 0;
constant HASH_NAME_A (line 4) | const HASH_NAME_A = 1;
constant HASH_NAME_B (line 5) | const HASH_NAME_B = 2;
constant HASH_FILE_KEY (line 6) | const HASH_FILE_KEY = 3;
constant HASH_ENTRY_DELETED (line 7) | const HASH_ENTRY_DELETED = 0xFFFFFFFE;
constant HASH_ENTRY_EMPTY (line 8) | const HASH_ENTRY_EMPTY = 0xFFFFFFFF;
constant BLOCK_TABLE_KEY (line 9) | const BLOCK_TABLE_KEY = 0xEC83B3A3;
constant FILE_IMPLODE (line 10) | const FILE_IMPLODE = 0x00000100;
constant FILE_COMPRESSED (line 11) | const FILE_COMPRESSED = 0x00000200;
constant FILE_ENCRYPTED (line 12) | const FILE_ENCRYPTED = 0x00010000;
constant FILE_OFFSET_ADJUSTED_KEY (line 13) | const FILE_OFFSET_ADJUSTED_KEY = 0x00020000;
constant FILE_PATCH_FILE (line 14) | const FILE_PATCH_FILE = 0x00100000;
constant FILE_SINGLE_UNIT (line 15) | const FILE_SINGLE_UNIT = 0x01000000;
constant FILE_DELETE_MARKER (line 16) | const FILE_DELETE_MARKER = 0x02000000;
constant FILE_SECTOR_CRC (line 17) | const FILE_SECTOR_CRC = 0x04000000;
constant FILE_EXISTS (line 18) | const FILE_EXISTS = 0x80000000;
constant COMPRESSION_HUFFMAN (line 19) | const COMPRESSION_HUFFMAN = 0x01;
constant COMPRESSION_DEFLATE (line 20) | const COMPRESSION_DEFLATE = 0x02;
constant COMPRESSION_IMPLODE (line 21) | const COMPRESSION_IMPLODE = 0x08;
constant COMPRESSION_BZIP2 (line 22) | const COMPRESSION_BZIP2 = 0x10;
constant COMPRESSION_ADPCM_MONO (line 23) | const COMPRESSION_ADPCM_MONO = 0x40;
constant COMPRESSION_ADPCM_STEREO (line 24) | const COMPRESSION_ADPCM_STEREO = 0x80;
FILE: src/parsers/mpq/crypto.ts
class MpqCrypto (line 11) | class MpqCrypto {
method constructor (line 14) | constructor() {
method hash (line 32) | hash(name: string, key: number): number {
method decryptBlock (line 50) | decryptBlock<T extends Uint8Array | Uint32Array>(data: T, key: number)...
method encryptBlock (line 82) | encryptBlock<T extends Uint8Array | Uint32Array>(data: T, key: number)...
method computeFileKey (line 117) | computeFileKey(name: string, block: MpqBlock): number {
FILE: src/parsers/mpq/explode.ts
constant CMP_BINARY (line 12) | const CMP_BINARY = 0;
constant CMP_ASCII (line 13) | const CMP_ASCII = 1;
class TDcmpStruct (line 15) | class TDcmpStruct {
method constructor (line 26) | constructor(in_buff: Uint8Array) {
constant PKDCL_OK (line 31) | const PKDCL_OK = 0;
constant PKDCL_STREAM_END (line 32) | const PKDCL_STREAM_END = 1;
function GenDecodeTabs (line 131) | function GenDecodeTabs(positions: Uint8Array, start_indexes: Uint8Array,...
function GenAscTabs (line 141) | function GenAscTabs(): void {
function WasteBits (line 198) | function WasteBits(pWork: TDcmpStruct, nBits: number): number {
function DecodeLit (line 219) | function DecodeLit(pWork: TDcmpStruct): number {
function DecodeDist (line 293) | function DecodeDist(pWork: TDcmpStruct, rep_length: number): number {
function Expand (line 320) | function Expand(pWork: TDcmpStruct): number {
function explode (line 348) | function explode(bytes: Uint8Array): Uint8Array {
FILE: src/parsers/mpq/file.ts
class MpqFile (line 15) | class MpqFile {
method constructor (line 25) | constructor(archive: MpqArchive, hash: MpqHash, block: MpqBlock, rawBu...
method bytes (line 49) | bytes(): Uint8Array {
method arrayBuffer (line 64) | arrayBuffer(): ArrayBuffer {
method text (line 73) | text(): string {
method set (line 82) | set(buffer: Uint8Array): boolean {
method delete (line 112) | delete(): boolean {
method rename (line 143) | rename(newName: string): boolean {
method decode (line 172) | decode(): void {
method decompressSector (line 277) | decompressSector(bytes: Uint8Array, decompressedSize: number): Uint8Ar...
method encode (line 331) | encode(): void {
method reEncrypt (line 410) | reEncrypt(offset: number): boolean {
method offsetChanged (line 471) | offsetChanged(offset: number): boolean {
FILE: src/parsers/mpq/hash.ts
class MpqHash (line 6) | class MpqHash {
method load (line 13) | load(bytes: Uint32Array): void {
method copy (line 23) | copy(hash: MpqHash): void {
method save (line 31) | save(bytes: Uint32Array): void {
method delete (line 38) | delete(): void {
FILE: src/parsers/mpq/hashtable.ts
class MpqHashTable (line 8) | class MpqHashTable {
method constructor (line 12) | constructor(c: MpqCrypto) {
method clear (line 20) | clear(): void {
method addEmpties (line 24) | addEmpties(howMany: number): void {
method getInsertionIndex (line 30) | getInsertionIndex(name: string): number {
method add (line 46) | add(name: string, blockIndex: number): MpqHash | undefined {
method load (line 64) | load(bytes: Uint8Array): void {
method save (line 80) | save(bytes: Uint8Array): void {
method get (line 97) | get(name: string): MpqHash | null {
FILE: src/parsers/mpq/isarchive.ts
function searchHeader (line 5) | function searchHeader(bytes: Uint8Array): number {
function isArchive (line 23) | function isArchive(bytes: Uint8Array): boolean {
FILE: src/parsers/slk/file.ts
class SlkFile (line 4) | class SlkFile {
method load (line 7) | load(buffer: string): void {
method save (line 47) | save(): string {
FILE: src/parsers/tga/image.ts
class TgaImage (line 7) | class TgaImage {
method load (line 12) | load(buffer: ArrayBuffer | Uint8Array): void {
FILE: src/parsers/tga/isformat.ts
function isTga (line 6) | function isTga(bytes: unknown): boolean {
FILE: src/parsers/w3x/doo/doodad.ts
class Doodad (line 7) | class Doodad {
method load (line 24) | load(stream: BinaryStream, version: number, buildVersion: number): void {
method save (line 53) | save(stream: BinaryStream, version: number, buildVersion: number): void {
method getByteLength (line 79) | getByteLength(version: number, buildVersion: number): number {
FILE: src/parsers/w3x/doo/file.ts
class War3MapDoo (line 8) | class War3MapDoo {
method load (line 15) | load(buffer: ArrayBuffer | Uint8Array, buildVersion: number): void {
method save (line 44) | save(buildVersion: number): Uint8Array {
method getByteLength (line 66) | getByteLength(buildVersion: number): number {
FILE: src/parsers/w3x/doo/randomitem.ts
class RandomItem (line 6) | class RandomItem {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/doo/randomitemset.ts
class RandomItemSet (line 7) | class RandomItemSet {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 20) | save(stream: BinaryStream): void {
method getByteLength (line 28) | getByteLength(): number {
FILE: src/parsers/w3x/doo/terraindoodad.ts
class TerrainDoodad (line 11) | class TerrainDoodad {
method load (line 16) | load(stream: BinaryStream, _version: number): void {
method save (line 22) | save(stream: BinaryStream, _version: number): void {
FILE: src/parsers/w3x/imp/file.ts
class War3MapImp (line 7) | class War3MapImp {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 29) | save(): Uint8Array {
method getByteLength (line 42) | getByteLength(): number {
method set (line 52) | set(path: string): boolean {
method has (line 67) | has(path: string): boolean {
method delete (line 71) | delete(path: string): boolean {
method rename (line 75) | rename(path: string, newPath: string): boolean {
FILE: src/parsers/w3x/imp/import.ts
class Import (line 7) | class Import {
method load (line 11) | load(stream: BinaryStream): void {
method save (line 16) | save(stream: BinaryStream): void {
method getByteLength (line 21) | getByteLength(): number {
FILE: src/parsers/w3x/map.ts
type War3MapModificationNames (line 13) | type War3MapModificationNames = 'w3a' | 'w3b' | 'w3d' | 'w3h' | 'w3q' | ...
type War3MapModifications (line 15) | interface War3MapModifications {
class War3Map (line 28) | class War3Map {
method load (line 43) | load(buffer: ArrayBuffer | Uint8Array, readonly = false): void {
method save (line 67) | save(): Uint8Array {
method getFileNames (line 102) | getFileNames(): string[] {
method getImportNames (line 109) | getImportNames(): string[] {
method setImportsFile (line 130) | setImportsFile(): boolean {
method import (line 152) | import(name: string, buffer: ArrayBuffer | string): boolean {
method set (line 169) | set(name: string, buffer: ArrayBuffer | string): boolean {
method get (line 180) | get(name: string): MpqFile | null {
method getScriptFile (line 187) | getScriptFile(): MpqFile | null {
method has (line 194) | has(name: string): boolean {
method delete (line 205) | delete(name: string): boolean {
method rename (line 219) | rename(name: string, newName: string): boolean {
method getMapInformation (line 234) | getMapInformation(): War3MapW3i {
method readImports (line 248) | readImports(): void {
method readTriggers (line 260) | readTriggers(triggerData: TriggerData): War3MapWtg | undefined {
method readCustomTextTriggers (line 281) | readCustomTextTriggers(): War3MapWct | undefined {
method readStringTable (line 302) | readStringTable(): War3MapWts | undefined {
method readModifications (line 323) | readModifications(): War3MapModifications {
FILE: src/parsers/w3x/mmp/file.ts
class War3MapMmp (line 7) | class War3MapMmp {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 25) | save(): Uint8Array {
method getByteLength (line 38) | getByteLength(): number {
FILE: src/parsers/w3x/mmp/minimapicon.ts
class MinimapIcon (line 6) | class MinimapIcon {
method load (line 14) | load(stream: BinaryStream): void {
method save (line 20) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/shd/file.ts
class War3MapShd (line 4) | class War3MapShd {
method load (line 7) | load(buffer: ArrayBuffer | Uint8Array, width: number, height: number):...
method save (line 11) | save(): Uint8Array {
method getByteLength (line 15) | getByteLength(): number {
FILE: src/parsers/w3x/unitsdoo/droppeditem.ts
class DroppedItem (line 6) | class DroppedItem {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/unitsdoo/droppeditemset.ts
class DroppedItemSet (line 7) | class DroppedItemSet {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 20) | save(stream: BinaryStream): void {
method getByteLength (line 28) | getByteLength(): number {
FILE: src/parsers/w3x/unitsdoo/file.ts
class War3MapUnitsDoo (line 7) | class War3MapUnitsDoo {
method load (line 12) | load(buffer: ArrayBuffer | Uint8Array, buildVersion: number): void {
method save (line 31) | save(buildVersion: number): Uint8Array {
method getByteLength (line 46) | getByteLength(buildVersion: number): number {
FILE: src/parsers/w3x/unitsdoo/inventoryitem.ts
class InventoryItem (line 6) | class InventoryItem {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/unitsdoo/modifiedability.ts
class ModifiedAbility (line 6) | class ModifiedAbility {
method load (line 11) | load(stream: BinaryStream): void {
method save (line 17) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/unitsdoo/randomunit.ts
class RandomUnit (line 6) | class RandomUnit {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/unitsdoo/unit.ts
class Unit (line 10) | class Unit {
method load (line 57) | load(stream: BinaryStream, version: number, subversion: number, buildV...
method save (line 135) | save(stream: BinaryStream, version: number, subversion: number, buildV...
method getByteLength (line 205) | getByteLength(version: number, subversion: number, buildVersion: numbe...
FILE: src/parsers/w3x/w3c/camera.ts
class Camera (line 7) | class Camera {
method load (line 30) | load(stream: BinaryStream, buildVersion: number): void {
method save (line 48) | save(stream: BinaryStream, buildVersion: number): void {
method getByteLength (line 66) | getByteLength(buildVersion: number): number {
FILE: src/parsers/w3x/w3c/file.ts
class War3MapW3c (line 7) | class War3MapW3c {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array, buildVersion: number): void {
method save (line 25) | save(buildVersion: number): Uint8Array {
method getByteLength (line 38) | getByteLength(buildVersion: number): number {
FILE: src/parsers/w3x/w3d/file.ts
class War3MapW3d (line 9) | class War3MapW3d {
method load (line 14) | load(bufferOrStream: ArrayBuffer | Uint8Array | BinaryStream): void {
method save (line 28) | save(): Uint8Array {
method getByteLength (line 38) | getByteLength(): number {
FILE: src/parsers/w3x/w3e/corner.ts
class Corner (line 6) | class Corner {
method load (line 20) | load(stream: BinaryStream): void {
method save (line 48) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/w3e/file.ts
class War3MapW3e (line 7) | class War3MapW3e {
method load (line 17) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 53) | save(): Uint8Array {
method getByteLength (line 84) | getByteLength(): number {
FILE: src/parsers/w3x/w3f/file.ts
class War3CampaignW3f (line 9) | class War3CampaignW3f {
method load (line 32) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 72) | save(): Uint8Array {
method getByteLength (line 109) | getByteLength(): number {
FILE: src/parsers/w3x/w3f/maporder.ts
class MapOrder (line 7) | class MapOrder {
method load (line 11) | load(stream: BinaryStream): void {
method save (line 16) | save(stream: BinaryStream): void {
method getByteLength (line 21) | getByteLength(): number {
FILE: src/parsers/w3x/w3f/maptitle.ts
class MapTitle (line 7) | class MapTitle {
method load (line 13) | load(stream: BinaryStream): void {
method save (line 20) | save(stream: BinaryStream): void {
method getByteLength (line 27) | getByteLength(): number {
FILE: src/parsers/w3x/w3i/file.ts
class War3MapW3i (line 13) | class War3MapW3i {
method load (line 58) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 174) | save(): Uint8Array {
method getByteLength (line 280) | getByteLength(): number {
method getBuildVersion (line 325) | getBuildVersion(): number {
FILE: src/parsers/w3x/w3i/force.ts
class Force (line 7) | class Force {
method load (line 12) | load(stream: BinaryStream): void {
method save (line 18) | save(stream: BinaryStream): void {
method getByteLength (line 24) | getByteLength(): number {
FILE: src/parsers/w3x/w3i/player.ts
class Player (line 7) | class Player {
method load (line 18) | load(stream: BinaryStream, version: number): void {
method save (line 32) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 46) | getByteLength(version: number): number {
FILE: src/parsers/w3x/w3i/randomitem.ts
class RandomItem (line 6) | class RandomItem {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/w3i/randomitemset.ts
class RandomItemSet (line 7) | class RandomItemSet {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 20) | save(stream: BinaryStream): void {
method getByteLength (line 28) | getByteLength(): number {
FILE: src/parsers/w3x/w3i/randomitemtable.ts
class RandomItemTable (line 8) | class RandomItemTable {
method load (line 13) | load(stream: BinaryStream): void {
method save (line 26) | save(stream: BinaryStream): void {
method getByteLength (line 36) | getByteLength(): number {
FILE: src/parsers/w3x/w3i/randomunit.ts
class RandomUnit (line 6) | class RandomUnit {
method load (line 10) | load(stream: BinaryStream, positions: number): void {
method save (line 18) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/w3i/randomunittable.ts
class RandomUnitTable (line 8) | class RandomUnitTable {
method load (line 15) | load(stream: BinaryStream): void {
method save (line 30) | save(stream: BinaryStream): void {
method getByteLength (line 42) | getByteLength(): number {
FILE: src/parsers/w3x/w3i/techavailabilitychange.ts
class TechAvailabilityChange (line 6) | class TechAvailabilityChange {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 15) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/w3i/upgradeavailabilitychange.ts
class UpgradeAvailabilityChange (line 6) | class UpgradeAvailabilityChange {
method load (line 12) | load(stream: BinaryStream): void {
method save (line 19) | save(stream: BinaryStream): void {
FILE: src/parsers/w3x/w3o/file.ts
class War3MapW3o (line 11) | class War3MapW3o {
method load (line 21) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 62) | save(): Uint8Array {
method getByteLength (line 119) | getByteLength(): number {
FILE: src/parsers/w3x/w3r/file.ts
class War3MapW3r (line 7) | class War3MapW3r {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 25) | save(): Uint8Array {
method getByteLength (line 38) | getByteLength(): number {
FILE: src/parsers/w3x/w3r/region.ts
class Region (line 7) | class Region {
method load (line 18) | load(stream: BinaryStream): void {
method save (line 30) | save(stream: BinaryStream): void {
method getByteLength (line 48) | getByteLength(): number {
FILE: src/parsers/w3x/w3s/file.ts
class War3MapW3s (line 7) | class War3MapW3s {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 25) | save(): Uint8Array {
method getByteLength (line 38) | getByteLength(): number {
FILE: src/parsers/w3x/w3s/sound.ts
class Sound (line 7) | class Sound {
method load (line 29) | load(stream: BinaryStream, version: number): void {
method save (line 59) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 89) | getByteLength(version: number): number {
FILE: src/parsers/w3x/w3u/file.ts
class War3MapW3u (line 9) | class War3MapW3u {
method load (line 14) | load(bufferOrStream: ArrayBuffer | Uint8Array | BinaryStream): void {
method save (line 28) | save(): Uint8Array {
method getByteLength (line 38) | getByteLength(): number {
FILE: src/parsers/w3x/w3u/modification.ts
class Modification (line 7) | class Modification {
method load (line 15) | load(stream: BinaryStream, useOptionalInts: boolean): void {
method save (line 37) | save(stream: BinaryStream, useOptionalInts: boolean): void {
method getByteLength (line 59) | getByteLength(useOptionalInts: boolean): number {
FILE: src/parsers/w3x/w3u/modificationtable.ts
class ModificationTable (line 7) | class ModificationTable {
method load (line 10) | load(
method save (line 24) | save(
method getByteLength (line 36) | getByteLength(useOptionalInts: boolean, formatVersion: number): number {
FILE: src/parsers/w3x/w3u/modifiedobject.ts
class ModifiedObject (line 7) | class ModifiedObject {
method load (line 14) | load(
method save (line 41) | save(
method getByteLength (line 74) | getByteLength(useOptionalInts: boolean, formatVersion: number): number {
FILE: src/parsers/w3x/wct/customtexttrigger.ts
class CustomTextTrigger (line 7) | class CustomTextTrigger {
method load (line 10) | load(stream: BinaryStream): void {
method save (line 19) | save(stream: BinaryStream): void {
method getByteLength (line 29) | getByteLength(): number {
FILE: src/parsers/w3x/wct/file.ts
class War3MapWct (line 8) | class War3MapWct {
method load (line 14) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 34) | save(): Uint8Array {
method getByteLength (line 54) | getByteLength(): number {
FILE: src/parsers/w3x/wpm/file.ts
class War3MapWpm (line 6) | class War3MapWpm {
method load (line 11) | load(buffer: ArrayBuffer | Uint8Array): void {
method save (line 23) | save(): Uint8Array {
method getByteLength (line 34) | getByteLength(): number {
FILE: src/parsers/w3x/wtg/eca.ts
class ECA (line 9) | class ECA {
method load (line 17) | load(stream: BinaryStream, version: number, isChildECA: boolean, trigg...
method save (line 71) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 94) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wtg/file.ts
class War3MapWtg (line 10) | class War3MapWtg {
method load (line 17) | load(buffer: ArrayBuffer | Uint8Array, triggerData: TriggerData): void {
method save (line 57) | save(): Uint8Array {
method getByteLength (line 84) | getByteLength(): number {
FILE: src/parsers/w3x/wtg/parameter.ts
class Parameter (line 9) | class Parameter {
method load (line 17) | load(stream: BinaryStream, version: number, triggerData: TriggerData):...
method save (line 59) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 83) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wtg/subparameters.ts
class SubParameters (line 9) | class SubParameters {
method load (line 15) | load(stream: BinaryStream, version: number, triggerData: TriggerData):...
method save (line 53) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 63) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wtg/trigger.ts
class Trigger (line 9) | class Trigger {
method load (line 20) | load(stream: BinaryStream, version: number, triggerData: TriggerData):...
method save (line 47) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 67) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wtg/triggercategory.ts
class TriggerCategory (line 9) | class TriggerCategory {
method load (line 14) | load(stream: BinaryStream, version: number): void {
method save (line 23) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 32) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wtg/triggerdata.ts
type StringObject (line 7) | type StringObject = {[key: string]: string };
type FunctionSignature (line 10) | type FunctionSignature = { args: string[], scriptName: string | null, re...
type FunctionObject (line 15) | type FunctionObject = {[key: string]: FunctionSignature };
class TriggerData (line 20) | class TriggerData {
method addTriggerData (line 28) | addTriggerData(buffer: string, isExternal: boolean): void {
method addTriggerTypes (line 74) | addTriggerTypes(types: StringObject, section: IniSection): void {
method addTriggerDataFunctions (line 83) | addTriggerDataFunctions(functions: FunctionObject, section: IniSection...
method addTriggerDataPresets (line 115) | addTriggerDataPresets(presets: StringObject, section: IniSection): void {
method addJassFunctions (line 126) | addJassFunctions(jass: string): void {
method getBaseType (line 181) | getBaseType(type: string): string {
method isBaseFunction (line 198) | isBaseFunction(type: number, name: string): boolean {
method getFunction (line 211) | getFunction(type: number, name: string): FunctionSignature {
method getFunctionType (line 227) | getFunctionType(name: string): number {
method getPreset (line 244) | getPreset(name: string): string {
method isCustomPreset (line 259) | isCustomPreset(name: string): boolean {
FILE: src/parsers/w3x/wtg/variable.ts
class Variable (line 7) | class Variable {
method load (line 16) | load(stream: BinaryStream, version: number): void {
method save (line 30) | save(stream: BinaryStream, version: number): void {
method getByteLength (line 44) | getByteLength(version: number): number {
FILE: src/parsers/w3x/wts/file.ts
class War3MapWts (line 9) | class War3MapWts {
method load (line 12) | load(buffer: string): void {
method save (line 50) | save(): string {
method getString (line 65) | getString(index: number | string): string | undefined {
method setString (line 82) | setString(index: number | string, value: string): void {
FILE: src/utils/blp/sanitytest.ts
function isMipmapFake (line 11) | function isMipmapFake(whichMipmap: number, mipmapOffsets: Uint32Array): ...
type SanityTestNode (line 23) | interface SanityTestNode {
type SanityTestResult (line 28) | interface SanityTestResult {
function sanityTest (line 36) | function sanityTest(texture: BlpImage): SanityTestResult {
FILE: src/utils/dds/sanitytest.ts
type SanityTestNode (line 4) | interface SanityTestNode {
type SanityTestResult (line 9) | interface SanityTestResult {
function sanityTest (line 17) | function sanityTest(texture: DdsImage): SanityTestResult {
FILE: src/utils/jass2/compilenatives.ts
function compileGetters (line 3) | function compileGetters(params: { type: string, name: string }[]): string {
function compileReturn (line 29) | function compileReturn(type: string): string {
function compileNative (line 59) | function compileNative(stream: TokenStream, isConstant: boolean): { name...
function compileBindings (line 99) | function compileBindings(names: string[]): string {
function compileNatives (line 107) | function compileNatives(jass: string): string {
FILE: src/utils/jass2/constanthandles.ts
type ConstantHandles (line 48) | interface ConstantHandles {
function constantHandles (line 90) | function constantHandles(): ConstantHandles {
FILE: src/utils/jass2/context.ts
class Context (line 22) | class Context extends EventEmitter {
method constructor (line 43) | constructor() {
method start (line 80) | start(): void {
method step (line 84) | step(): void {
method addHandle (line 138) | addHandle(handle: JassHandle): JassHandle {
method freeHandle (line 156) | freeHandle(handle: JassHandle): void {
method call (line 166) | call(name?: string | number): void {
method run (line 182) | run(code: string, isJass: boolean): void {
method open (line 202) | open(map: War3Map): void {
FILE: src/utils/jass2/jass2lua.ts
function jass2lua (line 3) | function jass2lua(jass: string): string {
FILE: src/utils/jass2/natives.ts
function ConvertRace (line 12) | function ConvertRace(C: Context, L: lua_State): number {
function ConvertAllianceType (line 23) | function ConvertAllianceType(C: Context, L: lua_State): number {
function ConvertRacePref (line 34) | function ConvertRacePref(C: Context, L: lua_State): number {
function ConvertIGameState (line 45) | function ConvertIGameState(C: Context, L: lua_State): number {
function ConvertFGameState (line 56) | function ConvertFGameState(C: Context, L: lua_State): number {
function ConvertPlayerState (line 67) | function ConvertPlayerState(C: Context, L: lua_State): number {
function ConvertPlayerScore (line 78) | function ConvertPlayerScore(C: Context, L: lua_State): number {
function ConvertPlayerGameResult (line 89) | function ConvertPlayerGameResult(C: Context, L: lua_State): number {
function ConvertUnitState (line 100) | function ConvertUnitState(C: Context, L: lua_State): number {
function ConvertAIDifficulty (line 111) | function ConvertAIDifficulty(C: Context, L: lua_State): number {
function ConvertGameEvent (line 122) | function ConvertGameEvent(C: Context, L: lua_State): number {
function ConvertPlayerEvent (line 133) | function ConvertPlayerEvent(C: Context, L: lua_State): number {
function ConvertPlayerUnitEvent (line 144) | function ConvertPlayerUnitEvent(C: Context, L: lua_State): number {
function ConvertWidgetEvent (line 155) | function ConvertWidgetEvent(C: Context, L: lua_State): number {
function ConvertDialogEvent (line 166) | function ConvertDialogEvent(C: Context, L: lua_State): number {
function ConvertUnitEvent (line 177) | function ConvertUnitEvent(C: Context, L: lua_State): number {
function ConvertLimitOp (line 188) | function ConvertLimitOp(C: Context, L: lua_State): number {
function ConvertUnitType (line 199) | function ConvertUnitType(C: Context, L: lua_State): number {
function ConvertGameSpeed (line 210) | function ConvertGameSpeed(C: Context, L: lua_State): number {
function ConvertPlacement (line 221) | function ConvertPlacement(C: Context, L: lua_State): number {
function ConvertStartLocPrio (line 232) | function ConvertStartLocPrio(C: Context, L: lua_State): number {
function ConvertGameDifficulty (line 243) | function ConvertGameDifficulty(C: Context, L: lua_State): number {
function ConvertGameType (line 254) | function ConvertGameType(C: Context, L: lua_State): number {
function ConvertMapFlag (line 265) | function ConvertMapFlag(C: Context, L: lua_State): number {
function ConvertMapVisibility (line 276) | function ConvertMapVisibility(C: Context, L: lua_State): number {
function ConvertMapSetting (line 289) | function ConvertMapSetting(C: Context, L: lua_State): number {
function ConvertMapDensity (line 302) | function ConvertMapDensity(C: Context, L: lua_State): number {
function ConvertMapControl (line 313) | function ConvertMapControl(C: Context, L: lua_State): number {
function ConvertPlayerColor (line 324) | function ConvertPlayerColor(C: Context, L: lua_State): number {
function ConvertPlayerSlotState (line 335) | function ConvertPlayerSlotState(C: Context, L: lua_State): number {
function ConvertVolumeGroup (line 346) | function ConvertVolumeGroup(C: Context, L: lua_State): number {
function ConvertCameraField (line 357) | function ConvertCameraField(C: Context, L: lua_State): number {
function ConvertBlendMode (line 368) | function ConvertBlendMode(C: Context, L: lua_State): number {
function ConvertRarityControl (line 379) | function ConvertRarityControl(C: Context, L: lua_State): number {
function ConvertTexMapFlags (line 390) | function ConvertTexMapFlags(C: Context, L: lua_State): number {
function ConvertFogState (line 401) | function ConvertFogState(C: Context, L: lua_State): number {
function ConvertEffectType (line 412) | function ConvertEffectType(C: Context, L: lua_State): number {
function ConvertVersion (line 423) | function ConvertVersion(C: Context, L: lua_State): number {
function ConvertItemType (line 434) | function ConvertItemType(C: Context, L: lua_State): number {
function ConvertAttackType (line 445) | function ConvertAttackType(C: Context, L: lua_State): number {
function ConvertDamageType (line 456) | function ConvertDamageType(C: Context, L: lua_State): number {
function ConvertWeaponType (line 467) | function ConvertWeaponType(C: Context, L: lua_State): number {
function ConvertSoundType (line 478) | function ConvertSoundType(C: Context, L: lua_State): number {
function ConvertPathingType (line 489) | function ConvertPathingType(C: Context, L: lua_State): number {
function ConvertMouseButtonType (line 500) | function ConvertMouseButtonType(C: Context, L: lua_State): number {
function ConvertAnimType (line 511) | function ConvertAnimType(C: Context, L: lua_State): number {
function ConvertSubAnimType (line 522) | function ConvertSubAnimType(C: Context, L: lua_State): number {
function OrderId (line 533) | function OrderId(C: Context, L: lua_State): number {
function OrderId2String (line 543) | function OrderId2String(C: Context, L: lua_State): number {
function UnitId (line 553) | function UnitId(C: Context, L: lua_State): number {
function UnitId2String (line 563) | function UnitId2String(C: Context, L: lua_State): number {
function AbilityId (line 573) | function AbilityId(C: Context, L: lua_State): number {
function AbilityId2String (line 583) | function AbilityId2String(C: Context, L: lua_State): number {
function GetObjectName (line 593) | function GetObjectName(C: Context, L: lua_State): number {
function GetBJMaxPlayers (line 603) | function GetBJMaxPlayers(C: Context, L: lua_State): number {
function GetBJPlayerNeutralVictim (line 612) | function GetBJPlayerNeutralVictim(C: Context, L: lua_State): number {
function GetBJPlayerNeutralExtra (line 621) | function GetBJPlayerNeutralExtra(C: Context, L: lua_State): number {
function GetBJMaxPlayerSlots (line 630) | function GetBJMaxPlayerSlots(C: Context, L: lua_State): number {
function GetPlayerNeutralPassive (line 639) | function GetPlayerNeutralPassive(C: Context, L: lua_State): number {
function GetPlayerNeutralAggressive (line 648) | function GetPlayerNeutralAggressive(C: Context, L: lua_State): number {
function Deg2Rad (line 657) | function Deg2Rad(C: Context, L: lua_State): number {
function Rad2Deg (line 668) | function Rad2Deg(C: Context, L: lua_State): number {
function Sin (line 679) | function Sin(C: Context, L: lua_State): number {
function Cos (line 690) | function Cos(C: Context, L: lua_State): number {
function Tan (line 701) | function Tan(C: Context, L: lua_State): number {
function Asin (line 712) | function Asin(C: Context, L: lua_State): number {
function Acos (line 723) | function Acos(C: Context, L: lua_State): number {
function Atan (line 734) | function Atan(C: Context, L: lua_State): number {
function Atan2 (line 745) | function Atan2(C: Context, L: lua_State): number {
function SquareRoot (line 757) | function SquareRoot(C: Context, L: lua_State): number {
function Pow (line 768) | function Pow(C: Context, L: lua_State): number {
function I2R (line 780) | function I2R(C: Context, L: lua_State): number {
function R2I (line 791) | function R2I(C: Context, L: lua_State): number {
function I2S (line 802) | function I2S(C: Context, L: lua_State): number {
function R2S (line 812) | function R2S(C: Context, L: lua_State): number {
function R2SW (line 822) | function R2SW(C: Context, L: lua_State): number {
function S2I (line 834) | function S2I(C: Context, L: lua_State): number {
function S2R (line 844) | function S2R(C: Context, L: lua_State): number {
function GetHandleId (line 854) | function GetHandleId(C: Context, L: lua_State): number {
function SubString (line 865) | function SubString(C: Context, L: lua_State): number {
function StringLength (line 877) | function StringLength(C: Context, L: lua_State): number {
function StringCase (line 887) | function StringCase(C: Context, L: lua_State): number {
function StringHash (line 898) | function StringHash(C: Context, L: lua_State): number {
function GetLocalizedString (line 908) | function GetLocalizedString(C: Context, L: lua_State): number {
function GetLocalizedHotkey (line 918) | function GetLocalizedHotkey(C: Context, L: lua_State): number {
function SetMapName (line 928) | function SetMapName(C: Context, L: lua_State): number {
function SetMapDescription (line 937) | function SetMapDescription(C: Context, L: lua_State): number {
function SetTeams (line 946) | function SetTeams(C: Context, L: lua_State): number {
function SetPlayers (line 955) | function SetPlayers(C: Context, L: lua_State): number {
function DefineStartLocation (line 964) | function DefineStartLocation(C: Context, L: lua_State): number {
function DefineStartLocationLoc (line 977) | function DefineStartLocationLoc(C: Context, L: lua_State): number {
function SetStartLocPrioCount (line 987) | function SetStartLocPrioCount(C: Context, L: lua_State): number {
function SetStartLocPrio (line 997) | function SetStartLocPrio(C: Context, L: lua_State): number {
function GetStartLocPrioSlot (line 1009) | function GetStartLocPrioSlot(C: Context, L: lua_State): number {
function GetStartLocPrio (line 1020) | function GetStartLocPrio(C: Context, L: lua_State): number {
function SetGameTypeSupported (line 1031) | function SetGameTypeSupported(C: Context, L: lua_State): number {
function SetMapFlag (line 1041) | function SetMapFlag(C: Context, L: lua_State): number {
function SetGamePlacement (line 1051) | function SetGamePlacement(C: Context, L: lua_State): number {
function SetGameSpeed (line 1060) | function SetGameSpeed(C: Context, L: lua_State): number {
function SetGameDifficulty (line 1069) | function SetGameDifficulty(C: Context, L: lua_State): number {
function SetResourceDensity (line 1078) | function SetResourceDensity(C: Context, L: lua_State): number {
function SetCreatureDensity (line 1087) | function SetCreatureDensity(C: Context, L: lua_State): number {
function GetTeams (line 1096) | function GetTeams(C: Context, L: lua_State): number {
function GetPlayers (line 1106) | function GetPlayers(C: Context, L: lua_State): number {
function IsGameTypeSupported (line 1116) | function IsGameTypeSupported(C: Context, L: lua_State): number {
function GetGameTypeSelected (line 1126) | function GetGameTypeSelected(C: Context, L: lua_State): number {
function IsMapFlagSet (line 1136) | function IsMapFlagSet(C: Context, L: lua_State): number {
function GetGamePlacement (line 1146) | function GetGamePlacement(C: Context, L: lua_State): number {
function GetGameSpeed (line 1156) | function GetGameSpeed(C: Context, L: lua_State): number {
function GetGameDifficulty (line 1166) | function GetGameDifficulty(C: Context, L: lua_State): number {
function GetResourceDensity (line 1176) | function GetResourceDensity(C: Context, L: lua_State): number {
function GetCreatureDensity (line 1186) | function GetCreatureDensity(C: Context, L: lua_State): number {
function GetStartLocationX (line 1196) | function GetStartLocationX(C: Context, L: lua_State): number {
function GetStartLocationY (line 1206) | function GetStartLocationY(C: Context, L: lua_State): number {
function GetStartLocationLoc (line 1216) | function GetStartLocationLoc(C: Context, L: lua_State): number {
function SetPlayerTeam (line 1226) | function SetPlayerTeam(C: Context, L: lua_State): number {
function SetPlayerStartLocation (line 1236) | function SetPlayerStartLocation(C: Context, L: lua_State): number {
function ForcePlayerStartLocation (line 1248) | function ForcePlayerStartLocation(C: Context, L: lua_State): number {
function SetPlayerColor (line 1258) | function SetPlayerColor(C: Context, L: lua_State): number {
function SetPlayerAlliance (line 1270) | function SetPlayerAlliance(C: Context, L: lua_State): number {
function SetPlayerTaxRate (line 1282) | function SetPlayerTaxRate(C: Context, L: lua_State): number {
function SetPlayerRacePreference (line 1294) | function SetPlayerRacePreference(C: Context, L: lua_State): number {
function SetPlayerRaceSelectable (line 1304) | function SetPlayerRaceSelectable(C: Context, L: lua_State): number {
function SetPlayerController (line 1316) | function SetPlayerController(C: Context, L: lua_State): number {
function SetPlayerName (line 1328) | function SetPlayerName(C: Context, L: lua_State): number {
function SetPlayerOnScoreScreen (line 1340) | function SetPlayerOnScoreScreen(C: Context, L: lua_State): number {
function GetPlayerTeam (line 1350) | function GetPlayerTeam(C: Context, L: lua_State): number {
function GetPlayerStartLocation (line 1360) | function GetPlayerStartLocation(C: Context, L: lua_State): number {
function GetPlayerColor (line 1371) | function GetPlayerColor(C: Context, L: lua_State): number {
function GetPlayerSelectable (line 1382) | function GetPlayerSelectable(C: Context, L: lua_State): number {
function GetPlayerController (line 1392) | function GetPlayerController(C: Context, L: lua_State): number {
function GetPlayerSlotState (line 1403) | function GetPlayerSlotState(C: Context, L: lua_State): number {
function GetPlayerTaxRate (line 1413) | function GetPlayerTaxRate(C: Context, L: lua_State): number {
function IsPlayerRacePrefSet (line 1425) | function IsPlayerRacePrefSet(C: Context, L: lua_State): number {
function GetPlayerName (line 1436) | function GetPlayerName(C: Context, L: lua_State): number {
function CreateTimer (line 1447) | function CreateTimer(C: Context, L: lua_State): number {
function DestroyTimer (line 1456) | function DestroyTimer(C: Context, L: lua_State): number {
function TimerStart (line 1470) | function TimerStart(C: Context, L: lua_State): number {
function TimerGetElapsed (line 1489) | function TimerGetElapsed(C: Context, L: lua_State): number {
function TimerGetRemaining (line 1500) | function TimerGetRemaining(C: Context, L: lua_State): number {
function TimerGetTimeout (line 1511) | function TimerGetTimeout(C: Context, L: lua_State): number {
function PauseTimer (line 1522) | function PauseTimer(C: Context, L: lua_State): number {
function ResumeTimer (line 1533) | function ResumeTimer(C: Context, L: lua_State): number {
function GetExpiredTimer (line 1544) | function GetExpiredTimer(C: Context, L: lua_State): number {
function CreateGroup (line 1559) | function CreateGroup(C: Context, L: lua_State): number {
function DestroyGroup (line 1568) | function DestroyGroup(C: Context, L: lua_State): number {
function GroupAddUnit (line 1579) | function GroupAddUnit(C: Context, L: lua_State): number {
function GroupRemoveUnit (line 1591) | function GroupRemoveUnit(C: Context, L: lua_State): number {
function GroupClear (line 1603) | function GroupClear(C: Context, L: lua_State): number {
function GroupEnumUnitsOfType (line 1614) | function GroupEnumUnitsOfType(C: Context, L: lua_State): number {
function GroupEnumUnitsOfPlayer (line 1625) | function GroupEnumUnitsOfPlayer(C: Context, L: lua_State): number {
function GroupEnumUnitsOfTypeCounted (line 1636) | function GroupEnumUnitsOfTypeCounted(C: Context, L: lua_State): number {
function GroupEnumUnitsInRect (line 1648) | function GroupEnumUnitsInRect(C: Context, L: lua_State): number {
function GroupEnumUnitsInRectCounted (line 1659) | function GroupEnumUnitsInRectCounted(C: Context, L: lua_State): number {
function GroupEnumUnitsInRange (line 1671) | function GroupEnumUnitsInRange(C: Context, L: lua_State): number {
function GroupEnumUnitsInRangeOfLoc (line 1684) | function GroupEnumUnitsInRangeOfLoc(C: Context, L: lua_State): number {
function GroupEnumUnitsInRangeCounted (line 1696) | function GroupEnumUnitsInRangeCounted(C: Context, L: lua_State): number {
function GroupEnumUnitsInRangeOfLocCounted (line 1710) | function GroupEnumUnitsInRangeOfLocCounted(C: Context, L: lua_State): nu...
function GroupEnumUnitsSelected (line 1723) | function GroupEnumUnitsSelected(C: Context, L: lua_State): number {
function GroupImmediateOrder (line 1734) | function GroupImmediateOrder(C: Context, L: lua_State): number {
function GroupImmediateOrderById (line 1745) | function GroupImmediateOrderById(C: Context, L: lua_State): number {
function GroupPointOrder (line 1756) | function GroupPointOrder(C: Context, L: lua_State): number {
function GroupPointOrderLoc (line 1769) | function GroupPointOrderLoc(C: Context, L: lua_State): number {
function GroupPointOrderById (line 1781) | function GroupPointOrderById(C: Context, L: lua_State): number {
function GroupPointOrderByIdLoc (line 1794) | function GroupPointOrderByIdLoc(C: Context, L: lua_State): number {
function GroupTargetOrder (line 1806) | function GroupTargetOrder(C: Context, L: lua_State): number {
function GroupTargetOrderById (line 1818) | function GroupTargetOrderById(C: Context, L: lua_State): number {
function ForGroup (line 1830) | function ForGroup(C: Context, L: lua_State): number {
function FirstOfGroup (line 1850) | function FirstOfGroup(C: Context, L: lua_State): number {
function CreateForce (line 1860) | function CreateForce(C: Context, L: lua_State): number {
function DestroyForce (line 1869) | function DestroyForce(C: Context, L: lua_State): number {
function ForceAddPlayer (line 1880) | function ForceAddPlayer(C: Context, L: lua_State): number {
function ForceRemovePlayer (line 1892) | function ForceRemovePlayer(C: Context, L: lua_State): number {
function ForceClear (line 1904) | function ForceClear(C: Context, L: lua_State): number {
function ForceEnumPlayers (line 1915) | function ForceEnumPlayers(C: Context, L: lua_State): number {
function ForceEnumPlayersCounted (line 1925) | function ForceEnumPlayersCounted(C: Context, L: lua_State): number {
function ForceEnumAllies (line 1936) | function ForceEnumAllies(C: Context, L: lua_State): number {
function ForceEnumEnemies (line 1947) | function ForceEnumEnemies(C: Context, L: lua_State): number {
function ForForce (line 1958) | function ForForce(C: Context, L: lua_State): number {
function Rect (line 1978) | function Rect(C: Context, L: lua_State): number {
function RectFromLoc (line 1991) | function RectFromLoc(C: Context, L: lua_State): number {
function RemoveRect (line 2002) | function RemoveRect(C: Context, L: lua_State): number {
function SetRect (line 2011) | function SetRect(C: Context, L: lua_State): number {
function SetRectFromLoc (line 2024) | function SetRectFromLoc(C: Context, L: lua_State): number {
function MoveRectTo (line 2035) | function MoveRectTo(C: Context, L: lua_State): number {
function MoveRectToLoc (line 2046) | function MoveRectToLoc(C: Context, L: lua_State): number {
function GetRectCenterX (line 2056) | function GetRectCenterX(C: Context, L: lua_State): number {
function GetRectCenterY (line 2066) | function GetRectCenterY(C: Context, L: lua_State): number {
function GetRectMinX (line 2076) | function GetRectMinX(C: Context, L: lua_State): number {
function GetRectMinY (line 2086) | function GetRectMinY(C: Context, L: lua_State): number {
function GetRectMaxX (line 2096) | function GetRectMaxX(C: Context, L: lua_State): number {
function GetRectMaxY (line 2106) | function GetRectMaxY(C: Context, L: lua_State): number {
function CreateRegion (line 2116) | function CreateRegion(C: Context, L: lua_State): number {
function RemoveRegion (line 2126) | function RemoveRegion(C: Context, L: lua_State): number {
function RegionAddRect (line 2135) | function RegionAddRect(C: Context, L: lua_State): number {
function RegionClearRect (line 2145) | function RegionClearRect(C: Context, L: lua_State): number {
function RegionAddCell (line 2155) | function RegionAddCell(C: Context, L: lua_State): number {
function RegionAddCellAtLoc (line 2166) | function RegionAddCellAtLoc(C: Context, L: lua_State): number {
function RegionClearCell (line 2176) | function RegionClearCell(C: Context, L: lua_State): number {
function RegionClearCellAtLoc (line 2187) | function RegionClearCellAtLoc(C: Context, L: lua_State): number {
function Location (line 2197) | function Location(C: Context, L: lua_State): number {
function RemoveLocation (line 2208) | function RemoveLocation(C: Context, L: lua_State): number {
function MoveLocation (line 2217) | function MoveLocation(C: Context, L: lua_State): number {
function GetLocationX (line 2228) | function GetLocationX(C: Context, L: lua_State): number {
function GetLocationY (line 2238) | function GetLocationY(C: Context, L: lua_State): number {
function GetLocationZ (line 2248) | function GetLocationZ(C: Context, L: lua_State): number {
function IsUnitInRegion (line 2258) | function IsUnitInRegion(C: Context, L: lua_State): number {
function IsPointInRegion (line 2269) | function IsPointInRegion(C: Context, L: lua_State): number {
function IsLocationInRegion (line 2281) | function IsLocationInRegion(C: Context, L: lua_State): number {
function GetWorldBounds (line 2292) | function GetWorldBounds(C: Context, L: lua_State): number {
function CreateTrigger (line 2302) | function CreateTrigger(C: Context, L: lua_State): number {
function DestroyTrigger (line 2311) | function DestroyTrigger(C: Context, L: lua_State): number {
function ResetTrigger (line 2325) | function ResetTrigger(C: Context, L: lua_State): number {
function EnableTrigger (line 2334) | function EnableTrigger(C: Context, L: lua_State): number {
function DisableTrigger (line 2343) | function DisableTrigger(C: Context, L: lua_State): number {
function IsTriggerEnabled (line 2352) | function IsTriggerEnabled(C: Context, L: lua_State): number {
function TriggerWaitOnSleeps (line 2362) | function TriggerWaitOnSleeps(C: Context, L: lua_State): number {
function IsTriggerWaitOnSleeps (line 2372) | function IsTriggerWaitOnSleeps(C: Context, L: lua_State): number {
function GetFilterUnit (line 2382) | function GetFilterUnit(C: Context, L: lua_State): number {
function GetEnumUnit (line 2391) | function GetEnumUnit(C: Context, L: lua_State): number {
function GetFilterDestructable (line 2400) | function GetFilterDestructable(C: Context, L: lua_State): number {
function GetEnumDestructable (line 2410) | function GetEnumDestructable(C: Context, L: lua_State): number {
function GetFilterItem (line 2420) | function GetFilterItem(C: Context, L: lua_State): number {
function GetEnumItem (line 2430) | function GetEnumItem(C: Context, L: lua_State): number {
function GetFilterPlayer (line 2440) | function GetFilterPlayer(C: Context, L: lua_State): number {
function GetEnumPlayer (line 2450) | function GetEnumPlayer(C: Context, L: lua_State): number {
function GetTriggeringTrigger (line 2459) | function GetTriggeringTrigger(C: Context, L: lua_State): number {
function GetTriggerEventId (line 2474) | function GetTriggerEventId(C: Context, L: lua_State): number {
function GetTriggerEvalCount (line 2484) | function GetTriggerEvalCount(C: Context, L: lua_State): number {
function GetTriggerExecCount (line 2494) | function GetTriggerExecCount(C: Context, L: lua_State): number {
function ExecuteFunc (line 2504) | function ExecuteFunc(C: Context, L: lua_State): number {
function And (line 2513) | function And(C: Context, L: lua_State): number {
function Or (line 2524) | function Or(C: Context, L: lua_State): number {
function Not (line 2535) | function Not(C: Context, L: lua_State): number {
function Condition (line 2545) | function Condition(C: Context, L: lua_State): number {
function DestroyCondition (line 2555) | function DestroyCondition(C: Context, L: lua_State): number {
function Filter (line 2564) | function Filter(C: Context, L: lua_State): number {
function DestroyFilter (line 2574) | function DestroyFilter(C: Context, L: lua_State): number {
function DestroyBoolExpr (line 2583) | function DestroyBoolExpr(C: Context, L: lua_State): number {
function TriggerRegisterVariableEvent (line 2592) | function TriggerRegisterVariableEvent(C: Context, L: lua_State): number {
function TriggerRegisterTimerEvent (line 2605) | function TriggerRegisterTimerEvent(C: Context, L: lua_State): number {
function TriggerRegisterTimerExpireEvent (line 2617) | function TriggerRegisterTimerExpireEvent(C: Context, L: lua_State): numb...
function TriggerRegisterGameStateEvent (line 2628) | function TriggerRegisterGameStateEvent(C: Context, L: lua_State): number {
function TriggerRegisterDialogEvent (line 2641) | function TriggerRegisterDialogEvent(C: Context, L: lua_State): number {
function TriggerRegisterDialogButtonEvent (line 2652) | function TriggerRegisterDialogButtonEvent(C: Context, L: lua_State): num...
function GetEventGameState (line 2663) | function GetEventGameState(C: Context, L: lua_State): number {
function TriggerRegisterGameEvent (line 2673) | function TriggerRegisterGameEvent(C: Context, L: lua_State): number {
function GetWinningPlayer (line 2684) | function GetWinningPlayer(C: Context, L: lua_State): number {
function TriggerRegisterEnterRegion (line 2694) | function TriggerRegisterEnterRegion(C: Context, L: lua_State): number {
function GetTriggeringRegion (line 2706) | function GetTriggeringRegion(C: Context, L: lua_State): number {
function GetEnteringUnit (line 2716) | function GetEnteringUnit(C: Context, L: lua_State): number {
function TriggerRegisterLeaveRegion (line 2726) | function TriggerRegisterLeaveRegion(C: Context, L: lua_State): number {
function GetLeavingUnit (line 2738) | function GetLeavingUnit(C: Context, L: lua_State): number {
function TriggerRegisterTrackableHitEvent (line 2748) | function TriggerRegisterTrackableHitEvent(C: Context, L: lua_State): num...
function TriggerRegisterTrackableTrackEvent (line 2759) | function TriggerRegisterTrackableTrackEvent(C: Context, L: lua_State): n...
function GetTriggeringTrackable (line 2770) | function GetTriggeringTrackable(C: Context, L: lua_State): number {
function GetClickedButton (line 2780) | function GetClickedButton(C: Context, L: lua_State): number {
function GetClickedDialog (line 2790) | function GetClickedDialog(C: Context, L: lua_State): number {
function GetTournamentFinishSoonTimeRemaining (line 2800) | function GetTournamentFinishSoonTimeRemaining(C: Context, L: lua_State):...
function GetTournamentFinishNowRule (line 2810) | function GetTournamentFinishNowRule(C: Context, L: lua_State): number {
function GetTournamentFinishNowPlayer (line 2820) | function GetTournamentFinishNowPlayer(C: Context, L: lua_State): number {
function GetTournamentScore (line 2830) | function GetTournamentScore(C: Context, L: lua_State): number {
function GetSaveBasicFilename (line 2840) | function GetSaveBasicFilename(C: Context, L: lua_State): number {
function TriggerRegisterPlayerEvent (line 2850) | function TriggerRegisterPlayerEvent(C: Context, L: lua_State): number {
function GetTriggerPlayer (line 2862) | function GetTriggerPlayer(C: Context, L: lua_State): number {
function TriggerRegisterPlayerUnitEvent (line 2872) | function TriggerRegisterPlayerUnitEvent(C: Context, L: lua_State): number {
function GetLevelingUnit (line 2885) | function GetLevelingUnit(C: Context, L: lua_State): number {
function GetLearningUnit (line 2895) | function GetLearningUnit(C: Context, L: lua_State): number {
function GetLearnedSkill (line 2905) | function GetLearnedSkill(C: Context, L: lua_State): number {
function GetLearnedSkillLevel (line 2915) | function GetLearnedSkillLevel(C: Context, L: lua_State): number {
function GetRevivableUnit (line 2925) | function GetRevivableUnit(C: Context, L: lua_State): number {
function GetRevivingUnit (line 2935) | function GetRevivingUnit(C: Context, L: lua_State): number {
function GetAttacker (line 2945) | function GetAttacker(C: Context, L: lua_State): number {
function GetRescuer (line 2955) | function GetRescuer(C: Context, L: lua_State): number {
function GetDyingUnit (line 2965) | function GetDyingUnit(C: Context, L: lua_State): number {
function GetKillingUnit (line 2975) | function GetKillingUnit(C: Context, L: lua_State): number {
function GetDecayingUnit (line 2985) | function GetDecayingUnit(C: Context, L: lua_State): number {
function GetConstructingStructure (line 2995) | function GetConstructingStructure(C: Context, L: lua_State): number {
function GetCancelledStructure (line 3005) | function GetCancelledStructure(C: Context, L: lua_State): number {
function GetConstructedStructure (line 3015) | function GetConstructedStructure(C: Context, L: lua_State): number {
function GetResearchingUnit (line 3025) | function GetResearchingUnit(C: Context, L: lua_State): number {
function GetResearched (line 3035) | function GetResearched(C: Context, L: lua_State): number {
function GetTrainedUnitType (line 3045) | function GetTrainedUnitType(C: Context, L: lua_State): number {
function GetTrainedUnit (line 3055) | function GetTrainedUnit(C: Context, L: lua_State): number {
function GetDetectedUnit (line 3065) | function GetDetectedUnit(C: Context, L: lua_State): number {
function GetSummoningUnit (line 3075) | function GetSummoningUnit(C: Context, L: lua_State): number {
function GetSummonedUnit (line 3085) | function GetSummonedUnit(C: Context, L: lua_State): number {
function GetTransportUnit (line 3095) | function GetTransportUnit(C: Context, L: lua_State): number {
function GetLoadedUnit (line 3105) | function GetLoadedUnit(C: Context, L: lua_State): number {
function GetSellingUnit (line 3115) | function GetSellingUnit(C: Context, L: lua_State): number {
function GetSoldUnit (line 3125) | function GetSoldUnit(C: Context, L: lua_State): number {
function GetBuyingUnit (line 3135) | function GetBuyingUnit(C: Context, L: lua_State): number {
function GetSoldItem (line 3145) | function GetSoldItem(C: Context, L: lua_State): number {
function GetChangingUnit (line 3155) | function GetChangingUnit(C: Context, L: lua_State): number {
function GetChangingUnitPrevOwner (line 3165) | function GetChangingUnitPrevOwner(C: Context, L: lua_State): number {
function GetManipulatingUnit (line 3175) | function GetManipulatingUnit(C: Context, L: lua_State): number {
function GetManipulatedItem (line 3185) | function GetManipulatedItem(C: Context, L: lua_State): number {
function GetOrderedUnit (line 3195) | function GetOrderedUnit(C: Context, L: lua_State): number {
function GetIssuedOrderId (line 3205) | function GetIssuedOrderId(C: Context, L: lua_State): number {
function GetOrderPointX (line 3215) | function GetOrderPointX(C: Context, L: lua_State): number {
function GetOrderPointY (line 3225) | function GetOrderPointY(C: Context, L: lua_State): number {
function GetOrderPointLoc (line 3235) | function GetOrderPointLoc(C: Context, L: lua_State): number {
function GetOrderTarget (line 3245) | function GetOrderTarget(C: Context, L: lua_State): number {
function GetOrderTargetDestructable (line 3255) | function GetOrderTargetDestructable(C: Context, L: lua_State): number {
function GetOrderTargetItem (line 3265) | function GetOrderTargetItem(C: Context, L: lua_State): number {
function GetOrderTargetUnit (line 3275) | function GetOrderTargetUnit(C: Context, L: lua_State): number {
function GetSpellAbilityUnit (line 3285) | function GetSpellAbilityUnit(C: Context, L: lua_State): number {
function GetSpellAbilityId (line 3295) | function GetSpellAbilityId(C: Context, L: lua_State): number {
function GetSpellAbility (line 3305) | function GetSpellAbility(C: Context, L: lua_State): number {
function GetSpellTargetLoc (line 3315) | function GetSpellTargetLoc(C: Context, L: lua_State): number {
function GetSpellTargetX (line 3325) | function GetSpellTargetX(C: Context, L: lua_State): number {
function GetSpellTargetY (line 3335) | function GetSpellTargetY(C: Context, L: lua_State): number {
function GetSpellTargetDestructable (line 3345) | function GetSpellTargetDestructable(C: Context, L: lua_State): number {
function GetSpellTargetItem (line 3355) | function GetSpellTargetItem(C: Context, L: lua_State): number {
function GetSpellTargetUnit (line 3365) | function GetSpellTargetUnit(C: Context, L: lua_State): number {
function TriggerRegisterPlayerAllianceChange (line 3375) | function TriggerRegisterPlayerAllianceChange(C: Context, L: lua_State): ...
function TriggerRegisterPlayerStateEvent (line 3387) | function TriggerRegisterPlayerStateEvent(C: Context, L: lua_State): numb...
function GetEventPlayerState (line 3401) | function GetEventPlayerState(C: Context, L: lua_State): number {
function TriggerRegisterPlayerChatEvent (line 3411) | function TriggerRegisterPlayerChatEvent(C: Context, L: lua_State): number {
function GetEventPlayerChatString (line 3424) | function GetEventPlayerChatString(C: Context, L: lua_State): number {
function GetEventPlayerChatStringMatched (line 3434) | function GetEventPlayerChatStringMatched(C: Context, L: lua_State): numb...
function TriggerRegisterDeathEvent (line 3444) | function TriggerRegisterDeathEvent(C: Context, L: lua_State): number {
function GetTriggerUnit (line 3455) | function GetTriggerUnit(C: Context, L: lua_State): number {
function TriggerRegisterUnitStateEvent (line 3470) | function TriggerRegisterUnitStateEvent(C: Context, L: lua_State): number {
function GetEventUnitState (line 3484) | function GetEventUnitState(C: Context, L: lua_State): number {
function TriggerRegisterUnitEvent (line 3494) | function TriggerRegisterUnitEvent(C: Context, L: lua_State): number {
function GetEventDamage (line 3506) | function GetEventDamage(C: Context, L: lua_State): number {
function GetEventDamageSource (line 3516) | function GetEventDamageSource(C: Context, L: lua_State): number {
function GetEventDetectingPlayer (line 3526) | function GetEventDetectingPlayer(C: Context, L: lua_State): number {
function TriggerRegisterFilterUnitEvent (line 3536) | function TriggerRegisterFilterUnitEvent(C: Context, L: lua_State): number {
function GetEventTargetUnit (line 3549) | function GetEventTargetUnit(C: Context, L: lua_State): number {
function TriggerRegisterUnitInRange (line 3559) | function TriggerRegisterUnitInRange(C: Context, L: lua_State): number {
function TriggerAddCondition (line 3572) | function TriggerAddCondition(C: Context, L: lua_State): number {
function TriggerRemoveCondition (line 3583) | function TriggerRemoveCondition(C: Context, L: lua_State): number {
function TriggerClearConditions (line 3593) | function TriggerClearConditions(C: Context, L: lua_State): number {
function TriggerAddAction (line 3602) | function TriggerAddAction(C: Context, L: lua_State): number {
function TriggerRemoveAction (line 3613) | function TriggerRemoveAction(C: Context, L: lua_State): number {
function TriggerClearActions (line 3623) | function TriggerClearActions(C: Context, L: lua_State): number {
function TriggerSleepAction (line 3632) | function TriggerSleepAction(C: Context, L: lua_State): number {
function TriggerWaitForSound (line 3645) | function TriggerWaitForSound(C: Context, L: lua_State): number {
function TriggerEvaluate (line 3655) | function TriggerEvaluate(C: Context, L: lua_State): number {
function TriggerExecute (line 3665) | function TriggerExecute(C: Context, L: lua_State): number {
function TriggerExecuteWait (line 3674) | function TriggerExecuteWait(C: Context, L: lua_State): number {
function TriggerSyncStart (line 3683) | function TriggerSyncStart(_C: Context, _L: lua_State): number {
function TriggerSyncReady (line 3692) | function TriggerSyncReady(_C: Context, _L: lua_State): number {
function GetWidgetLife (line 3701) | function GetWidgetLife(C: Context, L: lua_State): number {
function SetWidgetLife (line 3711) | function SetWidgetLife(C: Context, L: lua_State): number {
function GetWidgetX (line 3721) | function GetWidgetX(C: Context, L: lua_State): number {
function GetWidgetY (line 3731) | function GetWidgetY(C: Context, L: lua_State): number {
function GetTriggerWidget (line 3741) | function GetTriggerWidget(C: Context, L: lua_State): number {
function CreateDestructable (line 3751) | function CreateDestructable(C: Context, L: lua_State): number {
function CreateDestructableZ (line 3766) | function CreateDestructableZ(C: Context, L: lua_State): number {
function CreateDeadDestructable (line 3782) | function CreateDeadDestructable(C: Context, L: lua_State): number {
function CreateDeadDestructableZ (line 3797) | function CreateDeadDestructableZ(C: Context, L: lua_State): number {
function RemoveDestructable (line 3813) | function RemoveDestructable(C: Context, L: lua_State): number {
function KillDestructable (line 3822) | function KillDestructable(C: Context, L: lua_State): number {
function SetDestructableInvulnerable (line 3831) | function SetDestructableInvulnerable(C: Context, L: lua_State): number {
function IsDestructableInvulnerable (line 3841) | function IsDestructableInvulnerable(C: Context, L: lua_State): number {
function EnumDestructablesInRect (line 3851) | function EnumDestructablesInRect(C: Context, L: lua_State): number {
function GetDestructableTypeId (line 3862) | function GetDestructableTypeId(C: Context, L: lua_State): number {
function GetDestructableX (line 3872) | function GetDestructableX(C: Context, L: lua_State): number {
function GetDestructableY (line 3882) | function GetDestructableY(C: Context, L: lua_State): number {
function SetDestructableLife (line 3892) | function SetDestructableLife(C: Context, L: lua_State): number {
function GetDestructableLife (line 3902) | function GetDestructableLife(C: Context, L: lua_State): number {
function SetDestructableMaxLife (line 3912) | function SetDestructableMaxLife(C: Context, L: lua_State): number {
function GetDestructableMaxLife (line 3922) | function GetDestructableMaxLife(C: Context, L: lua_State): number {
function DestructableRestoreLife (line 3932) | function DestructableRestoreLife(C: Context, L: lua_State): number {
function QueueDestructableAnimation (line 3943) | function QueueDestructableAnimation(C: Context, L: lua_State): number {
function SetDestructableAnimation (line 3953) | function SetDestructableAnimation(C: Context, L: lua_State): number {
function SetDestructableAnimationSpeed (line 3963) | function SetDestructableAnimationSpeed(C: Context, L: lua_State): number {
function ShowDestructable (line 3973) | function ShowDestructable(C: Context, L: lua_State): number {
function GetDestructableOccluderHeight (line 3983) | function GetDestructableOccluderHeight(C: Context, L: lua_State): number {
function SetDestructableOccluderHeight (line 3993) | function SetDestructableOccluderHeight(C: Context, L: lua_State): number {
function GetDestructableName (line 4003) | function GetDestructableName(C: Context, L: lua_State): number {
function GetTriggerDestructable (line 4013) | function GetTriggerDestructable(C: Context, L: lua_State): number {
function CreateItem (line 4023) | function CreateItem(C: Context, L: lua_State): number {
function RemoveItem (line 4035) | function RemoveItem(C: Context, L: lua_State): number {
function GetItemPlayer (line 4044) | function GetItemPlayer(C: Context, L: lua_State): number {
function GetItemTypeId (line 4054) | function GetItemTypeId(C: Context, L: lua_State): number {
function GetItemX (line 4064) | function GetItemX(C: Context, L: lua_State): number {
function GetItemY (line 4074) | function GetItemY(C: Context, L: lua_State): number {
function SetItemPosition (line 4084) | function SetItemPosition(C: Context, L: lua_State): number {
function SetItemDropOnDeath (line 4095) | function SetItemDropOnDeath(C: Context, L: lua_State): number {
function SetItemDroppable (line 4105) | function SetItemDroppable(C: Context, L: lua_State): number {
function SetItemPawnable (line 4115) | function SetItemPawnable(C: Context, L: lua_State): number {
function SetItemPlayer (line 4125) | function SetItemPlayer(C: Context, L: lua_State): number {
function SetItemInvulnerable (line 4136) | function SetItemInvulnerable(C: Context, L: lua_State): number {
function IsItemInvulnerable (line 4146) | function IsItemInvulnerable(C: Context, L: lua_State): number {
function SetItemVisible (line 4156) | function SetItemVisible(C: Context, L: lua_State): number {
function IsItemVisible (line 4166) | function IsItemVisible(C: Context, L: lua_State): number {
function IsItemOwned (line 4176) | function IsItemOwned(C: Context, L: lua_State): number {
function IsItemPowerup (line 4186) | function IsItemPowerup(C: Context, L: lua_State): number {
function IsItemSellable (line 4196) | function IsItemSellable(C: Context, L: lua_State): number {
function IsItemPawnable (line 4206) | function IsItemPawnable(C: Context, L: lua_State): number {
function IsItemIdPowerup (line 4216) | function IsItemIdPowerup(C: Context, L: lua_State): number {
function IsItemIdSellable (line 4226) | function IsItemIdSellable(C: Context, L: lua_State): number {
function IsItemIdPawnable (line 4236) | function IsItemIdPawnable(C: Context, L: lua_State): number {
function EnumItemsInRect (line 4246) | function EnumItemsInRect(C: Context, L: lua_State): number {
function GetItemLevel (line 4257) | function GetItemLevel(C: Context, L: lua_State): number {
function GetItemType (line 4267) | function GetItemType(C: Context, L: lua_State): number {
function SetItemDropID (line 4277) | function SetItemDropID(C: Context, L: lua_State): number {
function GetItemName (line 4287) | function GetItemName(C: Context, L: lua_State): number {
function GetItemCharges (line 4297) | function GetItemCharges(C: Context, L: lua_State): number {
function SetItemCharges (line 4307) | function SetItemCharges(C: Context, L: lua_State): number {
function GetItemUserData (line 4317) | function GetItemUserData(C: Context, L: lua_State): number {
function SetItemUserData (line 4327) | function SetItemUserData(C: Context, L: lua_State): number {
function CreateUnit (line 4337) | function CreateUnit(C: Context, L: lua_State): number {
function CreateUnitByName (line 4352) | function CreateUnitByName(C: Context, L: lua_State): number {
function CreateUnitAtLoc (line 4366) | function CreateUnitAtLoc(C: Context, L: lua_State): number {
function CreateUnitAtLocByName (line 4379) | function CreateUnitAtLocByName(C: Context, L: lua_State): number {
function CreateCorpse (line 4392) | function CreateCorpse(C: Context, L: lua_State): number {
function KillUnit (line 4406) | function KillUnit(C: Context, L: lua_State): number {
function RemoveUnit (line 4415) | function RemoveUnit(C: Context, L: lua_State): number {
function ShowUnit (line 4424) | function ShowUnit(C: Context, L: lua_State): number {
function SetUnitState (line 4434) | function SetUnitState(C: Context, L: lua_State): number {
function SetUnitX (line 4445) | function SetUnitX(C: Context, L: lua_State): number {
function SetUnitY (line 4455) | function SetUnitY(C: Context, L: lua_State): number {
function SetUnitPosition (line 4465) | function SetUnitPosition(C: Context, L: lua_State): number {
function SetUnitPositionLoc (line 4476) | function SetUnitPositionLoc(C: Context, L: lua_State): number {
function SetUnitFacing (line 4486) | function SetUnitFacing(C: Context, L: lua_State): number {
function SetUnitFacingTimed (line 4496) | function SetUnitFacingTimed(C: Context, L: lua_State): number {
function SetUnitMoveSpeed (line 4507) | function SetUnitMoveSpeed(C: Context, L: lua_State): number {
function SetUnitFlyHeight (line 4517) | function SetUnitFlyHeight(C: Context, L: lua_State): number {
function SetUnitTurnSpeed (line 4528) | function SetUnitTurnSpeed(C: Context, L: lua_State): number {
function SetUnitPropWindow (line 4538) | function SetUnitPropWindow(C: Context, L: lua_State): number {
function SetUnitAcquireRange (line 4548) | function SetUnitAcquireRange(C: Context, L: lua_State): number {
function SetUnitCreepGuard (line 4558) | function SetUnitCreepGuard(C: Context, L: lua_State): number {
function GetUnitAcquireRange (line 4568) | function GetUnitAcquireRange(C: Context, L: lua_State): number {
function GetUnitTurnSpeed (line 4578) | function GetUnitTurnSpeed(C: Context, L: lua_State): number {
function GetUnitPropWindow (line 4588) | function GetUnitPropWindow(C: Context, L: lua_State): number {
function GetUnitFlyHeight (line 4598) | function GetUnitFlyHeight(C: Context, L: lua_State): number {
function GetUnitDefaultAcquireRange (line 4608) | function GetUnitDefaultAcquireRange(C: Context, L: lua_State): number {
function GetUnitDefaultTurnSpeed (line 4618) | function GetUnitDefaultTurnSpeed(C: Context, L: lua_State): number {
function GetUnitDefaultPropWindow (line 4628) | function GetUnitDefaultPropWindow(C: Context, L: lua_State): number {
function GetUnitDefaultFlyHeight (line 4638) | function GetUnitDefaultFlyHeight(C: Context, L: lua_State): number {
function SetUnitOwner (line 4648) | function SetUnitOwner(C: Context, L: lua_State): number {
function SetUnitColor (line 4659) | function SetUnitColor(C: Context, L: lua_State): number {
function SetUnitScale (line 4669) | function SetUnitScale(C: Context, L: lua_State): number {
function SetUnitTimeScale (line 4681) | function SetUnitTimeScale(C: Context, L: lua_State): number {
function SetUnitBlendTime (line 4691) | function SetUnitBlendTime(C: Context, L: lua_State): number {
function SetUnitVertexColor (line 4701) | function SetUnitVertexColor(C: Context, L: lua_State): number {
function QueueUnitAnimation (line 4714) | function QueueUnitAnimation(C: Context, L: lua_State): number {
function SetUnitAnimation (line 4724) | function SetUnitAnimation(C: Context, L: lua_State): number {
function SetUnitAnimationByIndex (line 4734) | function SetUnitAnimationByIndex(C: Context, L: lua_State): number {
function SetUnitAnimationWithRarity (line 4744) | function SetUnitAnimationWithRarity(C: Context, L: lua_State): number {
function AddUnitAnimationProperties (line 4755) | function AddUnitAnimationProperties(C: Context, L: lua_State): number {
function SetUnitLookAt (line 4766) | function SetUnitLookAt(C: Context, L: lua_State): number {
function ResetUnitLookAt (line 4780) | function ResetUnitLookAt(C: Context, L: lua_State): number {
function SetUnitRescuable (line 4789) | function SetUnitRescuable(C: Context, L: lua_State): number {
function SetUnitRescueRange (line 4800) | function SetUnitRescueRange(C: Context, L: lua_State): number {
function SetHeroStr (line 4810) | function SetHeroStr(C: Context, L: lua_State): number {
function SetHeroAgi (line 4821) | function SetHeroAgi(C: Context, L: lua_State): number {
function SetHeroInt (line 4832) | function SetHeroInt(C: Context, L: lua_State): number {
function GetHeroStr (line 4843) | function GetHeroStr(C: Context, L: lua_State): number {
function GetHeroAgi (line 4854) | function GetHeroAgi(C: Context, L: lua_State): number {
function GetHeroInt (line 4865) | function GetHeroInt(C: Context, L: lua_State): number {
function UnitStripHeroLevel (line 4876) | function UnitStripHeroLevel(C: Context, L: lua_State): number {
function GetHeroXP (line 4887) | function GetHeroXP(C: Context, L: lua_State): number {
function SetHeroXP (line 4897) | function SetHeroXP(C: Context, L: lua_State): number {
function GetHeroSkillPoints (line 4908) | function GetHeroSkillPoints(C: Context, L: lua_State): number {
function UnitModifySkillPoints (line 4918) | function UnitModifySkillPoints(C: Context, L: lua_State): number {
function AddHeroXP (line 4929) | function AddHeroXP(C: Context, L: lua_State): number {
function SetHeroLevel (line 4940) | function SetHeroLevel(C: Context, L: lua_State): number {
function GetHeroLevel (line 4951) | function GetHeroLevel(C: Context, L: lua_State): number {
function GetUnitLevel (line 4961) | function GetUnitLevel(C: Context, L: lua_State): number {
function GetHeroProperName (line 4971) | function GetHeroProperName(C: Context, L: lua_State): number {
function SuspendHeroXP (line 4981) | function SuspendHeroXP(C: Context, L: lua_State): number {
function IsSuspendedXP (line 4991) | function IsSuspendedXP(C: Context, L: lua_State): number {
function SelectHeroSkill (line 5001) | function SelectHeroSkill(C: Context, L: lua_State): number {
function GetUnitAbilityLevel (line 5011) | function GetUnitAbilityLevel(C: Context, L: lua_State): number {
function DecUnitAbilityLevel (line 5022) | function DecUnitAbilityLevel(C: Context, L: lua_State): number {
function IncUnitAbilityLevel (line 5033) | function IncUnitAbilityLevel(C: Context, L: lua_State): number {
function SetUnitAbilityLevel (line 5044) | function SetUnitAbilityLevel(C: Context, L: lua_State): number {
function ReviveHero (line 5056) | function ReviveHero(C: Context, L: lua_State): number {
function ReviveHeroLoc (line 5069) | function ReviveHeroLoc(C: Context, L: lua_State): number {
function SetUnitExploded (line 5081) | function SetUnitExploded(C: Context, L: lua_State): number {
function SetUnitInvulnerable (line 5091) | function SetUnitInvulnerable(C: Context, L: lua_State): number {
function PauseUnit (line 5101) | function PauseUnit(C: Context, L: lua_State): number {
function IsUnitPaused (line 5111) | function IsUnitPaused(C: Context, L: lua_State): number {
function SetUnitPathing (line 5121) | function SetUnitPathing(C: Context, L: lua_State): number {
function ClearSelection (line 5131) | function ClearSelection(_C: Context, _L: lua_State): number {
function SelectUnit (line 5140) | function SelectUnit(C: Context, L: lua_State): number {
function GetUnitPointValue (line 5150) | function GetUnitPointValue(C: Context, L: lua_State): number {
function GetUnitPointValueByType (line 5160) | function GetUnitPointValueByType(C: Context, L: lua_State): number {
function UnitAddItem (line 5170) | function UnitAddItem(C: Context, L: lua_State): number {
function UnitAddItemById (line 5181) | function UnitAddItemById(C: Context, L: lua_State): number {
function UnitAddItemToSlotById (line 5192) | function UnitAddItemToSlotById(C: Context, L: lua_State): number {
function UnitRemoveItem (line 5204) | function UnitRemoveItem(C: Context, L: lua_State): number {
function UnitRemoveItemFromSlot (line 5214) | function UnitRemoveItemFromSlot(C: Context, L: lua_State): number {
function UnitHasItem (line 5225) | function UnitHasItem(C: Context, L: lua_State): number {
function UnitItemInSlot (line 5236) | function UnitItemInSlot(C: Context, L: lua_State): number {
function UnitInventorySize (line 5247) | function UnitInventorySize(C: Context, L: lua_State): number {
function UnitDropItemPoint (line 5257) | function UnitDropItemPoint(C: Context, L: lua_State): number {
function UnitDropItemSlot (line 5270) | function UnitDropItemSlot(C: Context, L: lua_State): number {
function UnitDropItemTarget (line 5282) | function UnitDropItemTarget(C: Context, L: lua_State): number {
function UnitUseItem (line 5294) | function UnitUseItem(C: Context, L: lua_State): number {
function UnitUseItemPoint (line 5305) | function UnitUseItemPoint(C: Context, L: lua_State): number {
function UnitUseItemTarget (line 5318) | function UnitUseItemTarget(C: Context, L: lua_State): number {
function GetUnitX (line 5330) | function GetUnitX(C: Context, L: lua_State): number {
function GetUnitY (line 5340) | function GetUnitY(C: Context, L: lua_State): number {
function GetUnitLoc (line 5350) | function GetUnitLoc(C: Context, L: lua_State): number {
function GetUnitFacing (line 5360) | function GetUnitFacing(C: Context, L: lua_State): number {
function GetUnitMoveSpeed (line 5370) | function GetUnitMoveSpeed(C: Context, L: lua_State): number {
function GetUnitDefaultMoveSpeed (line 5380) | function GetUnitDefaultMoveSpeed(C: Context, L: lua_State): number {
function GetUnitState (line 5390) | function GetUnitState(C: Context, L: lua_State): number {
function GetOwningPlayer (line 5401) | function GetOwningPlayer(C: Context, L: lua_State): number {
function GetUnitTypeId (line 5412) | function GetUnitTypeId(C: Context, L: lua_State): number {
function GetUnitRace (line 5422) | function GetUnitRace(C: Context, L: lua_State): number {
function GetUnitName (line 5432) | function GetUnitName(C: Context, L: lua_State): number {
function GetUnitFoodUsed (line 5442) | function GetUnitFoodUsed(C: Context, L: lua_State): number {
function GetUnitFoodMade (line 5452) | function GetUnitFoodMade(C: Context, L: lua_State): number {
function GetFoodMade (line 5462) | function GetFoodMade(C: Context, L: lua_State): number {
function GetFoodUsed (line 5472) | function GetFoodUsed(C: Context, L: lua_State): number {
function SetUnitUseFood (line 5482) | function SetUnitUseFood(C: Context, L: lua_State): number {
function GetUnitRallyPoint (line 5492) | function GetUnitRallyPoint(C: Context, L: lua_State): number {
function GetUnitRallyUnit (line 5502) | function GetUnitRallyUnit(C: Context, L: lua_State): number {
function GetUnitRallyDestructable (line 5512) | function GetUnitRallyDestructable(C: Context, L: lua_State): number {
function IsUnitInGroup (line 5522) | function IsUnitInGroup(C: Context, L: lua_State): number {
function IsUnitInForce (line 5533) | function IsUnitInForce(C: Context, L: lua_State): number {
function IsUnitOwnedByPlayer (line 5544) | function IsUnitOwnedByPlayer(C: Context, L: lua_State): number {
function IsUnitAlly (line 5555) | function IsUnitAlly(C: Context, L: lua_State): number {
function IsUnitEnemy (line 5566) | function IsUnitEnemy(C: Context, L: lua_State): number {
function IsUnitVisible (line 5577) | function IsUnitVisible(C: Context, L: lua_State): number {
function IsUnitDetected (line 5588) | function IsUnitDetected(C: Context, L: lua_State): number {
function IsUnitInvisible (line 5599) | function IsUnitInvisible(C: Context, L: lua_State): number {
function IsUnitFogged (line 5610) | function IsUnitFogged(C: Context, L: lua_State): number {
function IsUnitMasked (line 5621) | function IsUnitMasked(C: Context, L: lua_State): number {
function IsUnitSelected (line 5632) | function IsUnitSelected(C: Context, L: lua_State): number {
function IsUnitRace (line 5643) | function IsUnitRace(C: Context, L: lua_State): number {
function IsUnitType (line 5654) | function IsUnitType(C: Context, L: lua_State): number {
function IsUnit (line 5665) | function IsUnit(C: Context, L: lua_State): number {
function IsUnitInRange (line 5676) | function IsUnitInRange(C: Context, L: lua_State): number {
function IsUnitInRangeXY (line 5688) | function IsUnitInRangeXY(C: Context, L: lua_State): number {
function IsUnitInRangeLoc (line 5701) | function IsUnitInRangeLoc(C: Context, L: lua_State): number {
function IsUnitHidden (line 5713) | function IsUnitHidden(C: Context, L: lua_State): number {
function IsUnitIllusion (line 5723) | function IsUnitIllusion(C: Context, L: lua_State): number {
function IsUnitInTransport (line 5733) | function IsUnitInTransport(C: Context, L: lua_State): number {
function IsUnitLoaded (line 5744) | function IsUnitLoaded(C: Context, L: lua_State): number {
function IsHeroUnitId (line 5754) | function IsHeroUnitId(C: Context, L: lua_State): number {
function IsUnitIdType (line 5764) | function IsUnitIdType(C: Context, L: lua_State): number {
function UnitShareVision (line 5775) | function UnitShareVision(C: Context, L: lua_State): number {
function UnitSuspendDecay (line 5786) | function UnitSuspendDecay(C: Context, L: lua_State): number {
function UnitAddType (line 5796) | function UnitAddType(C: Context, L: lua_State): number {
function UnitRemoveType (line 5807) | function UnitRemoveType(C: Context, L: lua_State): number {
function UnitAddAbility (line 5818) | function UnitAddAbility(C: Context, L: lua_State): number {
function UnitRemoveAbility (line 5829) | function UnitRemoveAbility(C: Context, L: lua_State): number {
function UnitMakeAbilityPermanent (line 5840) | function UnitMakeAbilityPermanent(C: Context, L: lua_State): number {
function UnitRemoveBuffs (line 5852) | function UnitRemoveBuffs(C: Context, L: lua_State): number {
function UnitRemoveBuffsEx (line 5863) | function UnitRemoveBuffsEx(C: Context, L: lua_State): number {
function UnitHasBuffsEx (line 5879) | function UnitHasBuffsEx(C: Context, L: lua_State): number {
function UnitCountBuffsEx (line 5896) | function UnitCountBuffsEx(C: Context, L: lua_State): number {
function UnitAddSleep (line 5913) | function UnitAddSleep(C: Context, L: lua_State): number {
function UnitCanSleep (line 5923) | function UnitCanSleep(C: Context, L: lua_State): number {
function UnitAddSleepPerm (line 5933) | function UnitAddSleepPerm(C: Context, L: lua_State): number {
function UnitCanSleepPerm (line 5943) | function UnitCanSleepPerm(C: Context, L: lua_State): number {
function UnitIsSleeping (line 5953) | function UnitIsSleeping(C: Context, L: lua_State): number {
function UnitWakeUp (line 5963) | function UnitWakeUp(C: Context, L: lua_State): number {
function UnitApplyTimedLife (line 5972) | function UnitApplyTimedLife(C: Context, L: lua_State): number {
function UnitIgnoreAlarm (line 5983) | function UnitIgnoreAlarm(C: Context, L: lua_State): number {
function UnitIgnoreAlarmToggled (line 5994) | function UnitIgnoreAlarmToggled(C: Context, L: lua_State): number {
function UnitResetCooldown (line 6004) | function UnitResetCooldown(C: Context, L: lua_State): number {
function UnitSetConstructionProgress (line 6013) | function UnitSetConstructionProgress(C: Context, L: lua_State): number {
function UnitSetUpgradeProgress (line 6023) | function UnitSetUpgradeProgress(C: Context, L: lua_State): number {
function UnitPauseTimedLife (line 6033) | function UnitPauseTimedLife(C: Context, L: lua_State): number {
function UnitSetUsesAltIcon (line 6043) | function UnitSetUsesAltIcon(C: Context, L: lua_State): number {
function UnitDamagePoint (line 6053) | function UnitDamagePoint(C: Context, L: lua_State): number {
function UnitDamageTarget (line 6073) | function UnitDamageTarget(C: Context, L: lua_State): number {
function IssueImmediateOrder (line 6090) | function IssueImmediateOrder(C: Context, L: lua_State): number {
function IssueImmediateOrderById (line 6101) | function IssueImmediateOrderById(C: Context, L: lua_State): number {
function IssuePointOrder (line 6112) | function IssuePointOrder(C: Context, L: lua_State): number {
function IssuePointOrderLoc (line 6125) | function IssuePointOrderLoc(C: Context, L: lua_State): number {
function IssuePointOrderById (line 6137) | function IssuePointOrderById(C: Context, L: lua_State): number {
function IssuePointOrderByIdLoc (line 6150) | function IssuePointOrderByIdLoc(C: Context, L: lua_State): number {
function IssueTargetOrder (line 6162) | function IssueTargetOrder(C: Context, L: lua_State): number {
function IssueTargetOrderById (line 6174) | function IssueTargetOrderById(C: Context, L: lua_State): number {
function IssueInstantPointOrder (line 6186) | function IssueInstantPointOrder(C: Context, L: lua_State): number {
function IssueInstantPointOrderById (line 6200) | function IssueInstantPointOrderById(C: Context, L: lua_State): number {
function IssueInstantTargetOrder (line 6214) | function IssueInstantTargetOrder(C: Context, L: lua_State): number {
function IssueInstantTargetOrderById (line 6227) | function IssueInstantTargetOrderById(C: Context, L: lua_State): number {
function IssueBuildOrder (line 6240) | function IssueBuildOrder(C: Context, L: lua_State): number {
function IssueBuildOrderById (line 6253) | function IssueBuildOrderById(C: Context, L: lua_State): number {
function IssueNeutralImmediateOrder (line 6266) | function IssueNeutralImmediateOrder(C: Context, L: lua_State): number {
function IssueNeutralImmediateOrderById (line 6278) | function IssueNeutralImmediateOrderById(C: Context, L: lua_State): number {
function IssueNeutralPointOrder (line 6290) | function IssueNeutralPointOrder(C: Context, L: lua_State): number {
function IssueNeutralPointOrderById (line 6304) | function IssueNeutralPointOrderById(C: Context, L: lua_State): number {
function IssueNeutralTargetOrder (line 6318) | function IssueNeutralTargetOrder(C: Context, L: lua_State): number {
function IssueNeutralTargetOrderById (line 6331) | function IssueNeutralTargetOrderById(C: Context, L: lua_State): number {
function GetUnitCurrentOrder (line 6344) | function GetUnitCurrentOrder(C: Context, L: lua_State): number {
function SetResourceAmount (line 6354) | function SetResourceAmount(C: Context, L: lua_State): number {
function AddResourceAmount (line 6364) | function AddResourceAmount(C: Context, L: lua_State): number {
function GetResourceAmount (line 6374) | function GetResourceAmount(C: Context, L: lua_State): number {
function WaygateGetDestinationX (line 6384) | function WaygateGetDestinationX(C: Context, L: lua_State): number {
function WaygateGetDestinationY (line 6394) | function WaygateGetDestinationY(C: Context, L: lua_State): number {
function WaygateSetDestination (line 6404) | function WaygateSetDestination(C: Context, L: lua_State): number {
function WaygateActivate (line 6415) | function WaygateActivate(C: Context, L: lua_State): number {
function WaygateIsActive (line 6425) | function WaygateIsActive(C: Context, L: lua_State): number {
function AddItemToAllStock (line 6435) | function AddItemToAllStock(C: Context, L: lua_State): number {
function AddItemToStock (line 6446) | function AddItemToStock(C: Context, L: lua_State): number {
function AddUnitToAllStock (line 6458) | function AddUnitToAllStock(C: Context, L: lua_State): number {
function AddUnitToStock (line 6469) | function AddUnitToStock(C: Context, L: lua_State): number {
function RemoveItemFromAllStock (line 6481) | function RemoveItemFromAllStock(C: Context, L: lua_State): number {
function RemoveItemFromStock (line 6490) | function RemoveItemFromStock(C: Context, L: lua_State): number {
function RemoveUnitFromAllStock (line 6500) | function RemoveUnitFromAllStock(C: Context, L: lua_State): number {
function RemoveUnitFromStock (line 6509) | function RemoveUnitFromStock(C: Context, L: lua_State): number {
function SetAllItemTypeSlots (line 6519) | function SetAllItemTypeSlots(C: Context, L: lua_State): number {
function SetAllUnitTypeSlots (line 6528) | function SetAllUnitTypeSlots(C: Context, L: lua_State): number {
function SetItemTypeSlots (line 6537) | function SetItemTypeSlots(C: Context, L: lua_State): number {
function SetUnitTypeSlots (line 6547) | function SetUnitTypeSlots(C: Context, L: lua_State): number {
function GetUnitUserData (line 6557) | function GetUnitUserData(C: Context, L: lua_State): number {
function SetUnitUserData (line 6567) | function SetUnitUserData(C: Context, L: lua_State): number {
function Player (line 6577) | function Player(C: Context, L: lua_State): number {
function GetLocalPlayer (line 6588) | function GetLocalPlayer(C: Context, L: lua_State): number {
function IsPlayerAlly (line 6598) | function IsPlayerAlly(C: Context, L: lua_State): number {
function IsPlayerEnemy (line 6609) | function IsPlayerEnemy(C: Context, L: lua_State): number {
function IsPlayerInForce (line 6620) | function IsPlayerInForce(C: Context, L: lua_State): number {
function IsPlayerObserver (line 6631) | function IsPlayerObserver(C: Context, L: lua_State): number {
function IsVisibleToPlayer (line 6641) | function IsVisibleToPlayer(C: Context, L: lua_State): number {
function IsLocationVisibleToPlayer (line 6653) | function IsLocationVisibleToPlayer(C: Context, L: lua_State): number {
function IsFoggedToPlayer (line 6664) | function IsFoggedToPlayer(C: Context, L: lua_State): number {
function IsLocationFoggedToPlayer (line 6676) | function IsLocationFoggedToPlayer(C: Context, L: lua_State): number {
function IsMaskedToPlayer (line 6687) | function IsMaskedToPlayer(C: Context, L: lua_State): number {
function IsLocationMaskedToPlayer (line 6699) | function IsLocationMaskedToPlayer(C: Context, L: lua_State): number {
function GetPlayerRace (line 6710) | function GetPlayerRace(C: Context, L: lua_State): number {
function GetPlayerId (line 6721) | function GetPlayerId(C: Context, L: lua_State): number {
function GetPlayerUnitCount (line 6732) | function GetPlayerUnitCount(C: Context, L: lua_State): number {
function GetPlayerTypedUnitCount (line 6743) | function GetPlayerTypedUnitCount(C: Context, L: lua_State): number {
function GetPlayerStructureCount (line 6756) | function GetPlayerStructureCount(C: Context, L: lua_State): number {
function GetPlayerState (line 6767) | function GetPlayerState(C: Context, L: lua_State): number {
function GetPlayerScore (line 6778) | function GetPlayerScore(C: Context, L: lua_State): number {
function GetPlayerAlliance (line 6789) | function GetPlayerAlliance(C: Context, L: lua_State): number {
function GetPlayerHandicap (line 6801) | function GetPlayerHandicap(C: Context, L: lua_State): number {
function GetPlayerHandicapXP (line 6811) | function GetPlayerHandicapXP(C: Context, L: lua_State): number {
function SetPlayerHandicap (line 6821) | function SetPlayerHandicap(C: Context, L: lua_State): number {
function SetPlayerHandicapXP (line 6831) | function SetPlayerHandicapXP(C: Context, L: lua_State): number {
function SetPlayerTechMaxAllowed (line 6841) | function SetPlayerTechMaxAllowed(C: Context, L: lua_State): number {
function GetPlayerTechMaxAllowed (line 6852) | function GetPlayerTechMaxAllowed(C: Context, L: lua_State): number {
function AddPlayerTechResearched (line 6863) | function AddPlayerTechResearched(C: Context, L: lua_State): number {
function SetPlayerTechResearched (line 6874) | function SetPlayerTechResearched(C: Context, L: lua_State): number {
function GetPlayerTechResearched (line 6885) | function GetPlayerTechResearched(C: Context, L: lua_State): number {
function GetPlayerTechCount (line 6897) | function GetPlayerTechCount(C: Context, L: lua_State): number {
function SetPlayerUnitsOwner (line 6909) | function SetPlayerUnitsOwner(C: Context, L: lua_State): number {
function CripplePlayer (line 6919) | function CripplePlayer(C: Context, L: lua_State): number {
function SetPlayerAbilityAvailable (line 6930) | function SetPlayerAbilityAvailable(C: Context, L: lua_State): number {
function SetPlayerState (line 6941) | function SetPlayerState(C: Context, L: lua_State): number {
function RemovePlayer (line 6952) | function RemovePlayer(C: Context, L: lua_State): number {
function CachePlayerHeroData (line 6962) | function CachePlayerHeroData(C: Context, L: lua_State): number {
function SetFogStateRect (line 6971) | function SetFogStateRect(C: Context, L: lua_State): number {
function SetFogStateRadius (line 6983) | function SetFogStateRadius(C: Context, L: lua_State): number {
function SetFogStateRadiusLoc (line 6997) | function SetFogStateRadiusLoc(C: Context, L: lua_State): number {
function FogMaskEnable (line 7010) | function FogMaskEnable(C: Context, L: lua_State): number {
function IsFogMaskEnabled (line 7019) | function IsFogMaskEnabled(C: Context, L: lua_State): number {
function FogEnable (line 7029) | function FogEnable(C: Context, L: lua_State): number {
function IsFogEnabled (line 7038) | function IsFogEnabled(C: Context, L: lua_State): number {
function CreateFogModifierRect (line 7048) | function CreateFogModifierRect(C: Context, L: lua_State): number {
function CreateFogModifierRadius (line 7062) | function CreateFogModifierRadius(C: Context, L: lua_State): number {
function CreateFogModifierRadiusLoc (line 7078) | function CreateFogModifierRadiusLoc(C: Context, L: lua_State): number {
function DestroyFogModifier (line 7093) | function DestroyFogModifier(C: Context, L: lua_State): number {
function FogModifierStart (line 7102) | function FogModifierStart(C: Context, L: lua_State): number {
function FogModifierStop (line 7111) | function FogModifierStop(C: Context, L: lua_State): number {
function VersionGet (line 7120) | function VersionGet(C: Context, L: lua_State): number {
function VersionCompatible (line 7130) | function VersionCompatible(C: Context, L: lua_State): number {
function VersionSupported (line 7140) | function VersionSupported(C: Context, L: lua_State): number {
function EndGame (line 7150) | function EndGame(C: Context, L: lua_State): number {
function ChangeLevel (line 7159) | function ChangeLevel(C: Context, L: lua_State): number {
function RestartGame (line 7169) | function RestartGame(C: Context, L: lua_State): number {
function ReloadGame (line 7178) | function ReloadGame(_C: Context, _L: lua_State): number {
function SetCampaignMenuRace (line 7187) | function SetCampaignMenuRace(C: Context, L: lua_State): number {
function SetCampaignMenuRaceEx (line 7196) | function SetCampaignMenuRaceEx(C: Context, L: lua_State): number {
function ForceCampaignSelectScreen (line 7205) | function ForceCampaignSelectScreen(_C: Context, _L: lua_State): number {
function LoadGame (line 7214) | function LoadGame(C: Context, L: lua_State): number {
function SaveGame (line 7224) | function SaveGame(C: Context, L: lua_State): number {
function RenameSaveDirectory (line 7233) | function RenameSaveDirectory(C: Context, L: lua_State): number {
function RemoveSaveDirectory (line 7244) | function RemoveSaveDirectory(C: Context, L: lua_State): number {
function CopySaveGame (line 7254) | function CopySaveGame(C: Context, L: lua_State): number {
function SaveGameExists (line 7265) | function SaveGameExists(C: Context, L: lua_State): number {
function SyncSelections (line 7275) | function SyncSelections(_C: Context, _L: lua_State): number {
function SetFloatGameState (line 7284) | function SetFloatGameState(C: Context, L: lua_State): number {
function GetFloatGameState (line 7294) | function GetFloatGameState(C: Context, L: lua_State): number {
function SetIntegerGameState (line 7304) | function SetIntegerGameState(C: Context, L: lua_State): number {
function GetIntegerGameState (line 7314) | function GetIntegerGameState(C: Context, L: lua_State): number {
function SetTutorialCleared (line 7324) | function SetTutorialCleared(C: Context, L: lua_State): number {
function SetMissionAvailable (line 7333) | function SetMissionAvailable(C: Context, L: lua_State): number {
function SetCampaignAvailable (line 7344) | function SetCampaignAvailable(C: Context, L: lua_State): number {
function SetOpCinematicAvailable (line 7354) | function SetOpCinematicAvailable(C: Context, L: lua_State): number {
function SetEdCinematicAvailable (line 7364) | function SetEdCinematicAvailable(C: Context, L: lua_State): number {
function GetDefaultDifficulty (line 7374) | function GetDefaultDifficulty(C: Context, L: lua_State): number {
function SetDefaultDifficulty (line 7384) | function SetDefaultDifficulty(C: Context, L: lua_State): number {
function SetCustomCampaignButtonVisible (line 7393) | function SetCustomCampaignButtonVisible(C: Context, L: lua_State): number {
function GetCustomCampaignButtonVisible (line 7403) | function GetCustomCampaignButtonVisible(C: Context, L: lua_State): number {
function DoNotSaveReplay (line 7413) | function DoNotSaveReplay(_C: Context, _L: lua_State): number {
function DialogCreate (line 7422) | function DialogCreate(C: Context, L: lua_State): number {
function DialogDestroy (line 7432) | function DialogDestroy(C: Context, L: lua_State): number {
function DialogClear (line 7441) | function DialogClear(C: Context, L: lua_State): number {
function DialogSetMessage (line 7450) | function DialogSetMessage(C: Context, L: lua_State): number {
function DialogAddButton (line 7460) | function DialogAddButton(C: Context, L: lua_State): number {
function DialogAddQuitButton (line 7472) | function DialogAddQuitButton(C: Context, L: lua_State): number {
function DialogDisplay (line 7485) | function DialogDisplay(C: Context, L: lua_State): number {
function ReloadGameCachesFromDisk (line 7496) | function ReloadGameCachesFromDisk(C: Context, L: lua_State): number {
function InitGameCache (line 7506) | function InitGameCache(C: Context, L: lua_State): number {
function SaveGameCache (line 7516) | function SaveGameCache(C: Context, L: lua_State): number {
function StoreInteger (line 7526) | function StoreInteger(C: Context, L: lua_State): number {
function StoreReal (line 7538) | function StoreReal(C: Context, L: lua_State): number {
function StoreBoolean (line 7550) | function StoreBoolean(C: Context, L: lua_State): number {
function StoreUnit (line 7562) | function StoreUnit(C: Context, L: lua_State): number {
function StoreString (line 7575) | function StoreString(C: Context, L: lua_State): number {
function SyncStoredInteger (line 7588) | function SyncStoredInteger(C: Context, L: lua_State): number {
function SyncStoredReal (line 7599) | function SyncStoredReal(C: Context, L: lua_State): number {
function SyncStoredBoolean (line 7610) | function SyncStoredBoolean(C: Context, L: lua_State): number {
function SyncStoredUnit (line 7621) | function SyncStoredUnit(C: Context, L: lua_State): number {
function SyncStoredString (line 7632) | function SyncStoredString(C: Context, L: lua_State): number {
function HaveStoredInteger (line 7643) | function HaveStoredInteger(C: Context, L: lua_State): number {
function HaveStoredReal (line 7655) | function HaveStoredReal(C: Context, L: lua_State): number {
function HaveStoredBoolean (line 7667) | function HaveStoredBoolean(C: Context, L: lua_State): number {
function HaveStoredUnit (line 7679) | function HaveStoredUnit(C: Context, L: lua_State): number {
function HaveStoredString (line 7691) | function HaveStoredString(C: Context, L: lua_State): number {
function FlushGameCache (line 7703) | function FlushGameCache(C: Context, L: lua_State): number {
function FlushStoredMission (line 7712) | function FlushStoredMission(C: Context, L: lua_State): number {
function FlushStoredInteger (line 7722) | function FlushStoredInteger(C: Context, L: lua_State): number {
function FlushStoredReal (line 7733) | function FlushStoredReal(C: Context, L: lua_State): number {
function FlushStoredBoolean (line 7744) | function FlushStoredBoolean(C: Context, L: lua_State): number {
function FlushStoredUnit (line 7755) | function FlushStoredUnit(C: Context, L: lua_State): number {
function FlushStoredString (line 7766) | function FlushStoredString(C: Context, L: lua_State): number {
function GetStoredInteger (line 7777) | function GetStoredInteger(C: Context, L: lua_State): number {
function GetStoredReal (line 7789) | function GetStoredReal(C: Context, L: lua_State): number {
function GetStoredBoolean (line 7801) | function GetStoredBoolean(C: Context, L: lua_State): number {
function GetStoredString (line 7813) | function GetStoredString(C: Context, L: lua_State): number {
function RestoreUnit (line 7825) | function RestoreUnit(C: Context, L: lua_State): number {
function InitHashtable (line 7841) | function InitHashtable(C: Context, L: lua_State): number {
function SaveInteger (line 7851) | function SaveInteger(C: Context, L: lua_State): number {
function SaveReal (line 7863) | function SaveReal(C: Context, L: lua_State): number {
function SaveBoolean (line 7875) | function SaveBoolean(C: Context, L: lua_State): number {
function SaveStr (line 7887) | function SaveStr(C: Context, L: lua_State): number {
function SavePlayerHandle (line 7900) | function SavePlayerHandle(C: Context, L: lua_State): number {
function SaveWidgetHandle (line 7913) | function SaveWidgetHandle(C: Context, L: lua_State): number {
function SaveDestructableHandle (line 7926) | function SaveDestructableHandle(C: Context, L: lua_State): number {
function SaveItemHandle (line 7939) | function SaveItemHandle(C: Context, L: lua_State): number {
function SaveUnitHandle (line 7952) | function SaveUnitHandle(C: Context, L: lua_State): number {
function SaveAbilityHandle (line 7965) | function SaveAbilityHandle(C: Context, L: lua_State): number {
function SaveTimerHandle (line 7978) | function SaveTimerHandle(C: Context, L: lua_State): number {
function SaveTriggerHandle (line 7991) | function SaveTriggerHandle(C: Context, L: lua_State): number {
function SaveTriggerConditionHandle (line 8004) | function SaveTriggerConditionHandle(C: Context, L: lua_State): number {
function SaveTriggerActionHandle (line 8017) | function SaveTriggerActionHandle(C: Context, L: lua_State): number {
function SaveTriggerEventHandle (line 8030) | function SaveTriggerEventHandle(C: Context, L: lua_State): number {
function SaveForceHandle (line 8043) | function SaveForceHandle(C: Context, L: lua_State): number {
function SaveGroupHandle (line 8056) | function SaveGroupHandle(C: Context, L: lua_State): number {
function SaveLocationHandle (line 8069) | function SaveLocationHandle(C: Context, L: lua_State): number {
function SaveRectHandle (line 8082) | function SaveRectHandle(C: Context, L: lua_State): number {
function SaveBooleanExprHandle (line 8095) | function SaveBooleanExprHandle(C: Context, L: lua_State): number {
function SaveSoundHandle (line 8108) | function SaveSoundHandle(C: Context, L: lua_State): number {
function SaveEffectHandle (line 8121) | function SaveEffectHandle(C: Context, L: lua_State): number {
function SaveUnitPoolHandle (line 8134) | function SaveUnitPoolHandle(C: Context, L: lua_State): number {
function SaveItemPoolHandle (line 8147) | function SaveItemPoolHandle(C: Context, L: lua_State): number {
function SaveQuestHandle (line 8160) | function SaveQuestHandle(C: Context, L: lua_State): number {
function SaveQuestItemHandle (line 8173) | function SaveQuestItemHandle(C: Context, L: lua_State): number {
function SaveDefeatConditionHandle (line 8186) | function SaveDefeatConditionHandle(C: Context, L: lua_State): number {
function SaveTimerDialogHandle (line 8199) | function SaveTimerDialogHandle(C: Context, L: lua_State): number {
function SaveLeaderboardHandle (line 8212) | function SaveLeaderboardHandle(C: Context, L: lua_State): number {
function SaveMultiboardHandle (line 8225) | function SaveMultiboardHandle(C: Context, L: lua_State): number {
function SaveMultiboardItemHandle (line 8238) | function SaveMultiboardItemHandle(C: Context, L: lua_State): number {
function SaveTrackableHandle (line 8251) | function SaveTrackableHandle(C: Context, L: lua_State): number {
function SaveDialogHandle (line 8264) | function SaveDialogHandle(C: Context, L: lua_State): number {
function SaveButtonHandle (line 8277) | function SaveButtonHandle(C: Context, L: lua_State): number {
function SaveTextTagHandle (line 8290) | function SaveTextTagHandle(C: Context, L: lua_State): number {
function SaveLightningHandle (line 8303) | function SaveLightningHandle(C: Context, L: lua_State): number {
function SaveImageHandle (line 8316) | function SaveImageHandle(C: Context, L: lua_State): number {
function SaveUbersplatHandle (line 8329) | function SaveUbersplatHandle(C: Context, L: lua_State): number {
function SaveRegionHandle (line 8342) | function SaveRegionHandle(C: Context, L: lua_State): number {
function SaveFogStateHandle (line 8355) | function SaveFogStateHandle(C: Context, L: lua_State): number {
function SaveFogModifierHandle (line 8368) | function SaveFogModifierHandle(C: Context, L: lua_State): number {
function SaveAgentHandle (line 8381) | function SaveAgentHandle(C: Context, L: lua_State): number {
function SaveHashtableHandle (line 8394) | function SaveHashtableHandle(C: Context, L: lua_State): number {
function LoadInteger (line 8407) | function LoadInteger(C: Context, L: lua_State): number {
function LoadReal (line 8419) | function LoadReal(C: Context, L: lua_State): number {
function LoadBoolean (line 8431) | function LoadBoolean(C: Context, L: lua_State): number {
function LoadStr (line 8443) | function LoadStr(C: Context, L: lua_State): number {
function LoadPlayerHandle (line 8455) | function LoadPlayerHandle(C: Context, L: lua_State): number {
function LoadWidgetHandle (line 8467) | function LoadWidgetHandle(C: Context, L: lua_State): number {
function LoadDestructableHandle (line 8479) | function LoadDestructableHandle(C: Context, L: lua_State): number {
function LoadItemHandle (line 8491) | function LoadItemHandle(C: Context, L: lua_State): number {
function LoadUnitHandle (line 8503) | function LoadUnitHandle(C: Context, L: lua_State): number {
function LoadAbilityHandle (line 8515) | function LoadAbilityHandle(C: Context, L: lua_State): number {
function LoadTimerHandle (line 8527) | function LoadTimerHandle(C: Context, L: lua_State): number {
function LoadTriggerHandle (line 8539) | function LoadTriggerHandle(C: Context, L: lua_State): number {
function LoadTriggerConditionHandle (line 8551) | function LoadTriggerConditionHandle(C: Context, L: lua_State): number {
function LoadTriggerActionHandle (line 8563) | function LoadTriggerActionHandle(C: Context, L: lua_State): number {
function LoadTriggerEventHandle (line 8575) | function LoadTriggerEventHandle(C: Context, L: lua_State): number {
function LoadForceHandle (line 8587) | function LoadForceHandle(C: Context, L: lua_State): number {
function LoadGroupHandle (line 8599) | function LoadGroupHandle(C: Context, L: lua_State): number {
function LoadLocationHandle (line 8611) | function LoadLocationHandle(C: Context, L: lua_State): number {
function LoadRectHandle (line 8623) | function LoadRectHandle(C: Context, L: lua_State): number {
function LoadBooleanExprHandle (line 8635) | function LoadBooleanExprHandle(C: Context, L: lua_State): number {
function LoadSoundHandle (line 8647) | function LoadSoundHandle(C: Context, L: lua_State): number {
function LoadEffectHandle (line 8659) | function LoadEffectHandle(C: Context, L: lua_State): number {
function LoadUnitPoolHandle (line 8671) | function LoadUnitPoolHandle(C: Context, L: lua_State): number {
function LoadItemPoolHandle (line 8683) | function LoadItemPoolHandle(C: Context, L: lua_State): number {
function LoadQuestHandle (line 8695) | function LoadQuestHandle(C: Context, L: lua_State): number {
function LoadQuestItemHandle (line 8707) | function LoadQuestItemHandle(C: Context, L: lua_State): number {
function LoadDefeatConditionHandle (line 8719) | function LoadDefeatConditionHandle(C: Context, L: lua_State): number {
function LoadTimerDialogHandle (line 8731) | function LoadTimerDialogHandle(C: Context, L: lua_State): number {
function LoadLeaderboardHandle (line 8743) | function LoadLeaderboardHandle(C: Context, L: lua_State): number {
function LoadMultiboardHandle (line 8755) | function LoadMultiboardHandle(C: Context, L: lua_State): number {
function LoadMultiboardItemHandle (line 8767) | function LoadMultiboardItemHandle(C: Context, L: lua_State): number {
function LoadTrackableHandle (line 8779) | function LoadTrackableHandle(C: Context, L: lua_State): number {
function LoadDialogHandle (line 8791) | function LoadDialogHandle(C: Context, L: lua_State): number {
function LoadButtonHandle (line 8803) | function LoadButtonHandle(C: Context, L: lua_State): number {
function LoadTextTagHandle (line 8815) | function LoadTextTagHandle(C: Context, L: lua_State): number {
function LoadLightningHandle (line 8827) | function LoadLightningHandle(C: Context, L: lua_State): number {
function LoadImageHandle (line 8839) | function LoadImageHandle(C: Context, L: lua_State): number {
function LoadUbersplatHandle (line 8851) | function LoadUbersplatHandle(C: Context, L: lua_State): number {
function LoadRegionHandle (line 8863) | function LoadRegionHandle(C: Context, L: lua_State): number {
function LoadFogStateHandle (line 8875) | function LoadFogStateHandle(C: Context, L: lua_State): number {
function LoadFogModifierHandle (line 8887) | function LoadFogModifierHandle(C: Context, L: lua_State): number {
function LoadHashtableHandle (line 8899) | function LoadHashtableHandle(C: Context, L: lua_State): number {
function HaveSavedInteger (line 8911) | function HaveSavedInteger(C: Context, L: lua_State): number {
function HaveSavedReal (line 8923) | function HaveSavedReal(C: Context, L: lua_State): number {
function HaveSavedBoolean (line 8935) | function HaveSavedBoolean(C: Context, L: lua_State): number {
function HaveSavedString (line 8947) | function HaveSavedString(C: Context, L: lua_State): number {
function HaveSavedHandle (line 8959) | function HaveSavedHandle(C: Context, L: lua_State): number {
function RemoveSavedInteger (line 8971) | function RemoveSavedInteger(C: Context, L: lua_State): number {
function RemoveSavedReal (line 8982) | function RemoveSavedReal(C: Context, L: lua_State): number {
function RemoveSavedBoolean (line 8993) | function RemoveSavedBoolean(C: Context, L: lua_State): number {
function RemoveSavedString (line 9004) | function RemoveSavedString(C: Context, L: lua_State): number {
function RemoveSavedHandle (line 9015) | function RemoveSavedHandle(C: Context, L: lua_State): number {
function FlushParentHashtable (line 9026) | function FlushParentHashtable(C: Context, L: lua_State): number {
function FlushChildHashtable (line 9035) | function FlushChildHashtable(C: Context, L: lua_State): number {
function GetRandomInt (line 9045) | function GetRandomInt(C: Context, L: lua_State): number {
function GetRandomReal (line 9056) | function GetRandomReal(C: Context, L: lua_State): number {
function CreateUnitPool (line 9067) | function CreateUnitPool(C: Context, L: lua_State): number {
function DestroyUnitPool (line 9077) | function DestroyUnitPool(C: Context, L: lua_State): number {
function UnitPoolAddUnitType (line 9086) | function UnitPoolAddUnitType(C: Context, L: lua_State): number {
function UnitPoolRemoveUnitType (line 9097) | function UnitPoolRemoveUnitType(C: Context, L: lua_State): number {
function PlaceRandomUnit (line 9107) | function PlaceRandomUnit(C: Context, L: lua_State): number {
function CreateItemPool (line 9121) | function CreateItemPool(C: Context, L: lua_State): number {
function DestroyItemPool (line 9131) | function DestroyItemPool(C: Context, L: lua_State): number {
function ItemPoolAddItemType (line 9140) | function ItemPoolAddItemType(C: Context, L: lua_State): number {
function ItemPoolRemoveItemType (line 9151) | function ItemPoolRemoveItemType(C: Context, L: lua_State): number {
function PlaceRandomItem (line 9161) | function PlaceRandomItem(C: Context, L: lua_State): number {
function ChooseRandomCreep (line 9173) | function ChooseRandomCreep(C: Context, L: lua_State): number {
function ChooseRandomNPBuilding (line 9183) | function ChooseRandomNPBuilding(C: Context, L: lua_State): number {
function ChooseRandomItem (line 9193) | function ChooseRandomItem(C: Context, L: lua_State): number {
function ChooseRandomItemEx (line 9203) | function ChooseRandomItemEx(C: Context, L: lua_State): number {
function SetRandomSeed (line 9214) | function SetRandomSeed(C: Context, L: lua_State): number {
function SetTerrainFog (line 9223) | function SetTerrainFog(C: Context, L: lua_State): number {
function ResetTerrainFog (line 9236) | function ResetTerrainFog(_C: Context, _L: lua_State): number {
function SetUnitFog (line 9245) | function SetUnitFog(C: Context, L: lua_State): number {
function SetTerrainFogEx (line 9258) | function SetTerrainFogEx(C: Context, L: lua_State): number {
function DisplayTextToPlayer (line 9273) | function DisplayTextToPlayer(C: Context, L: lua_State): number {
function DisplayTimedTextToPlayer (line 9285) | function DisplayTimedTextToPlayer(C: Context, L: lua_State): number {
function DisplayTimedTextFromPlayer (line 9298) | function DisplayTimedTextFromPlayer(C: Context, L: lua_State): number {
function ClearTextMessages (line 9311) | function ClearTextMessages(_C: Context, _L: lua_State): number {
function SetDayNightModels (line 9320) | function SetDayNightModels(C: Context, L: lua_State): number {
function SetSkyModel (line 9330) | function SetSkyModel(C: Context, L: lua_State): number {
function EnableUserControl (line 9339) | function EnableUserControl(C: Context, L: lua_State): number {
function EnableUserUI (line 9348) | function EnableUserUI(C: Context, L: lua_State): number {
function SuspendTimeOfDay (line 9357) | function SuspendTimeOfDay(C: Context, L: lua_State): number {
function SetTimeOfDayScale (line 9366) | function SetTimeOfDayScale(C: Context, L: lua_State): number {
function GetTimeOfDayScale (line 9375) | function GetTimeOfDayScale(C: Context, L: lua_State): number {
function ShowInterface (line 9385) | function ShowInterface(C: Context, L: lua_State): number {
function PauseGame (line 9395) | function PauseGame(C: Context, L: lua_State): number {
function UnitAddIndicator (line 9404) | function UnitAddIndicator(C: Context, L: lua_State): number {
function AddIndicator (line 9417) | function AddIndicator(C: Context, L: lua_State): number {
function PingMinimap (line 9430) | function PingMinimap(C: Context, L: lua_State): number {
function PingMinimapEx (line 9441) | function PingMinimapEx(C: Context, L: lua_State): number {
function EnableOcclusion (line 9456) | function EnableOcclusion(C: Context, L: lua_State): number {
function SetIntroShotText (line 9465) | function SetIntroShotText(C: Context, L: lua_State): number {
function SetIntroShotModel (line 9474) | function SetIntroShotModel(C: Context, L: lua_State): number {
function EnableWorldFogBoundary (line 9483) | function EnableWorldFogBoundary(C: Context, L: lua_State): number {
function PlayModelCinematic (line 9492) | function PlayModelCinematic(C: Context, L: lua_State): number {
function PlayCinematic (line 9501) | function PlayCinematic(C: Context, L: lua_State): number {
function ForceUIKey (line 9510) | function ForceUIKey(C: Context, L: lua_State): number {
function ForceUICancel (line 9519) | function ForceUICancel(_C: Context, _L: lua_State): number {
function DisplayLoadDialog (line 9528) | function DisplayLoadDialog(_C: Context, _L: lua_State): number {
function SetAltMinimapIcon (line 9537) | function SetAltMinimapIcon(C: Context, L: lua_State): number {
function DisableRestartMission (line 9546) | function DisableRestartMission(C: Context, L: lua_State): number {
function CreateTextTag (line 9555) | function CreateTextTag(C: Context, L: lua_State): number {
function DestroyTextTag (line 9565) | function DestroyTextTag(C: Context, L: lua_State): number {
function SetTextTagText (line 9574) | function SetTextTagText(C: Context, L: lua_State): number {
function SetTextTagPos (line 9585) | function SetTextTagPos(C: Context, L: lua_State): number {
function SetTextTagPosUnit (line 9597) | function SetTextTagPosUnit(C: Context, L: lua_State): number {
function SetTextTagColor (line 9608) | function SetTextTagColor(C: Context, L: lua_State): number {
function SetTextTagVelocity (line 9621) | function SetTextTagVelocity(C: Context, L: lua_State): number {
function SetTextTagVisibility (line 9632) | function SetTextTagVisibility(C: Context, L: lua_State): number {
function SetTextTagSuspended (line 9642) | function SetTextTagSuspended(C: Context, L: lua_State): number {
function SetTextTagPermanent (line 9652) | function SetTextTagPermanent(C: Context, L: lua_State): number {
function SetTextTagAge (line 9662) | function SetTextTagAge(C: Context, L: lua_State): number {
function SetTextTagLifespan (line 9672) | function SetTextTagLifespan(C: Context, L: lua_State): number {
function SetTextTagFadepoint (line 9682) | function SetTextTagFadepoint(C: Context, L: lua_State): number {
function SetReservedLocalHeroButtons (line 9692) | function SetReservedLocalHeroButtons(C: Context, L: lua_State): number {
function GetAllyColorFilterState (line 9701) | function GetAllyColorFilterState(C: Context, L: lua_State): number {
function SetAllyColorFilterState (line 9711) | function SetAllyColorFilterState(C: Context, L: lua_State): number {
function GetCreepCampFilterState (line 9720) | function GetCreepCampFilterState(C: Context, L: lua_State): number {
function SetCreepCampFilterState (line 9730) | function SetCreepCampFilterState(C: Context, L: lua_State): number {
function EnableMinimapFilterButtons (line 9739) | function EnableMinimapFilterButtons(C: Context, L: lua_State): number {
function EnableDragSelect (line 9749) | function EnableDragSelect(C: Context, L: lua_State): number {
function EnablePreSelect (line 9759) | function EnablePreSelect(C: Context, L: lua_State): number {
function EnableSelect (line 9769) | function EnableSelect(C: Context, L: lua_State): number {
function CreateTrackable (line 9779) | function CreateTrackable(C: Context, L: lua_State): number {
function CreateQuest (line 9792) | function CreateQuest(C: Context, L: lua_State): number {
function DestroyQuest (line 9802) | function DestroyQuest(C: Context, L: lua_State): number {
function QuestSetTitle (line 9811) | function QuestSetTitle(C: Context, L: lua_State): number {
function QuestSetDescription (line 9821) | function QuestSetDescription(C: Context, L: lua_State): number {
function QuestSetIconPath (line 9831) | function QuestSetIconPath(C: Context, L: lua_State): number {
function QuestSetRequired (line 9841) | function QuestSetRequired(C: Context, L: lua_State): number {
function QuestSetCompleted (line 9851) | function QuestSetCompleted(C: Context, L: lua_State): number {
function QuestSetDiscovered (line 9861) | function QuestSetDiscovered(C: Context, L: lua_State): number {
function QuestSetFailed (line 9871) | function QuestSetFailed(C: Context, L: lua_State): number {
function QuestSetEnabled (line 9881) | function QuestSetEnabled(C: Context, L: lua_State): number {
function IsQuestRequired (line 9891) | function IsQuestRequired(C: Context, L: lua_State): number {
function IsQuestCompleted (line 9901) | function IsQuestCompleted(C: Context, L: lua_State): number {
function IsQuestDiscovered (line 9911) | function IsQuestDiscovered(C: Context, L: lua_State): number {
function IsQuestFailed (line 9921) | function IsQuestFailed(C: Context, L: lua_State): number {
function IsQuestEnabled (line 9931) | function IsQuestEnabled(C: Context, L: lua_State): number {
function QuestCreateItem (line 9941) | function QuestCreateItem(C: Context, L: lua_State): number {
function QuestItemSetDescription (line 9951) | function QuestItemSetDescription(C: Context, L: lua_State): number {
function QuestItemSetCompleted (line 9961) | function QuestItemSetCompleted(C: Context, L: lua_State): number {
function IsQuestItemCompleted (line 9971) | function IsQuestItemCompleted(C: Context, L: lua_State): number {
function CreateDefeatCondition (line 9981) | function CreateDefeatCondition(C: Context, L: lua_State): number {
function DestroyDefeatCondition (line 9991) | function DestroyDefeatCondition(C: Context, L: lua_State): number {
function DefeatConditionSetDescription (line 10000) | function DefeatConditionSetDescription(C: Context, L: lua_State): number {
function FlashQuestDialogButton (line 10010) | function FlashQuestDialogButton(_C: Context, _L: lua_State): number {
function ForceQuestDialogUpdate (line 10019) | function ForceQuestDialogUpdate(_C: Context, _L: lua_State): number {
function CreateTimerDialog (line 10028) | function CreateTimerDialog(C: Context, L: lua_State): number {
function DestroyTimerDialog (line 10038) | function DestroyTimerDialog(C: Context, L: lua_State): number {
function TimerDialogSetTitle (line 10047) | function TimerDialogSetTitle(C: Context, L: lua_State): number {
function TimerDialogSetTitleColor (line 10057) | function TimerDialogSetTitleColor(C: Context, L: lua_State): number {
function TimerDialogSetTimeColor (line 10070) | function TimerDialogSetTimeColor(C: Context, L: lua_State): number {
function TimerDialogSetSpeed (line 10083) | function TimerDialogSetSpeed(C: Context, L: lua_State): number {
function TimerDialogDisplay (line 10093) | function TimerDialogDisplay(C: Context, L: lua_State): number {
function IsTimerDialogDisplayed (line 10103) | function IsTimerDialogDisplayed(C: Context, L: lua_State): number {
function TimerDialogSetRealTimeRemaining (line 10113) | function TimerDialogSetRealTimeRemaining(C: Context, L: lua_State): numb...
function CreateLeaderboard (line 10123) | function CreateLeaderboard(C: Context, L: lua_State): number {
function DestroyLeaderboard (line 10133) | function DestroyLeaderboard(C: Context, L: lua_State): number {
function LeaderboardDisplay (line 10142) | function LeaderboardDisplay(C: Context, L: lua_State): number {
function IsLeaderboardDisplayed (line 10152) | function IsLeaderboardDisplayed(C: Context, L: lua_State): number {
function LeaderboardGetItemCount (line 10162) | function LeaderboardGetItemCount(C: Context, L: lua_State): number {
function LeaderboardSetSizeByItemCount (line 10172) | function LeaderboardSetSizeByItemCount(C: Context, L: lua_State): number {
function LeaderboardAddItem (line 10182) | function LeaderboardAddItem(C: Context, L: lua_State): number {
function LeaderboardRemoveItem (line 10194) | function LeaderboardRemoveItem(C: Context, L: lua_State): number {
function LeaderboardRemovePlayerItem (line 10204) | function LeaderboardRemovePlayerItem(C: Context, L: lua_State): number {
function LeaderboardClear (line 10214) | function LeaderboardClear(C: Context, L: lua_State): number {
function LeaderboardSortItemsByValue (line 10223) | function LeaderboardSortItemsByValue(C: Context, L: lua_State): number {
function LeaderboardSortItemsByPlayer (line 10233) | function LeaderboardSortItemsByPlayer(C: Context, L: lua_State): number {
function LeaderboardSortItemsByLabel (line 10243) | function LeaderboardSortItemsByLabel(C: Context, L: lua_State): number {
function LeaderboardHasPlayerItem (line 10253) | function LeaderboardHasPlayerItem(C: Context, L: lua_State): number {
function LeaderboardGetPlayerIndex (line 10264) | function LeaderboardGetPlayerIndex(C: Context, L: lua_State): number {
function LeaderboardSetLabel (line 10275) | function LeaderboardSetLabel(C: Context, L: lua_State): number {
function LeaderboardGetLabelText (line 10285) | function LeaderboardGetLabelText(C: Context, L: lua_State): number {
function PlayerSetLeaderboard (line 10295) | function PlayerSetLeaderboard(C: Context, L: lua_State): number {
function PlayerGetLeaderboard (line 10305) | function PlayerGetLeaderboard(C: Context, L: lua_State): number {
function LeaderboardSetLabelColor (line 10315) | function LeaderboardSetLabelColor(C: Context, L: lua_State): number {
function LeaderboardSetValueColor (line 10328) | function LeaderboardSetValueColor(C: Context, L: lua_State): number {
function LeaderboardSetStyle (line 10341) | function LeaderboardSetStyle(C: Context, L: lua_State): number {
function LeaderboardSetItemValue (line 10354) | function LeaderboardSetItemValue(C: Context, L: lua_State): number {
function LeaderboardSetItemLabel (line 10365) | function LeaderboardSetItemLabel(C: Context, L: lua_State): number {
function LeaderboardSetItemStyle (line 10376) | function LeaderboardSetItemStyle(C: Context, L: lua_State): number {
function LeaderboardSetItemLabelColor (line 10389) | function LeaderboardSetItemLabelColor(C: Context, L: lua_State): number {
function LeaderboardSetItemValueColor (line 10403) | function LeaderboardSetItemValueColor(C: Context, L: lua_State): number {
function CreateMultiboard (line 10417) | function CreateMultiboard(C: Context, L: lua_State): number {
function DestroyMultiboard (line 10427) | function DestroyMultiboard(C: Context, L: lua_State): number {
function MultiboardDisplay (line 10436) | function MultiboardDisplay(C: Context, L: lua_State): number {
function IsMultiboardDisplayed (line 10446) | function IsMultiboardDisplayed(C: Context, L: lua_State): number {
function MultiboardMinimize (line 10456) | function MultiboardMinimize(C: Context, L: lua_State): number {
function IsMultiboardMinimized (line 10466) | function IsMultiboardMinimized(C: Context, L: lua_State): number {
function MultiboardClear (line 10476) | function MultiboardClear(C: Context, L: lua_State): number {
function MultiboardSetTitleText (line 10485) | function MultiboardSetTitleText(C: Context, L: lua_State): number {
function MultiboardGetTitleText (line 10495) | function MultiboardGetTitleText(C: Context, L: lua_State): number {
function MultiboardSetTitleTextColor (line 10505) | function MultiboardSetTitleTextColor(C: Context, L: lua_State): number {
function MultiboardGetRowCount (line 10518) | function MultiboardGetRowCount(C: Context, L: lua_State): number {
function MultiboardGetColumnCount (line 10528) | function MultiboardGetColumnCount(C: Context, L: lua_State): number {
function MultiboardSetColumnCount (line 10538) | function MultiboardSetColumnCount(C: Context, L: lua_State): number {
function MultiboardSetRowCount (line 10548) | function MultiboardSetRowCount(C: Context, L: lua_State): number {
function MultiboardSetItemsStyle (line 10558) | function MultiboardSetItemsStyle(C: Context, L: lua_State): number {
function MultiboardSetItemsValue (line 10569) | function MultiboardSetItemsValue(C: Context, L: lua_State): number {
function MultiboardSetItemsValueColor (line 10579) | function MultiboardSetItemsValueColor(C: Context, L: lua_State): number {
function MultiboardSetItemsWidth (line 10592) | function MultiboardSetItemsWidth(C: Context, L: lua_State): number {
function MultiboardSetItemsIcon (line 10602) | function MultiboardSetItemsIcon(C: Context, L: lua_State): number {
function MultiboardGetItem (line 10612) | function MultiboardGetItem(C: Context, L: lua_State): number {
function MultiboardReleaseItem (line 10624) | function MultiboardReleaseItem(C: Context, L: lua_State): number {
function MultiboardSetItemStyle (line 10633) | function MultiboardSetItemStyle(C: Context, L: lua_State): number {
function MultiboardSetItemValue (line 10644) | function MultiboardSetItemValue(C: Context, L: lua_State): number {
function MultiboardSetItemValueColor (line 10654) | function MultiboardSetItemValueColor(C: Context, L: lua_State): number {
function MultiboardSetItemWidth (line 10667) | function MultiboardSetItemWidth(C: Context, L: lua_State): number {
function MultiboardSetItemIcon (line 10677) | function MultiboardSetItemIcon(C: Context, L: lua_State): number {
function MultiboardSuppressDisplay (line 10687) | function MultiboardSuppressDisplay(C: Context, L: lua_State): number {
function SetCameraPosition (line 10696) | function SetCameraPosition(C: Context, L: lua_State): number {
function SetCameraQuickPosition (line 10706) | function SetCameraQuickPosition(C: Context, L: lua_State): number {
function SetCameraBounds (line 10716) | function SetCameraBounds(C: Context, L: lua_State): number {
function StopCamera (line 10732) | function StopCamera(_C: Context, _L: lua_State): number {
function ResetToGameCamera (line 10741) | function ResetToGameCamera(C: Context, L: lua_State): number {
function PanCameraTo (line 10750) | function PanCameraTo(C: Context, L: lua_State): number {
function PanCameraToTimed (line 10760) | function PanCameraToTimed(C: Context, L: lua_State): number {
function PanCameraToWithZ (line 10771) | function PanCameraToWithZ(C: Context, L: lua_State): number {
function PanCameraToTimedWithZ (line 10782) | function PanCameraToTimedWithZ(C: Context, L: lua_State): number {
function SetCinematicCamera (line 10794) | function SetCinematicCamera(C: Context, L: lua_State): number {
function SetCameraRotateMode (line 10803) | function SetCameraRotateMode(C: Context, L: lua_State): number {
function SetCameraField (line 10815) | function SetCameraField(C: Context, L: lua_State): number {
function AdjustCameraField (line 10826) | function AdjustCameraField(C: Context, L: lua_State): number {
function SetCameraTargetController (line 10837) | function SetCameraTargetController(C: Context, L: lua_State): number {
function SetCameraOrientController (line 10849) | function SetCameraOrientController(C: Context, L: lua_State): number {
function CreateCameraSetup (line 10860) | function CreateCameraSetup(C: Context, L: lua_State): number {
function CameraSetupSetField (line 10870) | function CameraSetupSetField(C: Context, L: lua_State): number {
function CameraSetupGetField (line 10882) | function CameraSetupGetField(C: Context, L: lua_State): number {
function CameraSetupSetDestPosition (line 10893) | function CameraSetupSetDestPosition(C: Context, L: lua_State): number {
function CameraSetupGetDestPositionLoc (line 10905) | function CameraSetupGetDestPositionLoc(C: Context, L: lua_State): number {
function CameraSetupGetDestPositionX (line 10915) | function CameraSetupGetDestPositionX(C: Context, L: lua_State): number {
function CameraSetupGetDestPositionY (line 10925) | function CameraSetupGetDestPositionY(C: Context, L: lua_State): number {
function CameraSetupApply (line 10935) | function CameraSetupApply(C: Context, L: lua_State): number {
function CameraSetupApplyWithZ (line 10946) | function CameraSetupApplyWithZ(C: Context, L: lua_State): number {
function CameraSetupApplyForceDuration (line 10956) | function CameraSetupApplyForceDuration(C: Context, L: lua_State): number {
function CameraSetupApplyForceDurationWithZ (line 10967) | function CameraSetupApplyForceDurationWithZ(C: Context, L: lua_State): n...
function CameraSetTargetNoise (line 10978) | function CameraSetTargetNoise(C: Context, L: lua_State): number {
function CameraSetSourceNoise (line 10988) | function CameraSetSourceNoise(C: Context, L: lua_State): number {
function CameraSetTargetNoiseEx (line 10998) | function CameraSetTargetNoiseEx(C: Context, L: lua_State): number {
function CameraSetSourceNoiseEx (line 11009) | function CameraSetSourceNoiseEx(C: Context, L: lua_State): number {
function CameraSetSmoothingFactor (line 11020) | function CameraSetSmoothingFactor(C: Context, L: lua_State): number {
function SetCineFilterTexture (line 11029) | function SetCineFilterTexture(C: Context, L: lua_State): number {
function SetCineFilterBlendMode (line 11038) | function SetCineFilterBlendMode(C: Context, L: lua_State): number {
function SetCineFilterTexMapFlags (line 11047) | function SetCineFilterTexMapFlags(C: Context, L: lua_State): number {
function SetCineFilterStartUV (line 11056) | func
Condensed preview — 496 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,231K chars).
[
{
"path": ".eslintignore",
"chars": 51,
"preview": "dist\nclients\nthirdparty\nwebpack.config.js\nclean.js\n"
},
{
"path": ".eslintrc.json",
"chars": 1108,
"preview": "{\n \"parser\": \"@typescript-eslint/parser\",\n \"parserOptions\": {\n \"ecmaVersion\": 9,\n \"sourceType\": \"module\",\n \"p"
},
{
"path": ".gitignore",
"chars": 35,
"preview": "node_modules\ndist\npackage-lock.json"
},
{
"path": ".npmignore",
"chars": 133,
"preview": ".*\n**/tsconfig.json\n**/webpack.config.js\nnode_modules\nViewer.code-workspace\nViewer.sublime-project\nsrc\nclients\ndist/clie"
},
{
"path": "CONTRIBUTING.md",
"chars": 676,
"preview": "If you want to contribute, here are a few notes:\n\n1) If the changes are related in any way to the viewer itself (parsers"
},
{
"path": "LICENSE",
"chars": 1088,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2013-2021 Chananya Freiman\n\nPermission is hereby granted, free of charge, to any pe"
},
{
"path": "README.md",
"chars": 22030,
"preview": "**NO LONGER ACTIVELY MAINTAINED.**\n\nmdx-m3-viewer\n=============\n\nAt the core of it, a 3D model viewer for MDX and M3 mod"
},
{
"path": "Viewer.code-workspace",
"chars": 398,
"preview": "{\n\t\"folders\": [\n\t\t{\n\t\t\t\"path\": \".\"\n\t\t}\n\t],\n\t\"settings\": {\n\t\t\"editor.tabSize\": 2,\n\t\t\"files.eol\": \"\\n\",\n\t\t\"typescript.pref"
},
{
"path": "Viewer.sublime-project",
"chars": 160,
"preview": "{\n \"folders\":\n [\n {\n \"path\": \".\"\n }\n ],\n \"tab_size\": 2,\n \"translate_tabs_to_spac"
},
{
"path": "clean.js",
"chars": 778,
"preview": "// See https://stackoverflow.com/a/52526549/2503048\n\nvar fs = require('fs');\n\nfunction deleteFolderRecursive(path) {\n i"
},
{
"path": "clients/README.md",
"chars": 710,
"preview": "Over the years, many different clients were made with this library. Most of them have gone into the pages of forgotten h"
},
{
"path": "clients/downgrader/index.html",
"chars": 613,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title></title>\n <meta charset=\"utf-8\" />\n</head>\n\n<body>\n <div>\n Drag "
},
{
"path": "clients/downgrader/index.js",
"chars": 1827,
"preview": "import War3Map from '../../src/parsers/w3x/map';\nimport War3MapW3i from '../../src/parsers/w3x/w3i/file';\nimport War3Map"
},
{
"path": "clients/example/README.md",
"chars": 99,
"preview": "A simple example client.\n\nThanks to Frank from the HiveWorkshop for the MDX model and BLP texture!\n"
},
{
"path": "clients/example/index.html",
"chars": 211,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>MDX Example</title>\n <meta charset=\"utf-8\" />\n</head>\n\n<body>\n <canvas "
},
{
"path": "clients/example/index.js",
"chars": 3107,
"preview": "import * as ModelViewer from '../../src/';\nimport { setupCamera } from '../shared/camera';\nconst handlers = ModelViewer."
},
{
"path": "clients/map/README.md",
"chars": 83,
"preview": "A Warcraft 3 map viewer client. Drag and drop a map file (W3X, W3M) into the page.\n"
},
{
"path": "clients/map/index.html",
"chars": 1256,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Map | HIVE</title>\n <meta charset=\"utf-8\" />\n\n <style>\n html,\n "
},
{
"path": "clients/map/index.js",
"chars": 2412,
"preview": "import { basename, extname } from \"../../src/common/path\";\nimport War3MapViewer from '../../src/viewer/handlers/w3x/view"
},
{
"path": "clients/mdlx/index.html",
"chars": 638,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>MDX <-> MDL</title>\n <meta charset=\"utf-8\" />\n\n <style>\n #"
},
{
"path": "clients/mdlx/index.js",
"chars": 1212,
"preview": "import { extname } from \"../../src/common/path\";\nimport { version } from \"../../src/version\";\nimport Model from '../../s"
},
{
"path": "clients/mdlxoptimizer/index.html",
"chars": 240,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>MDLX Optimizer</title>\n <meta charset=\"utf-8\" />\n</head>\n\n<body>\n <scri"
},
{
"path": "clients/mdlxoptimizer/index.ts",
"chars": 6624,
"preview": "import { extname } from \"../../src/common/path\";\n// @ts-ignore\nimport { getAllFileEntries, readEntry } from \"../shared/u"
},
{
"path": "clients/melee/README.md",
"chars": 137,
"preview": "A small tool to fake a map as a Melee map. This changes the map's icon when it is listed in the game. I don't know of an"
},
{
"path": "clients/melee/index.html",
"chars": 390,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Melee</title>\n <meta charset=\"utf-8\" />\n <style>\n .center {\n text-ali"
},
{
"path": "clients/melee/index.js",
"chars": 1384,
"preview": "let w3x = ModelViewer.default.parsers.w3x;\n\nfunction onLocalLoaded(e, name) {\n let buffer = e.target.result;\n\n con"
},
{
"path": "clients/rebuild/README.md",
"chars": 372,
"preview": "This is a small proof of concept of rebuilding a \"protected\" map.\nThis is done by running the map's Jass script with a v"
},
{
"path": "clients/rebuild/components/rebuilder.js",
"chars": 4002,
"preview": "import { extname } from \"../../../src/common/path\";\nimport War3Map from \"../../../src/parsers/w3x/map\";\nimport UnitsDooF"
},
{
"path": "clients/rebuild/index.html",
"chars": 574,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Rebuilder</title>\n <meta charset=\"utf-8\" />\n\n <style>\n .log {}\n\n"
},
{
"path": "clients/rebuild/index.js",
"chars": 412,
"preview": "import Rebuilder from './components/rebuilder';\n\nconst rebuilder = new Rebuilder(document.body);\n\ndocument.addEventListe"
},
{
"path": "clients/recorder/README.md",
"chars": 113,
"preview": "This client is used to record unit animations into a collection of images, that can be downloaded in a zip file.\n"
},
{
"path": "clients/recorder/index.html",
"chars": 1396,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Recorder | HIVE</title>\n <meta charset=\"utf-8\" />\n\n <style>\n htm"
},
{
"path": "clients/recorder/index.js",
"chars": 5509,
"preview": "ModelViewer = ModelViewer.default;\n\nlet common = ModelViewer.common;\nlet quat = common.glMatrix.quat;\nlet vec3 = common."
},
{
"path": "clients/sanitytest/README.md",
"chars": 172,
"preview": "This client runs the MDX sanity tester, and shows the information in a graphical manner.\nIt is used on the Hiveworkshop "
},
{
"path": "clients/sanitytest/components/logger.js",
"chars": 2421,
"preview": "import Component from \"../../shared/component\";\nimport Toggle from \"../../shared/components/toggle\";\nimport { createElem"
},
{
"path": "clients/sanitytest/components/mdlview.js",
"chars": 1490,
"preview": "import mdlStructure from \"../../../src/utils/mdlx/mdlstructure\";\nimport Component from \"../../shared/component\";\nimport "
},
{
"path": "clients/sanitytest/components/sanitytester.js",
"chars": 10146,
"preview": "import { basename, extname } from \"../../../src/common/path\";\nimport War3Map from \"../../../src/parsers/w3x/map\";\nimport"
},
{
"path": "clients/sanitytest/components/teamcolors.js",
"chars": 1024,
"preview": "export const TEAM_COLORS = [\n { name: 'Red', color: '#ff0402' },\n { name: 'Blue', color: '#0042ff' },\n { name: 'Teal'"
},
{
"path": "clients/sanitytest/components/testmeta.js",
"chars": 1551,
"preview": "import Component from \"../../shared/component\";\nimport { createElement } from \"../../shared/domutils\";\n\nfunction singleO"
},
{
"path": "clients/sanitytest/components/testresults.js",
"chars": 7079,
"preview": "import { imageDataToImage } from \"../../../src/common/canvas\";\nimport Component from \"../../shared/component\";\nimport { "
},
{
"path": "clients/sanitytest/components/tooltips.js",
"chars": 2867,
"preview": "export default function getTooltip(message) {\n if (message.includes('does not match the number of sequences')) { // Num"
},
{
"path": "clients/sanitytest/components/viewer.js",
"chars": 12976,
"preview": "import ModelViewer from '../../../src/viewer/viewer';\nimport mdxHandler from '../../../src/viewer/handlers/mdx/handler';"
},
{
"path": "clients/sanitytest/components/viewercontrols.js",
"chars": 6254,
"preview": "import { DebugRenderMode } from '../../../src/viewer/viewer';\nimport Component from \"../../shared/component\";\nimport Tog"
},
{
"path": "clients/sanitytest/index.css",
"chars": 5040,
"preview": "html,\nbody {\n padding: 0;\n margin: 0;\n font-family: monaco, monospace;\n font-size: 14px;\n}\n\n.client {\n d"
},
{
"path": "clients/sanitytest/index.html",
"chars": 224,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Sanity Test</title>\n <meta charset=\"utf-8\" />\n <link href=\"index.css\" r"
},
{
"path": "clients/sanitytest/index.js",
"chars": 446,
"preview": "import SanityTester from './components/sanitytester';\n\nconst tester = new SanityTester(document.body);\n\ndocument.addEven"
},
{
"path": "clients/sanitytest/test.js",
"chars": 2021,
"preview": "import { basename, extname } from \"../../src/common/path\";\nimport MdlxModel from '../../src/parsers/mdlx/model';\nimport "
},
{
"path": "clients/shared/camera.js",
"chars": 9250,
"preview": "import { vec3, quat } from 'gl-matrix';\n\n// Backwards compat with existing clients.\nexport function setupCamera(scene, o"
},
{
"path": "clients/shared/component.js",
"chars": 442,
"preview": "import { createElement, hideElement, showElement } from './domutils';\n\nexport default class Component {\n constructor(op"
},
{
"path": "clients/shared/components/toggle.js",
"chars": 606,
"preview": "import Component from \"../component\";\n\nexport default class Toggle extends Component {\n constructor(offName, onName, ca"
},
{
"path": "clients/shared/domutils.js",
"chars": 2048,
"preview": "export function createElement(options) {\n let tagName = 'div';\n\n if (options && options.tagName) {\n tagName = optio"
},
{
"path": "clients/shared/localorhive.js",
"chars": 518,
"preview": "import urlWithParams from '../../src/common/urlwithparams';\n\nexport default function localOrHive(src, params) {\n src = "
},
{
"path": "clients/shared/utils.js",
"chars": 1732,
"preview": "// Returns a promise that will resolve in the next VM event loop step.\n// Used to force the VM to wait, allowing the DOM"
},
{
"path": "clients/tests/README.md",
"chars": 320,
"preview": "The unit tester.\nBy definition, a test is comprised of an input scene, defined by the resources it needs and the setup s"
},
{
"path": "clients/tests/components/unittester.js",
"chars": 5412,
"preview": "import { version } from '../../../src/version';\nimport UnitTester from '../unittester';\nimport Component from '../../sha"
},
{
"path": "clients/tests/index.html",
"chars": 752,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>Unit Tests</title>\n <meta charset=\"utf-8\" />\n\n <style>\n button {\n mar"
},
{
"path": "clients/tests/index.js",
"chars": 144,
"preview": "import UnitTester from './components/unittester';\n\nconst tester = new UnitTester(document.body);\n\n// For debugging etc.\n"
},
{
"path": "clients/tests/solvers.js",
"chars": 425,
"preview": "import localOrHive from \"../shared/localorhive\";\n\nexport const wc3Solver = (path, params) => {\n path = localOrHive(path"
},
{
"path": "clients/tests/tests/base.js",
"chars": 1513,
"preview": "import { wc3Solver, sc2Solver } from \"../solvers\";\n\nexport const baseTests = {\n name: 'base',\n tests: [\n {\n na"
},
{
"path": "clients/tests/tests/m3.js",
"chars": 2710,
"preview": "import { sc2Solver } from \"../solvers\";\n\nexport const m3Tests = {\n name: 'm3',\n tests: [\n {\n name: 'base',\n "
},
{
"path": "clients/tests/tests/mdx.js",
"chars": 11840,
"preview": "import { quat } from \"gl-matrix\";\nimport { wc3Solver } from \"../solvers\";\n\nexport const mdxTests = {\n name: 'mdx',\n te"
},
{
"path": "clients/tests/tests/mdxprimitives.js",
"chars": 11868,
"preview": "import { quat } from \"gl-matrix\";\nimport createPrimitive from \"../../../src/utils/mdlx/primitives/createprimitive\";\nimpo"
},
{
"path": "clients/tests/unittester.js",
"chars": 5974,
"preview": "import * as resemble from '../thirdparty/resemble';\nimport seededRandom from '../../src/common/seededrandom';\nimport { b"
},
{
"path": "clients/textureatlas/index.html",
"chars": 2626,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>KEKW</title>\n\n <meta charset=\"utf-8\" />\n\n <style>\n .row {\n display: f"
},
{
"path": "clients/textureatlas/index.js",
"chars": 4995,
"preview": "class TextureAtlasGenerator {\n constructor() {\n this.inputWidthElement = document.getElementById('input_width');\n "
},
{
"path": "clients/thirdparty/filesaver.js",
"chars": 11727,
"preview": "/* FileSaver.js\n * A saveAs() & saveTextAs() FileSaver implementation.\n * 2014-06-24\n *\n * Modify by Brian Chen\n * A"
},
{
"path": "clients/thirdparty/resemble.js",
"chars": 33574,
"preview": "// NOTE: require(\"canvas-prebuilt\") was commented because it makes webpack throw annoying errors, since my code is runni"
},
{
"path": "clients/weu/README.md",
"chars": 844,
"preview": "This client is used to recover old maps that were created in 3rd party World Editor applications, such as World Editor U"
},
{
"path": "clients/weu/TriggerDataCustom.txt",
"chars": 1603,
"preview": "[TriggerParams]\n\nUnitStateMaxLifeSec=0,unitstate,UNIT_STATE_MAX_LIFE,WESTRING_USTATE_MAXLIFE\n\nSaveLoadOp0=0,integer,0,\"0"
},
{
"path": "clients/weu/TriggerDataPTR129.txt",
"chars": 311677,
"preview": "//***************************************************************************\n[TriggerCategories]\n// Defines categories "
},
{
"path": "clients/weu/TriggerDataWEU.txt",
"chars": 461110,
"preview": "[TriggerCategories]\nTC_ARITHMETIC=WESTRING_TRIGCAT_ARITHMETIC,ReplaceableTextures\\WorldEditUI\\Actions-AI,1\nTC_NOTHING=WE"
},
{
"path": "clients/weu/TriggerDataYDWE.txt",
"chars": 514962,
"preview": "\n\n\n\n\n\n\n\n\n\n\n\n//***************************************************************************\n[TriggerCategories]\n// Defines"
},
{
"path": "clients/weu/components/weuchanges.js",
"chars": 932,
"preview": "import Component from '../../shared/component';\nimport { addTextToRow } from '../../shared/domutils';\n\nexport default cl"
},
{
"path": "clients/weu/components/weuconverter.js",
"chars": 6336,
"preview": "\nimport { extname } from '../../../src/common/path';\nimport MpqArchive from '../../../src/parsers/mpq/archive';\nimport {"
},
{
"path": "clients/weu/components/weumeta.js",
"chars": 1239,
"preview": "\nimport Component from '../../shared/component';\nimport Toggle from '../../shared/components/toggle';\nimport { createEle"
},
{
"path": "clients/weu/index.css",
"chars": 1112,
"preview": "html,\nbody {\n width: 100%;\n height: 100%;\n margin: 0;\n}\n\n.client {\n display: grid;\n width: 100%;\n hei"
},
{
"path": "clients/weu/index.html",
"chars": 274,
"preview": "<!DOCTYPE html>\n<html>\n\n<head>\n <title>WEU Converter</title>\n <meta charset=\"utf-8\" />\n <link href=\"index.css\""
},
{
"path": "clients/weu/index.js",
"chars": 368,
"preview": "import WeuConverter from './components/weuconverter';\n\nconst converter = new WeuConverter(document.body);\n\ndocument.addE"
},
{
"path": "package.json",
"chars": 1229,
"preview": "{\n \"name\": \"mdx-m3-viewer\",\n \"version\": \"5.13.0\",\n \"description\": \"A browser WebGL model viewer. Mainly focused on mo"
},
{
"path": "src/common/arrayunique.ts",
"chars": 241,
"preview": "/**\n * Returns an array that only contains unique values found in the source array.\n */\nexport default function unique<T"
},
{
"path": "src/common/audio.ts",
"chars": 440,
"preview": "let audioContext: OfflineAudioContext;\n\n// Some browsers don't have OfflineAudioContext or AudioContext.\nif (typeof Offl"
},
{
"path": "src/common/binarystream.ts",
"chars": 20374,
"preview": "import { bytesOf } from './bytesof';\nimport { boundIndexOf } from './searches';\nimport { uint8ToInt8, uint8ToInt16, uint"
},
{
"path": "src/common/bitstream.ts",
"chars": 1468,
"preview": "import { bytesOf } from './bytesof';\n\n/**\n * A bit stream.\n */\nexport default class BitStream {\n buffer: ArrayBuffer;\n "
},
{
"path": "src/common/bytesof.ts",
"chars": 401,
"preview": "import { encodeUtf8 } from './utf8';\n\n/**\n * Return the given buffer as a Uint8Array.\n * \n * Strings are encoded as UTF8"
},
{
"path": "src/common/canvas.ts",
"chars": 2860,
"preview": "let canvas: HTMLCanvasElement;\nlet ctx: CanvasRenderingContext2D;\nlet canvas2: HTMLCanvasElement;\nlet ctx2: CanvasRender"
},
{
"path": "src/common/convertbitrange.ts",
"chars": 417,
"preview": "/**\n * Returns a number, which when multiplied with a number of fromBits bits, will convert it to a toBits bits number.\n"
},
{
"path": "src/common/dxt.ts",
"chars": 10091,
"preview": "import convertBitRange from './convertbitrange';\n\nconst dxt4to8 = convertBitRange(4, 8);\nconst dxt5to8 = convertBitRange"
},
{
"path": "src/common/fetchdatatype.ts",
"chars": 2203,
"preview": "/**\n * The valid data type names for resource fetches.\n */\nexport type FetchDataTypeName = 'image' | 'text' | 'arrayBuff"
},
{
"path": "src/common/gl-matrix-addon.ts",
"chars": 6118,
"preview": "import { vec3, vec4, quat, mat4 } from 'gl-matrix';\n\nexport const VEC3_UNIT_X = vec3.fromValues(1, 0, 0);\nexport const V"
},
{
"path": "src/common/index.ts",
"chars": 535,
"preview": "import * as glMatrix from 'gl-matrix';\nimport * as glMatrixAddon from './gl-matrix-addon';\nimport * as math from './math"
},
{
"path": "src/common/isformat.ts",
"chars": 1973,
"preview": "/**\n * Detects if the given object is a PNG source.\n * \n * PNG starts with [89 50 4E 47 0D 0A 1A 0A]\n */\nexport function"
},
{
"path": "src/common/math.ts",
"chars": 2268,
"preview": "/**\n * Convert from degrees to radians.\n */\nexport function degToRad(degrees: number): number {\n return degrees * (Math"
},
{
"path": "src/common/path.ts",
"chars": 1036,
"preview": "/**\n * Returns the base name of a file path.\n * \n * Path/To/My/File.ext => File.ext\n */\nexport function basename(path: s"
},
{
"path": "src/common/searches.ts",
"chars": 1535,
"preview": "export function isStringInBytes(buffer: Uint8Array, target: string, offset = 0, length = Infinity): boolean {\n const st"
},
{
"path": "src/common/seededrandom.ts",
"chars": 330,
"preview": "/**\n * Return a function that works in the same exact way as Math.random(), but with the given seed.\n * See http://indie"
},
{
"path": "src/common/sstrhash2.ts",
"chars": 2424,
"preview": "function hash(buffer: Uint8Array): number {\n let o = 0;\n let len = buffer.length;\n let a = 0x9e3779b9;\n let b = 0x9e"
},
{
"path": "src/common/stringreverse.ts",
"chars": 121,
"preview": "/**\n * Reverses a string.\n */\nexport default function reverse(s: string): string {\n return [...s].reverse().join('');\n}"
},
{
"path": "src/common/typecast.ts",
"chars": 5735,
"preview": "const buffer = new ArrayBuffer(8);\nconst int8 = new Int8Array(buffer);\nconst int16 = new Int16Array(buffer);\nconst int32"
},
{
"path": "src/common/urlwithparams.ts",
"chars": 583,
"preview": "/**\n * Appends url parameters given in params to the url given in src.\n * \n * The source url can have url parameters alr"
},
{
"path": "src/common/utf8.ts",
"chars": 1678,
"preview": "const decoder = new TextDecoder();\nconst encoder = new TextEncoder();\n\n/**\n * Decode bytes as a UTF8 string.\n */\nexport "
},
{
"path": "src/index.ts",
"chars": 225,
"preview": "import { version } from './version';\nimport common from './common';\nimport parsers from './parsers';\nimport viewer from "
},
{
"path": "src/parsers/blp/image.ts",
"chars": 4117,
"preview": "import BitStream from '../../common/bitstream';\nimport { bytesOf } from '../../common/bytesof';\nimport convertBitRange f"
},
{
"path": "src/parsers/blp/index.ts",
"chars": 75,
"preview": "import { BlpImage as Image } from './image';\n\nexport default {\n Image,\n};\n"
},
{
"path": "src/parsers/blp/isformat.ts",
"chars": 368,
"preview": "/**\n * Detects if the given object is a BLP source.\n */\nexport default function isBlp(bytes: unknown): boolean {\n if (b"
},
{
"path": "src/parsers/blp/jpg.js",
"chars": 26930,
"preview": "/* eslint-disable */\n\n/* Copyright 2017 Mozilla Foundation\n *\n * Licensed under the Apache License, Version 2.0 (the 'Li"
},
{
"path": "src/parsers/dds/image.ts",
"chars": 3681,
"preview": "import { base256ToString } from '../../common/typecast';\nimport { decodeDxt1, decodeDxt3, decodeDxt5, decodeRgtc } from "
},
{
"path": "src/parsers/dds/index.ts",
"chars": 228,
"preview": "import { DdsImage as Image, FOURCC_DXT1, FOURCC_DXT3, FOURCC_DXT5, FOURCC_ATI2 } from './image';\nimport isDds from './is"
},
{
"path": "src/parsers/dds/isformat.ts",
"chars": 368,
"preview": "/**\n * Detects if the given object is a DDS source.\n */\nexport default function isDds(bytes: unknown): boolean {\n if (b"
},
{
"path": "src/parsers/index.ts",
"chars": 309,
"preview": "import ini from './ini';\nimport slk from './slk';\nimport m3 from './m3';\nimport mdlx from './mdlx';\nimport mpq from './m"
},
{
"path": "src/parsers/ini/file.ts",
"chars": 1952,
"preview": "/**\n * An INI section.\n */\nexport type IniSection = Map<string, string>;\n\n/**\n * An INI file.\n */\nexport class IniFile {"
},
{
"path": "src/parsers/ini/index.ts",
"chars": 71,
"preview": "import { IniFile as File } from './file';\n\nexport default {\n File,\n};\n"
},
{
"path": "src/parsers/m3/animationreference.ts",
"chars": 2436,
"preview": "import BinaryStream from '../../common/binarystream';\n\n/**\n * The base class to all animation references.\n */\nexport abs"
},
{
"path": "src/parsers/m3/attachmentpoint.ts",
"chars": 493,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/batch.ts",
"chars": 591,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\n\n/**\n * A batch.\n */\nexport"
},
{
"path": "src/parsers/m3/bone.ts",
"chars": 1010,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/boundingshape.ts",
"chars": 810,
"preview": "import BinaryStream from '../../common/binarystream';\n\n/**\n * A bounding shape.\n */\nexport default class BoundingShape {"
},
{
"path": "src/parsers/m3/boundingsphere.ts",
"chars": 357,
"preview": "import BinaryStream from '../../common/binarystream';\n\n/**\n * A bounding sphere.\n */\nexport default class BoundingSphere"
},
{
"path": "src/parsers/m3/camera.ts",
"chars": 1188,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/division.ts",
"chars": 635,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/event.ts",
"chars": 1014,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/index.ts",
"chars": 98,
"preview": "import Model from './model';\nimport isM3 from './isformat';\n\nexport default {\n Model,\n isM3,\n};\n"
},
{
"path": "src/parsers/m3/indexentry.ts",
"chars": 7331,
"preview": "import reverse from '../../common/stringreverse';\nimport BinaryStream from '../../common/binarystream';\nimport Md34 from"
},
{
"path": "src/parsers/m3/isformat.ts",
"chars": 367,
"preview": "/**\n * Detects if the given object is an M3 source.\n */\nexport default function isM3(bytes: unknown): boolean {\n if (by"
},
{
"path": "src/parsers/m3/layer.ts",
"chars": 3711,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/light.ts",
"chars": 1428,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport { Float32AnimationRe"
},
{
"path": "src/parsers/m3/materialreference.ts",
"chars": 428,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\n\n/**\n * A material referenc"
},
{
"path": "src/parsers/m3/md34.ts",
"chars": 590,
"preview": "import reverse from '../../common/stringreverse';\nimport BinaryStream from '../../common/binarystream';\nimport IndexEntr"
},
{
"path": "src/parsers/m3/model.ts",
"chars": 851,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Md34 from './md34';\n"
},
{
"path": "src/parsers/m3/modelheader.ts",
"chars": 5069,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/reference.ts",
"chars": 890,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry, { EntryType, SingleEntryType } from './indexent"
},
{
"path": "src/parsers/m3/region.ts",
"chars": 1370,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\n\n/**\n * A region.\n */\nexpor"
},
{
"path": "src/parsers/m3/sd.ts",
"chars": 548,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/sequence.ts",
"chars": 892,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/standardmaterial.ts",
"chars": 3429,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/stc.ts",
"chars": 1000,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/stg.ts",
"chars": 450,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/sts.ts",
"chars": 413,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\nimport Reference from './re"
},
{
"path": "src/parsers/m3/unsupportedentry.ts",
"chars": 629,
"preview": "import BinaryStream from '../../common/binarystream';\nimport IndexEntry from './indexentry';\n\n/**\n * An unsupported entr"
},
{
"path": "src/parsers/mdlx/animatedobject.ts",
"chars": 1937,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport { Animation } from"
},
{
"path": "src/parsers/mdlx/animationmap.ts",
"chars": 2470,
"preview": "import { UintAnimation, FloatAnimation, Vector3Animation, Vector4Animation } from './animations';\n\n// A map from MDX ani"
},
{
"path": "src/parsers/mdlx/animations.ts",
"chars": 7312,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\n\nexport const enum Interp"
},
{
"path": "src/parsers/mdlx/attachment.ts",
"chars": 1864,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/bone.ts",
"chars": 1896,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/camera.ts",
"chars": 3034,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport AnimatedObject fro"
},
{
"path": "src/parsers/mdlx/collisionshape.ts",
"chars": 3283,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/eventobject.ts",
"chars": 2024,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/extent.ts",
"chars": 994,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\n\n/**\n * An extent.\n */\nex"
},
{
"path": "src/parsers/mdlx/faceeffect.ts",
"chars": 888,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\n\n/**\n * A face effect.\n *"
},
{
"path": "src/parsers/mdlx/genericobject.ts",
"chars": 5240,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport AnimatedObject fro"
},
{
"path": "src/parsers/mdlx/geoset.ts",
"chars": 11747,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport Extent from './ext"
},
{
"path": "src/parsers/mdlx/geosetanimation.ts",
"chars": 2278,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport AnimatedObject fro"
},
{
"path": "src/parsers/mdlx/helper.ts",
"chars": 527,
"preview": "import TokenStream from './tokenstream';\nimport GenericObject from './genericobject';\n\n/**\n * A helper.\n */\nexport defau"
},
{
"path": "src/parsers/mdlx/index.ts",
"chars": 1210,
"preview": "import Model from './model';\nimport Sequence from './sequence';\nimport Material from './material';\nimport Layer from './"
},
{
"path": "src/parsers/mdlx/isformat.ts",
"chars": 1062,
"preview": "import { isStringInBytes, isStringInString } from '../../common/searches';\n\n/**\n * Detects if the given object is an MDX"
},
{
"path": "src/parsers/mdlx/layer.ts",
"chars": 7869,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport AnimatedObject fro"
},
{
"path": "src/parsers/mdlx/light.ts",
"chars": 4452,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/material.ts",
"chars": 3405,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport Layer from './laye"
},
{
"path": "src/parsers/mdlx/model.ts",
"chars": 24134,
"preview": "import BinaryStream from '../../common/binarystream';\nimport { decodeUtf8, encodeUtf8 } from '../../common/utf8';\nimport"
},
{
"path": "src/parsers/mdlx/particleemitter.ts",
"chars": 4670,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/particleemitter2.ts",
"chars": 11940,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/particleemitterpopcorn.ts",
"chars": 4893,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/ribbonemitter.ts",
"chars": 4759,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport GenericObject from"
},
{
"path": "src/parsers/mdlx/sequence.ts",
"chars": 2264,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport Extent from './ext"
},
{
"path": "src/parsers/mdlx/texture.ts",
"chars": 1665,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\n\nexport const enum WrapMo"
},
{
"path": "src/parsers/mdlx/textureanimation.ts",
"chars": 1245,
"preview": "import BinaryStream from '../../common/binarystream';\nimport TokenStream from './tokenstream';\nimport AnimatedObject fro"
},
{
"path": "src/parsers/mdlx/tokenstream.ts",
"chars": 8874,
"preview": "/**\n * Used to read and write MDL tokens.\n */\nexport default class TokenStream {\n buffer: string;\n index = 0;\n ident "
},
{
"path": "src/parsers/mdlx/unknownchunk.ts",
"chars": 548,
"preview": "import BinaryStream from '../../common/binarystream';\n\n/**\n * An unknown chunk.\n */\nexport default class UnknownChunk {\n"
},
{
"path": "src/parsers/mpq/adpcm.ts",
"chars": 3694,
"preview": "import BinaryStream from '../../common/binarystream';\n\nconst MAX_ADPCM_CHANNEL_COUNT = 2;\nconst INITIAL_ADPCM_STEP_INDEX"
},
{
"path": "src/parsers/mpq/archive.ts",
"chars": 13388,
"preview": "import { bytesOf } from '../../common/bytesof';\nimport { powerOfTwo } from '../../common/math';\nimport { numberToUint32 "
},
{
"path": "src/parsers/mpq/block.ts",
"chars": 444,
"preview": "/**\n * A block.\n */\nexport default class Block {\n offset = 0;\n compressedSize = 0;\n normalSize = 0;\n flags = 0;\n\n l"
},
{
"path": "src/parsers/mpq/blocktable.ts",
"chars": 1469,
"preview": "import MpqCrypto from './crypto';\nimport MpqBlock from './block';\nimport { BLOCK_TABLE_KEY } from './constants';\n\n/**\n *"
},
{
"path": "src/parsers/mpq/constants.ts",
"chars": 1046,
"preview": "export const MAGIC = 0x1A51504D; // MPQ\\x1A reversed\nexport const HASH_TABLE_KEY = 0xC3AF3770; // Hash of (hashtable)\nex"
},
{
"path": "src/parsers/mpq/crypto.ts",
"chars": 3613,
"preview": "import MpqBlock from './block';\nimport { HASH_FILE_KEY, FILE_OFFSET_ADJUSTED_KEY } from './constants';\n\n// Global variab"
},
{
"path": "src/parsers/mpq/explode.ts",
"chars": 12705,
"preview": "// A near direct copy of Ladislav Zezula's C implementation.\n// I left the comments out - if you wish to understand the "
},
{
"path": "src/parsers/mpq/file.ts",
"chars": 14629,
"preview": "import { deflate, inflate } from 'pako';\nimport { decodeUtf8 } from '../../common/utf8';\nimport MpqArchive from './archi"
},
{
"path": "src/parsers/mpq/hash.ts",
"chars": 1050,
"preview": "import { HASH_ENTRY_DELETED, HASH_ENTRY_EMPTY } from './constants';\n\n/**\n * A MPQ hash.\n */\nexport default class MpqHash"
},
{
"path": "src/parsers/mpq/hashtable.ts",
"chars": 2744,
"preview": "import MpqCrypto from './crypto';\nimport MpqHash from './hash';\nimport { HASH_TABLE_KEY, HASH_TABLE_INDEX, HASH_NAME_A, "
},
{
"path": "src/parsers/mpq/index.ts",
"chars": 371,
"preview": "import Archive from './archive';\nimport Crypto from './crypto';\nimport HashTable from './hashtable';\nimport Hash from '."
},
{
"path": "src/parsers/mpq/isarchive.ts",
"chars": 836,
"preview": "/**\n * Search for the MPQ header - MPQ\\x1A.\n * The header can be on any 512 bytes boundry offset.\n */\nexport function se"
},
{
"path": "src/parsers/slk/file.ts",
"chars": 2350,
"preview": "/**\n * A SLK table file.\n */\nexport default class SlkFile {\n rows: string[][] = [];\n\n load(buffer: string): void {\n "
},
{
"path": "src/parsers/slk/index.ts",
"chars": 56,
"preview": "import File from './file';\n\nexport default {\n File,\n};\n"
},
{
"path": "src/parsers/tga/image.ts",
"chars": 534,
"preview": "import TgaLoader from 'tga-js';\nimport { bytesOf } from '../../common/bytesof';\n\n/**\n * A TGA image.\n */\nexport default "
},
{
"path": "src/parsers/tga/index.ts",
"chars": 100,
"preview": "import Image from './image';\nimport isTga from './isformat';\n\nexport default {\n Image,\n isTga,\n};\n"
},
{
"path": "src/parsers/tga/isformat.ts",
"chars": 394,
"preview": "import { isStringInBytes } from '../../common/searches';\n\n/**\n * Detects if the given object is a TGA source.\n */\nexport"
},
{
"path": "src/parsers/w3x/doo/doodad.ts",
"chars": 2159,
"preview": "import BinaryStream from '../../../common/binarystream';\nimport RandomItemSet from './randomitemset';\n\n/**\n * A doodad.\n"
},
{
"path": "src/parsers/w3x/doo/file.ts",
"chars": 1962,
"preview": "import BinaryStream from '../../../common/binarystream';\nimport Doodad from './doodad';\nimport TerrainDoodad from './ter"
},
{
"path": "src/parsers/w3x/doo/index.ts",
"chars": 274,
"preview": "import File from './file';\nimport Doodad from './doodad';\nimport RandomItemSet from './randomitemset';\nimport RandomItem"
},
{
"path": "src/parsers/w3x/doo/randomitem.ts",
"chars": 380,
"preview": "import BinaryStream from '../../../common/binarystream';\n\n/**\n * A random item.\n */\nexport default class RandomItem {\n "
},
{
"path": "src/parsers/w3x/doo/randomitemset.ts",
"chars": 619,
"preview": "import RandomItem from './randomitem';\nimport BinaryStream from '../../../common/binarystream';\n\n/**\n * A random item se"
},
{
"path": "src/parsers/w3x/doo/terraindoodad.ts",
"chars": 818,
"preview": "import BinaryStream from '../../../common/binarystream';\n\n/**\n * A terrain doodad.\n *\n * This type of doodad works much "
},
{
"path": "src/parsers/w3x/imp/file.ts",
"chars": 1723,
"preview": "import BinaryStream from '../../../common/binarystream';\nimport Import from './import';\n\n/**\n * war3map.imp - the import"
},
{
"path": "src/parsers/w3x/imp/import.ts",
"chars": 501,
"preview": "import BinaryStream from '../../../common/binarystream';\nimport { byteLengthUtf8 } from '../../../common/utf8';\n\n/**\n * "
},
{
"path": "src/parsers/w3x/imp/index.ts",
"chars": 97,
"preview": "import File from './file';\nimport Import from './import';\n\nexport default {\n File,\n Import,\n};\n"
},
{
"path": "src/parsers/w3x/index.ts",
"chars": 644,
"preview": "import Map from './map';\nimport doo from './doo';\nimport imp from './imp';\nimport mmp from './mmp';\nimport shd from './s"
},
{
"path": "src/parsers/w3x/map.ts",
"chars": 8177,
"preview": "import BinaryStream from '../../common/binarystream';\nimport MpqArchive from '../mpq/archive';\nimport War3MapImp from '."
},
{
"path": "src/parsers/w3x/mmp/file.ts",
"chars": 866,
"preview": "import BinaryStream from '../../../common/binarystream';\nimport MinimapIcon from './minimapicon';\n\n/**\n * war3map.mmp - "
},
{
"path": "src/parsers/w3x/mmp/index.ts",
"chars": 112,
"preview": "import File from './file';\nimport MinimapIcon from './minimapicon';\n\nexport default {\n File,\n MinimapIcon,\n};\n"
},
{
"path": "src/parsers/w3x/mmp/minimapicon.ts",
"chars": 546,
"preview": "import BinaryStream from '../../../common/binarystream';\n\n/**\n * A minimap icon.\n */\nexport default class MinimapIcon {\n"
},
{
"path": "src/parsers/w3x/shd/file.ts",
"chars": 393,
"preview": "/**\n * war3map.shd - the shadow file.\n */\nexport default class War3MapShd {\n shadows = new Uint8Array(0);\n\n load(buffe"
},
{
"path": "src/parsers/w3x/shd/index.ts",
"chars": 56,
"preview": "import File from './file';\n\nexport default {\n File,\n};\n"
}
]
// ... and 296 more files (download for full content)
About this extraction
This page contains the full source code of the flowtsohg/mdx-m3-viewer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 496 files (3.0 MB), approximately 799.6k tokens, and a symbol index with 3241 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.