@lampdotdev/lamp 0.0.0-stage → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +357 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1646 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3036 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +414 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +59 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +136 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +103 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/android.mjs +941 -0
- package/cli/browser.mjs +268 -0
- package/cli/calls.mjs +390 -0
- package/cli/dev.mjs +773 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1016 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6863 -0
- package/cli/lamps/lamp.js +7023 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7023 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +138 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/outside.mjs +140 -0
- package/cli/page.js +165 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +202 -0
- package/cli/skill/SKILL.md +255 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +173 -0
- package/cli/update.mjs +57 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +996 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: assets
|
|
3
|
+
description: Ready-made models, sprites, tilesets, UI, icons, textures, sound effects and music from Lamp's free index (the `assets` tool) - when to use them rather than making things in code or with make_art, keeping one style, loading them so a change shows in the running game, glTF scale, orientation, copies and animations in three.js, sprite sheets and tilesets in Phaser, sounds and music, pictures for apps, and their credit. Read before choosing how a game's or app's things will look or sound.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ready-made assets
|
|
7
|
+
|
|
8
|
+
The `assets` tool searches Lamp's index of free work by people who publish it for anyone to use: low-poly 3D packs
|
|
9
|
+
(Kenney's city, houses, furniture and survival kits, Quaternius's cars, nature, animals, people and monsters, KayKit's
|
|
10
|
+
city bits, a few single models such as a taxi or a bus), Kenney's 2D packs (a platformer, a space shooter, a top-down
|
|
11
|
+
racer, pixel-art towns and dungeons, cartoon characters, animals), UI pieces, icons, ambientCG's tileable materials,
|
|
12
|
+
Kenney's interface sounds and SubspaceAudio's retro effects and music loops. Each is CC0, or CC-BY, which asks for
|
|
13
|
+
credit. Lamp fetches what you choose into the app, checks it, makes its pictures smaller where the slowest place it's
|
|
14
|
+
shown needs that, and writes its credit in credits.json. Nothing is
|
|
15
|
+
loaded from the network while the app runs.
|
|
16
|
+
|
|
17
|
+
## Ready-made or made yourself
|
|
18
|
+
|
|
19
|
+
Ready-made, when the person wants things that look like real things and there are many of them, or that move in
|
|
20
|
+
ways code can't easily give: a city of different buildings, real-looking cars, people and animals that walk and run
|
|
21
|
+
(their skeletons and animations come with them, which code can't make), a forest of varied trees, a platformer's
|
|
22
|
+
character with its run and jump frames, a tileset for a whole level, a UI that looks finished. And whenever the person
|
|
23
|
+
asks for "the same game with different models" or another look for a game that exists (below).
|
|
24
|
+
|
|
25
|
+
Made yourself, when the thing is simple or abstract (blocks, balls, a neon track), when the game moves its parts itself
|
|
26
|
+
(a robot whose arms the player aims, a car whose doors open), when it must match something the person described or
|
|
27
|
+
gave, when only one or two things are needed and code makes them well, or when nothing in the index fits the style.
|
|
28
|
+
Three.js shapes or Phaser graphics for shapes; `make_art` for a picture in the app's own style (a hero, a boss, a
|
|
29
|
+
backdrop, an illustration in an app). The two mix well when the code-made things take the pack's palette.
|
|
30
|
+
|
|
31
|
+
Sounds and music have a rule of their own, below: the index comes first.
|
|
32
|
+
|
|
33
|
+
Look first with `find` (and `kind`), `show: true` to see the candidates together, before deciding: it costs nothing.
|
|
34
|
+
|
|
35
|
+
## One style
|
|
36
|
+
|
|
37
|
+
Things seen together come from one pack, or from one author's packs, whose `style` matches: Kenney with Kenney,
|
|
38
|
+
Quaternius with Quaternius. Different authors' low-poly flat-color work can sit together, but look at them side by side
|
|
39
|
+
(`show`) first: a pastel KayKit house beside a sharp Google Poly taxi reads as two games. Fill what the pack lacks in
|
|
40
|
+
code, in its colors and proportions, rather than with a third style. In 2D, pixel art at one size (16 px) never mixes
|
|
41
|
+
with smooth vector art.
|
|
42
|
+
|
|
43
|
+
## Bringing them in
|
|
44
|
+
|
|
45
|
+
1. `assets` with `find` ("taxi", "low-poly tree", "platformer player") and `kind`, and `show: true`. Each line has an
|
|
46
|
+
id, its triangles, its box in its own units, its animations, its size, its pack, author, license and style.
|
|
47
|
+
2. `assets` with `fetch` and the ids. They land in Web/assets/<pack>/ for a game or another page, or Assets/<pack>/ for
|
|
48
|
+
a Swift app (app/src/main/assets/<pack>/ for a native Android app, read with `LampAssets`), and the answer gives each
|
|
49
|
+
file's path as the app loads it.
|
|
50
|
+
3. Load each through the runtime (below), then `look_at_app`: a model's size and the way it faces are only certain once
|
|
51
|
+
seen.
|
|
52
|
+
|
|
53
|
+
The answer leaves out what's too heavy for the slowest place the app is shown (an Xbox One, a TV, a cheap Android
|
|
54
|
+
phone): what's listed fits one copy. The scene's total is still yours to keep within the device line's budget: twenty
|
|
55
|
+
cars of 3,000 triangles are 60,000.
|
|
56
|
+
|
|
57
|
+
Keep every asset's path in one table at the top of the game (`const MODELS = { taxi: 'assets/poly-quaternius/car.glb', … }`),
|
|
58
|
+
with each thing's real size beside it. Changing the look is then that table, which is also how "the same game with
|
|
59
|
+
different models" is made: find a set in another style, fetch it, and point the table at it; the game's code stays.
|
|
60
|
+
|
|
61
|
+
## In a three.js game
|
|
62
|
+
|
|
63
|
+
Load with lamp-game.js, never a loader of your own, so a new copy of a file goes into the running game:
|
|
64
|
+
`const taxi = await model(MODELS.taxi)` in `init` gives a `THREE.Group` holding the file's scene, with
|
|
65
|
+
`taxi.animations`. Pictures: `texture(path, t => { t.colorSpace = THREE.SRGBColorSpace; })`.
|
|
66
|
+
|
|
67
|
+
- **Scale.** Units differ by author: Kenney's are tiles (a building about 1 unit wide), Quaternius's and KayKit's are
|
|
68
|
+
near meters, Google Poly's are often centimeters (a taxi 90 units long). Scale each to its real size from its box,
|
|
69
|
+
once: a car is about 4.5 m long, a person 1.75 m tall, a door 2 m, a street lamp 5 m.
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
function fitted(group, meters, axis = 'longest') {
|
|
73
|
+
const size = new THREE.Box3().setFromObject(group).getSize(new THREE.Vector3());
|
|
74
|
+
const now = axis === 'height' ? size.y : Math.max(size.x, size.z);
|
|
75
|
+
group.scale.setScalar(meters / now);
|
|
76
|
+
return group;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- **Standing on the ground.** A model's origin may be at its center or its feet: after scaling, lift it by the box's
|
|
81
|
+
bottom (`group.position.y = -box.min.y`), inside a holder group that the game moves.
|
|
82
|
+
- **Facing.** glTF is y up; most models face +z, some -z or +x. Find out by looking, then turn the holder (or the
|
|
83
|
+
group) once: `holder.add(taxi); taxi.rotation.y = Math.PI`. Never change the meshes inside the group: a new copy of
|
|
84
|
+
the file replaces them.
|
|
85
|
+
- **Many copies.** The same model many times: `clone()` shares its geometry and materials (cheap in memory, one draw
|
|
86
|
+
per mesh per copy); for a whole street of one building or a forest of one tree, an `InstancedMesh` per mesh of the
|
|
87
|
+
model (walk it with `traverse`, take each mesh's `geometry` and `material` and its matrix within the model) is one
|
|
88
|
+
draw for all of them. A rigged character (one with `SkinnedMesh`es) is copied with `SkeletonUtils.clone` from
|
|
89
|
+
`three/addons/utils/SkeletonUtils.js`; a plain clone shares one skeleton and every copy moves as one. Copies and
|
|
90
|
+
instances are made again in `assetChanged(path)` (the game skill, "Changes while it's played").
|
|
91
|
+
- **Animations.** One `THREE.AnimationMixer` per character, its clips found by the end of their names, which carry
|
|
92
|
+
the rig's name ("CharacterArmature|Walk"):
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
const clip = name => model.animations.find(a => a.name.split('|').pop() === name);
|
|
96
|
+
const mixer = new THREE.AnimationMixer(character);
|
|
97
|
+
const walk = mixer.clipAction(clip('Walk')), run = mixer.clipAction(clip('Run'));
|
|
98
|
+
walk.play();
|
|
99
|
+
// switching: run.reset().play(); walk.crossFadeTo(run, 0.25, false);
|
|
100
|
+
// in frame(f): mixer.update(f.dt);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The fetch answer lists each model's animations. Mixers are made again in `assetChanged(path)`.
|
|
104
|
+
- **Materials.** Packs come lit for MeshStandardMaterial. Where the device line names a slow place, swap each mesh's
|
|
105
|
+
material for a `MeshLambertMaterial` with the same `color` and `map` as the game starts. Shadows only where the budget
|
|
106
|
+
allows them: `castShadow` on each mesh through `traverse`.
|
|
107
|
+
- **Textures** (ambientCG): color in sRGB, the normal and roughness maps as they are, all with
|
|
108
|
+
`wrapS = wrapT = THREE.RepeatWrapping` and `repeat` set so a tile is about its real size (a 1K brick map covers about
|
|
109
|
+
two meters).
|
|
110
|
+
|
|
111
|
+
## In a Phaser game
|
|
112
|
+
|
|
113
|
+
Load in a Boot scene's `preload`, by the path the fetch gave:
|
|
114
|
+
|
|
115
|
+
- **A sprite sheet with an XML atlas** (most of Kenney's 2D packs):
|
|
116
|
+
`this.load.atlasXML('players', 'assets/kenney-platformer/spritesheet_players.png', 'assets/kenney-platformer/spritesheet_players.xml')`.
|
|
117
|
+
Its frames are named as the XML says ("alienBeige_walk1.png"); an animation is
|
|
118
|
+
`this.anims.create({ key: 'walk', frames: this.anims.generateFrameNames('players', { prefix: 'alienBeige_walk', start: 1, end: 2, suffix: '.png' }), frameRate: 8, repeat: -1 })`.
|
|
119
|
+
Read the XML (the fetch put it beside the sheet) for the frame names before writing them.
|
|
120
|
+
- **A tilesheet** (the pixel-art packs): `this.load.spritesheet('tiles', path, { frameWidth: 16, frameHeight: 16, spacing: 1 })`
|
|
121
|
+
with the size and spacing the fetch answer gives, and in a tilemap
|
|
122
|
+
`map.addTilesetImage('tiles', 'tiles', 16, 16, 0, 1)` (margin, then spacing). Its tiles are numbered left to right,
|
|
123
|
+
top to bottom, from 0: look at the sheet before writing the level's rows.
|
|
124
|
+
- **Pixel art** at 16 px wants `pixelArt: true` and a whole-number camera zoom (the 2d-game skill); smooth art is drawn
|
|
125
|
+
at its own size or smaller, never scaled up.
|
|
126
|
+
|
|
127
|
+
A picture Phaser's loader read goes in again through `assetChanged(path)` in phaser() (the 2d-game skill).
|
|
128
|
+
|
|
129
|
+
## Sounds and music
|
|
130
|
+
|
|
131
|
+
Kinds `sound` (short effects) and `music` (loops). Each line has its length and says when it loops. `show` has nothing
|
|
132
|
+
to show: a sound's name and notes are all you can judge it by, so try it in the game, and say in your report that you
|
|
133
|
+
haven't heard it, since Lamp hears nothing of what plays.
|
|
134
|
+
|
|
135
|
+
A game's sounds start here, whatever else it makes in code. List them all before writing any: `kind: sound`, `limit: 30`
|
|
136
|
+
and no `find`, then `kind: music`, since one search stops at its own words. Go through each moment (a click, a flip, a
|
|
137
|
+
coin, a hit, a win, a loss) and the music against those lists: "Coin", "Impact" or "Jump" may do for a flip. Make one in
|
|
138
|
+
code (the game skill, "Sound") only when nothing here fits that moment, or when it must follow the game as it's played
|
|
139
|
+
(an engine's pitch, notes on a scale), and say which and why in your report.
|
|
140
|
+
|
|
141
|
+
Most sounds here are retro and chiptune. That's no reason to skip them, since a tone written in code is no less
|
|
142
|
+
synthetic; a clip that's wrong for the moment is. One game keeps to one sound family as it keeps to one art style.
|
|
143
|
+
|
|
144
|
+
Choose them as the game is made, and fetch them then: they ship inside it, so the game works offline. Load each once, as
|
|
145
|
+
the game sets itself up, through the runtime, and play it with what the game skill names:
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
const SOUNDS = { click: 'assets/subspace-retro-sfx/sfx_menu_select1.wav', coin: 'assets/subspace-retro-sfx/sfx_coin_single1.wav' };
|
|
149
|
+
const click = await sound.load(SOUNDS.click);
|
|
150
|
+
const theme = await sound.load('assets/subspace-music-loops/menu-relaxed.ogg');
|
|
151
|
+
sound.play(click, { volume: 0.7 });
|
|
152
|
+
sound.music(theme, 0.35);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Keep them in one table, as with models, and keep the mute setting and `sound.volume` as the game skill says: a fetched
|
|
156
|
+
sound follows them like any other. A loop is decoded whole, about 20 MB of memory a minute: one or two on a phone or a
|
|
157
|
+
TV, and the shortest that does. Native games read the same files: `lamp_sound_load` and `lamp_music` take
|
|
158
|
+
`"<pack>/<file>"` from Assets/, and a Swift app `LampAssets.url("<pack>/<file>")`.
|
|
159
|
+
|
|
160
|
+
Kenney's interface sounds and the music are Ogg Vorbis, which a page or `AVAudioPlayer` on Apple's devices decodes only
|
|
161
|
+
from about macOS 15.4 and iOS 18.4: on an older one such a sound stays silent, and the page's log says it couldn't be
|
|
162
|
+
loaded. SubspaceAudio's effects are WAV and play everywhere, so they carry a game's menus and what the player needs to
|
|
163
|
+
hear; use them for those on an older Mac or iPhone.
|
|
164
|
+
|
|
165
|
+
## In an app
|
|
166
|
+
|
|
167
|
+
On Apple's devices, an SF Symbol comes before any icon file. Kenney's icons and UI pieces suit a game's menus, a web
|
|
168
|
+
app or a page on a TV. An illustration in an app is `make_art`'s, in the app's own style. In a Swift app a fetched file
|
|
169
|
+
is in Assets/<pack>/, read with `LampAssets.url("<pack>/<file>")` or `LampAssets.image(…)`; a .glb in a Mac app's
|
|
170
|
+
RealityKit scene is turned into USD as the scene-3d skill says.
|
|
171
|
+
|
|
172
|
+
## Credit
|
|
173
|
+
|
|
174
|
+
Lamp writes each fetched asset, sounds and music included, into credits.json (its pack, author, license and files), which the app's info, its About
|
|
175
|
+
window, a shared copy, a published page and its repository's README all show: never take an entry out. CC-BY work asks
|
|
176
|
+
for more: name it where the game or app shows its credits too (a Credits line in the pause menu or the About screen:
|
|
177
|
+
"Taxi by Poly by Google, CC BY 3.0"), which the fetch answer reminds you of. CC0 needs nothing, though a line thanking
|
|
178
|
+
the pack's author is kind.
|
|
179
|
+
|
|
180
|
+
## When nothing fits
|
|
181
|
+
|
|
182
|
+
Make it in code, in the style of what's there, or with `make_art` for a picture. Lamp has no way to make a new model
|
|
183
|
+
from words yet: don't promise one.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: building-blocks
|
|
3
|
+
description: How to call LampSupport.swift's tested building blocks - notifications, schedules and work while the app is closed, text from documents and pictures, dropped files, folders, global shortcuts, the clipboard, login items, photos, location, weather, music, Spotlight, the home, the devices on the home network and a Roku. Read before using any of them.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lamp's building blocks
|
|
7
|
+
|
|
8
|
+
LampSupport.swift has tested building blocks for common jobs, the same ones on a Mac and an iPhone where both have
|
|
9
|
+
them. Use them instead of writing your own.
|
|
10
|
+
|
|
11
|
+
## On both
|
|
12
|
+
|
|
13
|
+
- `LampNotifications.send("Title", body: "…")`, also `at: date` to show it later, even with the app closed, `id:` to
|
|
14
|
+
replace or `cancel(id)` one, `actions: ["Done", "Snooze"]` for buttons that work without opening the app, handled by
|
|
15
|
+
`LampNotifications.onAction { action, id in … }` set where the app starts, and on iPhone `timeSensitive: true`,
|
|
16
|
+
with `{"timeSensitive": true}` in capabilities.json, for what can't wait, sparingly.
|
|
17
|
+
- `LampSchedule.daily("briefing", hour: 7) { }` and `LampSchedule.every("inbox", minutes: 15) { }`: work at a time or
|
|
18
|
+
every so often, catching up after sleep; keep it alive. On an iPhone see "Work while the app is closed" below.
|
|
19
|
+
- `await LampText.read(url)`: text from PDFs, scanned PDFs, images and screenshots via Live Text, RTF, Word, HTML,
|
|
20
|
+
plain text, all on the device and free; use it before sending documents to LampAI. `await LampText.recognize(in:
|
|
21
|
+
image)` for an `NSImage` on the Mac, a `UIImage` on iPhone.
|
|
22
|
+
- `.lampDropFiles { urls in }` on any view and `LampDropZone("Drop screenshots here") { urls in }` for an empty state
|
|
23
|
+
(Finder files, images from other apps, links; on iPad, files and images dragged in from another app).
|
|
24
|
+
- Photos: `LampPhotos` (`authorize()`, `photos(days:)`, `photos(near:_:km:)`, `favorites()`, `albums()`,
|
|
25
|
+
`photos(in:)`, `image(_:size:)`, `tags(of:)` for what a picture shows (empty in the simulator), `save(_:)`;
|
|
26
|
+
choosing one is SwiftUI's `PhotosPicker`).
|
|
27
|
+
- Location: `LampLocation` (`current()` with a name from the map, `find(address)`, `distance(from:to:)`,
|
|
28
|
+
`shared.watch()` for big moves, `shared.watchVisits()` on the iPhone for where the person stops and for how long,
|
|
29
|
+
which needs `"backgroundModes": ["location"]`).
|
|
30
|
+
- Weather: `LampWeather` (`now(latitude:longitude:)`, `hours`, `days`, `here()`), after `{"weather": true}` in
|
|
31
|
+
capabilities.json, for apps with an iPhone half only; the team also turns WeatherKit on for the app at
|
|
32
|
+
developer.apple.com once, and the call's message says so until then (otherwise, Open-Meteo through `connectors`).
|
|
33
|
+
Apple's terms ask for `LampWeatherAttribution()` (its Weather mark, linking to its sources) wherever its weather is
|
|
34
|
+
shown, allow forecasts to be kept only briefly (never saved with the app's data), and rule out apps meant for
|
|
35
|
+
emergencies or safety.
|
|
36
|
+
- Music: `LampMusic` (`authorize()`, `recentlyPlayed()`, `library()`, `search(_:)`, `play(_:)`, `pause()`, and on the
|
|
37
|
+
iPhone `nowPlaying`), Apple Music only, with MusicKit turned on for the app at developer.apple.com the same way.
|
|
38
|
+
- Spotlight: for the app's own things people would look for by name (notes, recipes, people, trips),
|
|
39
|
+
`LampSpotlight.index(id:title:details:keywords:)` when one is added or changed and `LampSpotlight.remove(id)` when
|
|
40
|
+
it's deleted, and `.lampSpotlightOpen { id in … }` on the view that shows them, to show the one tapped in Spotlight.
|
|
41
|
+
|
|
42
|
+
- The home network: `LampNetwork`, for an app on the Mac or a phone that controls, plays to or reads the person's
|
|
43
|
+
devices (a remote for the TV and speakers, what's playing, a light). The system asks the person about the local
|
|
44
|
+
network before anything answers, so the app says why first, in its own words and on its own screen, and asks with
|
|
45
|
+
`await LampNetwork.requestAccess()` (`.allowed`, `.denied` with `LampNetwork.allowHint` saying where to turn it on,
|
|
46
|
+
or `.unknown` off a home network), never at launch. Then `await LampNetwork.find()`: every device that answers, each
|
|
47
|
+
with `address`, `name`, `maker`, `model`, what it answered SSDP for (`ssdp`, `server`, `location`) and its Bonjour
|
|
48
|
+
services (`bonjour`). An iPhone app sees only the Bonjour types in capabilities.json's `bonjourServices` (add the
|
|
49
|
+
types of the devices the app is for: `"_sonos._tcp"`, `"_googlecast._tcp"`), and the system's question shows
|
|
50
|
+
`"localNetwork"` there, the app's own reason ("TV Remote finds your TV and speakers to control them."). Work out how
|
|
51
|
+
to reach each device from what it says of itself; a Roku is `LampRoku`'s. Its maker and model say what a device is;
|
|
52
|
+
its services say only what it can do: a console and a TV both answer as media renderers, and a Mac offers AirPlay,
|
|
53
|
+
so none of them is a speaker for that.
|
|
54
|
+
- Roku: `LampRoku`, for an app on the Mac or a phone that controls the person's Roku (a remote of its own, buttons
|
|
55
|
+
that open Netflix or a show, what's playing, a Roku TV's power, volume and input), with nothing installed on the
|
|
56
|
+
Roku. An app that runs on the Roku itself is a Roku app instead. `await LampRoku.find()` (every Roku that answers,
|
|
57
|
+
each with `name`, `isTV` and `canBeControlled`), then `launch(named:)` or `launch(appID:contentID:mediaType:)` for a
|
|
58
|
+
deep link, `press(.home)` and the other keys, `type(_:)` into its on-screen keyboard, `activeApp()`, `playing()`,
|
|
59
|
+
`apps()`, and on a Roku TV `power(on:)`, `press(.volumeUp)` and `input(.hdmi1)`. The one setup is on the Roku:
|
|
60
|
+
Settings, System, Advanced system settings, Control by mobile apps, Network access set to Enabled
|
|
61
|
+
(`LampRoku.setUp` says it); show that when `canBeControlled` is false or a call says so, and never suggest
|
|
62
|
+
Permissive. The first `find()` makes the system ask about the local network, so give the person a way to look
|
|
63
|
+
again; remember the Roku they chose by its `id`, and offer a choice when more than one answers.
|
|
64
|
+
|
|
65
|
+
## On the Mac only
|
|
66
|
+
|
|
67
|
+
These exist only in a Mac app's copy of the library (in an app for both, only under `#if os(macOS)`):
|
|
68
|
+
|
|
69
|
+
- `LampFolderWatcher(folder) { changedURLs in }`: files added or changed in a folder; keep it alive.
|
|
70
|
+
- `LampFolders`: downloads, desktop, documents, screenshots, `files(in:)` newest first.
|
|
71
|
+
- `LampHotKey("cmd+shift+space") { }`: a shortcut that works from any app; keep it alive.
|
|
72
|
+
- `LampLoginItem.isEnabled`: open at login. Offer it as a toggle in Settings, never turn it on yourself; an app that
|
|
73
|
+
declares `"background": true` is opened at login by Lamp.
|
|
74
|
+
- `LampClipboardWatcher { item in }` (item.text / image / fileURLs; keep it alive) and
|
|
75
|
+
`LampClipboardWatcher.copy(text)`.
|
|
76
|
+
|
|
77
|
+
## On iPhone only
|
|
78
|
+
|
|
79
|
+
An iPhone app's copy of the library has none of the Mac-only blocks above, nor Mail, other apps, the menu bar or the
|
|
80
|
+
permission screens: never call them there.
|
|
81
|
+
|
|
82
|
+
- Home: `LampHome` (after `{"homekit": true}` in capabilities.json): `accessories()` (lights, locks, thermostats,
|
|
83
|
+
sensors, switches, each with its room and state), `set(_:on:)`, `set(_:brightness:)`, `set(_:locked:)`,
|
|
84
|
+
`read(_:)`. Apple's terms allow it only in an app whose job is controlling the home, and what it reads never
|
|
85
|
+
leaves the phone: not to LampAI, a server, LampSync or the Mac.
|
|
86
|
+
|
|
87
|
+
### Work while the app is closed
|
|
88
|
+
|
|
89
|
+
When the app should do something while it's closed (fetch the news before breakfast, check a price, tidy up,
|
|
90
|
+
remind), declare `{"background": true}` in capabilities.json, put `.lampBackground()` on its WindowGroup, and make
|
|
91
|
+
`@State private var check = LampSchedule.every("prices", minutes: 60) { … }` or
|
|
92
|
+
`LampSchedule.daily("briefing", hour: 7) { … }` in the App, the same calls as on a Mac. iOS runs them while the app
|
|
93
|
+
is closed when it judges best: near the time, not on the dot, at most a few times an hour, and less for an app the
|
|
94
|
+
person rarely opens; while the app is open they run on time. Keep each run short (seconds) and tell the person what
|
|
95
|
+
came of it with a notification. Something that must happen at an exact time and only needs to tell the person is a
|
|
96
|
+
notification sent with `at:`, not a schedule. The simulator never wakes a closed app by itself, so try the work by
|
|
97
|
+
running it from the app.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: device-control
|
|
3
|
+
description: How an app controls, plays to or reads the person's own devices on their home network (a TV, speakers, a console, lights) when Lamp has no block for them - finding each one, working out its local API, writing it into the app, and asking the person before changing anything on a real device. Read before writing code that reaches one of their devices.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Controlling the person's devices
|
|
7
|
+
|
|
8
|
+
A remote for the TV and speakers, buttons that open the family's apps, what's playing in the menu bar: the app talks
|
|
9
|
+
to devices that are really in the person's home. Work out each one from what it says about itself, and never change
|
|
10
|
+
anything on a real one until the person has said you may.
|
|
11
|
+
|
|
12
|
+
## What's there
|
|
13
|
+
|
|
14
|
+
- Call `network_devices` first: what Lamp's own look found, with what it already has for each device. Start from
|
|
15
|
+
that, not from a question about what the person owns, and ask only about what it can't tell you.
|
|
16
|
+
- In the app, find devices with `LampNetwork` (the building-blocks skill): `requestAccess()` after the app has said
|
|
17
|
+
why, then `find()`. Give capabilities.json a `localNetwork` reason in the app's own words, and the Bonjour types
|
|
18
|
+
of the devices it's for in `bonjourServices` (an iPhone app can look for no others).
|
|
19
|
+
- A Roku is `LampRoku`'s. Use it rather than writing ECP yourself.
|
|
20
|
+
- A device's maker and model say what it is. Its services say only what it can do: a console and a TV both answer as
|
|
21
|
+
media renderers, and a Mac offers AirPlay, so none of them is a speaker for that.
|
|
22
|
+
|
|
23
|
+
## Working out a device
|
|
24
|
+
|
|
25
|
+
For a device Lamp has no block for, find how its maker's own phone app talks to it on the home network, from what it
|
|
26
|
+
says about itself: its SSDP answer and UPnP description (`location`), its Bonjour services and TXT record, its model.
|
|
27
|
+
Most have a local API: an HTTP or SOAP service (Sonos on port 1400, UPnP's AVTransport and RenderingControl), a
|
|
28
|
+
WebSocket (Samsung's remote channel, LG's second-screen socket), or a documented REST API. Read it from the device
|
|
29
|
+
(its description, a status endpoint) before relying on it. Some can't be reached this way: pairing that needs
|
|
30
|
+
cryptography of the maker's own (Apple TV, a Google TV's remote), or control only through the maker's cloud account.
|
|
31
|
+
Say so plainly in a sentence instead of half-building it.
|
|
32
|
+
|
|
33
|
+
## Writing it
|
|
34
|
+
|
|
35
|
+
- One file per kind of device, behind one small protocol the rest of the app uses, so a new kind is one more file:
|
|
36
|
+
what it can do (keys, apps, text, volume, power, what's playing) and how. The screen asks a device what it can do,
|
|
37
|
+
never which kind it is: a TV without volume over the network shows no volume buttons.
|
|
38
|
+
- Reach only addresses that discovery found, or one the person typed.
|
|
39
|
+
- A device that signs its own secure socket (an LG's 3001, a Samsung's 8002) is trusted for that address alone,
|
|
40
|
+
never every certificate the app meets.
|
|
41
|
+
- A token a device hands back after the person allows the app on its screen is kept with the device in LampStore:
|
|
42
|
+
it only lets an app on this network reach that one device, and the remote must work with Lamp closed, which
|
|
43
|
+
`LampSecrets` on a Mac doesn't. A sign-in to the maker's account is the person's: `LampSecrets`, never LampStore.
|
|
44
|
+
- When the device asks the person on its own screen (Allow on a TV), the app says so while it waits, and what to do
|
|
45
|
+
if they missed it.
|
|
46
|
+
- Example devices for exploring with nothing found, clearly marked, sending nothing.
|
|
47
|
+
|
|
48
|
+
## Asking before changing a device
|
|
49
|
+
|
|
50
|
+
Reading a device is always fine: what it is, its apps, what's playing, its volume. Changing one is the person's to
|
|
51
|
+
allow: a key press, opening an app, the volume, the input, power, a setting. Before the first change on a device, by
|
|
52
|
+
a command or by using the app (`use_app`), call `device_permission` with the device as the person knows it, its address,
|
|
53
|
+
and what you'd do, and end your turn. Lamp shows the card and keeps the answer: "Allow once" covers this request, "Always for"
|
|
54
|
+
the device covers the wish. Lamp refuses `use_app` on an app that reaches devices unless its `device` names one the person allowed,
|
|
55
|
+
and every engine's check refuses a command that changes a device without it. When the answer is "Not now", leave the
|
|
56
|
+
device alone and say how the person can try it themselves.
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: device-integrations
|
|
3
|
+
description: A device Lamp has no kit for (a streaming stick, a photo frame, a TV, an appliance), described as data for device_integration - how Lamp finds it, reads who it is, sets it up step by step, and puts software on it. Read before writing or fixing an integration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Device integrations
|
|
7
|
+
|
|
8
|
+
An integration is a JSON object handed to Lamp with `device_integration`. It is data, never code: Lamp acts on it with
|
|
9
|
+
its own primitives, fills every value itself, draws every card the person sees, and checks each step on the device.
|
|
10
|
+
Write it from the device's own documentation (its developer docs, its local API's reference). Lamp answers with what's
|
|
11
|
+
wrong; fix exactly that and send it again.
|
|
12
|
+
|
|
13
|
+
You never reach the device: no command, request or scan of yours. Lamp does that. You never walk the person through
|
|
14
|
+
steps in the chat: the steps are cards Lamp draws from what you write here.
|
|
15
|
+
|
|
16
|
+
## Shape
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"id": "roku", // lowercase letters, digits, dashes
|
|
21
|
+
"name": "Roku", "maker": "Roku", "kind": "streaming stick",
|
|
22
|
+
"sources": ["https://developer.roku.com/docs/developer-program/debugging/external-control-api.md"],
|
|
23
|
+
"find": [{ "ssdp": "roku:ecp" }],
|
|
24
|
+
"identity": { ... },
|
|
25
|
+
"steps": [ ... ],
|
|
26
|
+
"bridge": { ... }, // how an app goes on it, opens, is seen and is used
|
|
27
|
+
"app": { ... } // what's built for it; needs bridge.install
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### find
|
|
32
|
+
|
|
33
|
+
How the device announces itself; any one that matches finds it. Each entry has exactly one of:
|
|
34
|
+
|
|
35
|
+
- `"ssdp": "<search target>"`, optionally `"contains"` for what the answer's SERVER line holds.
|
|
36
|
+
- `"bonjour": "_service._tcp"`, optionally `"contains"` for the name.
|
|
37
|
+
- `"http": {"port": 8060, "path": "/query/device-info", "contains": "<device-info>"}`: asked of every address that
|
|
38
|
+
answered Lamp's own SSDP scan.
|
|
39
|
+
|
|
40
|
+
### identity
|
|
41
|
+
|
|
42
|
+
Where each field of the device's record is read from its own answers. `os` is said once; the rest are reads. `id`
|
|
43
|
+
(unique to this one device: a serial, a UDN) and `model` are required.
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
"identity": {
|
|
47
|
+
"os": "Roku OS",
|
|
48
|
+
"id": { "http": { "port": 8060, "path": "/query/device-info" }, "xml": "serial-number" },
|
|
49
|
+
"model": { "http": { "port": 8060, "path": "/query/device-info" }, "xml": "model-name" },
|
|
50
|
+
"name": { "http": { "port": 8060, "path": "/query/device-info" }, "xml": "user-device-name" },
|
|
51
|
+
"modelID": { "http": { "port": 8060, "path": "/query/device-info" }, "xml": "model-number" },
|
|
52
|
+
"osVersion": { "http": { "port": 8060, "path": "/query/device-info" }, "xml": "software-version" }
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A read has `json` (a dotted path: `device.modelName`, `items.0.id`) or `xml` (an element, or `parent/child`). Reads are
|
|
57
|
+
GETs. In place of `http`, `"description": true` reads the device's UPnP description wherever its SSDP answer points now
|
|
58
|
+
(with `xml`), for a device whose description moves with its mode, as an Xbox's does. `contains` on a read says what the
|
|
59
|
+
value must hold for the device to be this kind (`"contains": "Xbox"` on the model), when other devices answer the same
|
|
60
|
+
search.
|
|
61
|
+
|
|
62
|
+
### Requests
|
|
63
|
+
|
|
64
|
+
Every request goes to the address the device was found at; you give only the port and path.
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{ "method": "POST", "port": 80, "path": "/plugin_install",
|
|
68
|
+
"auth": { "digest": true, "user": "rokudev", "password": "{field:password}" },
|
|
69
|
+
"form": { "mysubmit": "Install", "archive": "@{package}" } }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`https: true` for a device that only speaks HTTPS with a certificate of its own (Xbox's Device Portal): Lamp
|
|
73
|
+
trusts that certificate the first time and holds the device to it after. `method` (GET, POST, PUT, DELETE), `headers`, `body` or `form` (a value `"@{package}"` sends the package file), `auth`
|
|
74
|
+
(`digest` true or false for basic; the password is always one `{field:…}`), and `keep`: `"picture"` in `bridge.look`
|
|
75
|
+
for the answer that is the screen's picture, `"screen"` in `bridge.screen` for the answer that is the screen as text (the
|
|
76
|
+
tree of what the app shows, where the device describes it), `"log"` in `bridge.log` for the answer that is the app's log, `"key"` in a
|
|
77
|
+
step's `run` for an SSH key the device gives this Mac.
|
|
78
|
+
`poll` (seconds) asks again every two seconds while the device answers 204 (still working on an install), and `expect`
|
|
79
|
+
(`json` or `xml`, with `equals` or `contains`) is what the answer must say for the step to count, else it fails with the
|
|
80
|
+
device's words. In a `json` path, `*` is every element of a list, and the answer counts when any of them says it
|
|
81
|
+
(`"InstalledPackages.*.PackageFullName"`); `equals` and `contains` may hold Lamp's values (`"{packageFullName}"`).
|
|
82
|
+
`until` (seconds, with `expect`) asks again every two seconds until the answer says it: for a device that's done with an
|
|
83
|
+
install a while before the app can be opened, end `install` with a request that waits until the device lists the app. A form value `"@{certificate}"` sends Lamp's certificate for a wrapped package (below).
|
|
84
|
+
`restore` (a JSON field's name) on a PUT or POST that changes a setting only for its sequence: Lamp first reads the
|
|
85
|
+
same path with a GET, takes that field's value, and when the sequence ends (in `bridge.install`, once the app has been
|
|
86
|
+
launched after it), however it ends, sends `{"<field>": "<that value>"}` back the same way. For a device-wide setting an install needs (an Xbox installs a package as a game only while
|
|
87
|
+
`/ext/settings/DefaultUWPContentTypeToGame` is `{"Value":"{isGame}"}`), so the person's own choice is left as it was.
|
|
88
|
+
|
|
89
|
+
### Values Lamp fills
|
|
90
|
+
|
|
91
|
+
Write `{name}`; Lamp fills it, checked to a safe alphabet. You never write a value yourself.
|
|
92
|
+
|
|
93
|
+
- `{address}` the device's address, `{mac}` this Mac's address on that network, `{deviceID}` the device's id
|
|
94
|
+
- `{package}` the built package's file, `{appID}` the app's id, `{key}` a remote key from `bridge.keys`, `{text}` one character being typed (only in `bridge.type`, in a path, form or body; in a path Lamp percent-encodes it)
|
|
95
|
+
- `{callback}` the sign-in's address back (only in `vendorSignIn.page`), `{signIn}` what that sign-in returned
|
|
96
|
+
- `{sshKey}` Lamp's public SSH key, for a device that must be told it
|
|
97
|
+
- `{field:<key>}` what the person typed in a step's field: only in a sign-in, a form, a header or a body, never in a path
|
|
98
|
+
or command
|
|
99
|
+
- `{read:<step>}` the value a step's check read
|
|
100
|
+
- `{cookie:<name>}` a cookie the device set earlier in the same sequence, only in a header (a CSRF token: a GET first,
|
|
101
|
+
then `"X-CSRF-Token": "{cookie:CSRF-Token}"` on the POST)
|
|
102
|
+
- `{packageFullName}` and `{appUserModelID}` a wrapped Windows package's names, and `{base64:<one of Lamp's values>}`
|
|
103
|
+
any of Lamp's values in base64, as some devices take an id in a query
|
|
104
|
+
- `{isGame}` "true" when the app is a game (Lamp's native games, or `{"game": true}` in the app's capabilities.json or its icon.json),
|
|
105
|
+
else "false", for a device that installs games differently from apps
|
|
106
|
+
|
|
107
|
+
### steps
|
|
108
|
+
|
|
109
|
+
The setup, in order. Each step is done when its `check` passes, never because anyone said so.
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"id": "developer-mode",
|
|
114
|
+
"title": "Turn on developer mode", // at most 8 words
|
|
115
|
+
"lines": ["Press Home three times on the remote", "Then Up, Up, Right, Left, Right, Left, Right",
|
|
116
|
+
"Choose Enable installer and restart", "Set a developer password when it asks"], // at most 8 lines, 16 words each
|
|
117
|
+
"wait": true, // hands on the device: Lamp checks again until it passes
|
|
118
|
+
"accepts": ["softwareRisk"],
|
|
119
|
+
"check": [{ "http": { "port": 8060, "path": "/query/device-info" }, "xml": "developer-enabled", "equals": "true" },
|
|
120
|
+
{ "tcp": 80 }],
|
|
121
|
+
"known": { "how": "read", "source": "https://developer.roku.com/docs/developer-program/getting-started/developer-setup.md" }
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- `show`: `[{"label": "This Mac", "value": "{mac}"}]`, Lamp's values shown large. `qr`: a value shown as a QR code.
|
|
126
|
+
- `field`: `{"key": "password", "label": "Developer password", "secret": true}`, what the person types; kept for that
|
|
127
|
+
device only and sent only to it.
|
|
128
|
+
- `link`: an https page to read. A step that roots, jailbreaks or unlocks a device is only ever a link the person
|
|
129
|
+
follows themselves.
|
|
130
|
+
- `run`: what Lamp does when the person presses the step's button, in order (primitives below).
|
|
131
|
+
- `check`: every condition must hold. Each is one of `http` (answers 2xx; with `json` or `xml`, the value `equals` or
|
|
132
|
+
`contains` something), `tcp` (a port that accepts a connection), `field` (the person typed it), `signedIn` (a
|
|
133
|
+
`vendorSignIn` came back).
|
|
134
|
+
- `model`: `true` when the value the check reads is the device's model, finer than what it says before it's set up
|
|
135
|
+
(an Xbox's description says Xbox One on every console; Device Portal's `/api/os/info` names the console).
|
|
136
|
+
- Every setting of the device's that the bridge needs is a step of its own, checked on the device, so it's found in
|
|
137
|
+
setup rather than when a builder first uses it: a Roku answers key presses only with Settings → System → Advanced
|
|
138
|
+
system settings → Control by mobile apps set to Enabled, which its device-info says
|
|
139
|
+
(`{"http": {"port": 8060, "path": "/query/device-info"}, "xml": "ecp-setting-mode", "equals": "enabled"}`; Roku's ECP
|
|
140
|
+
page doesn't list that field, but Rokus report it: enabled, limited, disabled or permissive). Never ask for a setting
|
|
141
|
+
looser than the bridge needs (a Roku's Permissive).
|
|
142
|
+
- `accepts`: what doing it may cost, from Lamp's list; Lamp writes the sentences. `account` (an account with the
|
|
143
|
+
maker), `softwareRisk` (it may stop working until reset), `warranty`, `dataWiped`, `updatesStop`, `protectionsOff`,
|
|
144
|
+
`commandRuns` (required by any step that runs `ssh` or a downloaded `tool`).
|
|
145
|
+
- `known`: only `{"how": "read", "source": "<https page>"}`. Lamp marks a step checked or done once it passes on a
|
|
146
|
+
device; the person sees "Not tried yet" until then.
|
|
147
|
+
|
|
148
|
+
### Primitives
|
|
149
|
+
|
|
150
|
+
A step's `run` and each bridge sequence are lists of these, one key each:
|
|
151
|
+
|
|
152
|
+
- `http`: a request (above).
|
|
153
|
+
- `probe`: `"tcp:8060"`, `"ssdp:<target>"` or `"bonjour:<type>"`; fails the sequence when the device doesn't answer.
|
|
154
|
+
- `stream`: `{"port": 8085}`, the device's log read line by line into the app's log (bridge.logs only).
|
|
155
|
+
- `ssh`: `{"user": "prisoner", "port": 9922, "command": "luna-send-pub -n 1 luna://… '{…}'", "explanation": "…"}`.
|
|
156
|
+
The person approves the exact command for that device first, with your explanation (plain words, at most 30). One
|
|
157
|
+
line; values are quoted by Lamp. Lamp pins the device's host key and forwards nothing.
|
|
158
|
+
- `tool`: `{"name": "<Lamp's tool>"}`, from Lamp's list (`unlock-device-key`: unlocks a key kept with `keep: "key"`
|
|
159
|
+
with the field `passphrase`), or `{"download": "https://…", "sha256": "<64 hex>", "arguments": […], "explanation": "…"}`
|
|
160
|
+
for another program, which runs confined to its own folder and the network after the person approves it.
|
|
161
|
+
- `vendorSignIn`: `{"page": "https://account.vendor.com/…?redirect_uri={callback}"}`, the vendor's page in the
|
|
162
|
+
browser; what comes back is `{signIn}`. Setup steps only.
|
|
163
|
+
- `wait`: seconds to wait, 1 to 30.
|
|
164
|
+
|
|
165
|
+
### bridge
|
|
166
|
+
|
|
167
|
+
How software goes on the device once it's set up. Each is a sequence of primitives. With `app`, this is all Lamp has
|
|
168
|
+
to make apps for the device with, and the builder of each app gets it as Lamp's own: `install` then `launch` when
|
|
169
|
+
the person presses Play (and at the end of a turn, or Reload, while the app is on the device), `look` for a picture of
|
|
170
|
+
its screen, `use` once for each of the remote's keys pressed (`{key}` is the device's name for it, from `keys`), `logs`
|
|
171
|
+
read into the app's log while it's open. The builder of an app never looks at or presses anything on the device itself,
|
|
172
|
+
only in its `preview` (below), so `look` and `use` are what Lamp's own test run of the integration (from the device's
|
|
173
|
+
setup window) goes through. What the device answers to `install` is shown to the builder, so a device that says there what it
|
|
174
|
+
made of the package (a compile error) needs nothing more. `stop` ends the app when the person stops it (Lamp presses
|
|
175
|
+
`home` when there's no `stop`, or the device refuses it), and for a wrapped package it also ends the copy on the device
|
|
176
|
+
before an update goes over it, with the values of the copy that's there. `running` says whether the app `launch` opened
|
|
177
|
+
is running: a request whose `expect` finds it among the device's processes, with `until` a few seconds. Lamp launches
|
|
178
|
+
again, with growing pauses, while the device refuses the launch or the app isn't running, and says so plainly when it
|
|
179
|
+
never opens. `type` types into a keyboard on the device's
|
|
180
|
+
screen, run once per character with `{text}` that character (a Roku's `/keypress/Lit_{text}`). `log` reads a log the app keeps on the device (a file) for the
|
|
181
|
+
builder, for a device with no log to stream. `remove` takes the app off the device when its project is deleted. With `app`,
|
|
182
|
+
each of `stop`, `remove` and `type` is there or named in `"lacks": ["type"]` when the device has no way to do it, so
|
|
183
|
+
Lamp can tell one forgotten from one that can't be; and every picture the scaffold names is in `files` or `icons`, and
|
|
184
|
+
`rules` names each library in `support`. `known` is Lamp's: once the device is set up, the person can have Lamp try the
|
|
185
|
+
integration on it (a test app put on, opened, pictured, pressed, typed into, stopped, put on again while open, and taken
|
|
186
|
+
off), and a run that passes marks the bridge with the device's model. What the run found comes back to you with the
|
|
187
|
+
next request in the device's setup conversation: fix the integration from the device's own words and send it again.
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
"bridge": {
|
|
191
|
+
"install": [{ "http": { "method": "POST", "port": 80, "path": "/plugin_install",
|
|
192
|
+
"auth": { "digest": true, "user": "rokudev", "password": "{field:password}" },
|
|
193
|
+
"form": { "mysubmit": "Install", "archive": "@{package}" } } }],
|
|
194
|
+
"launch": [{ "http": { "method": "POST", "port": 8060, "path": "/launch/dev" } }, { "wait": 3 }],
|
|
195
|
+
"look": [{ "http": { "method": "POST", "port": 80, "path": "/plugin_inspect",
|
|
196
|
+
"auth": { "digest": true, "user": "rokudev", "password": "{field:password}" },
|
|
197
|
+
"form": { "mysubmit": "Screenshot" } } },
|
|
198
|
+
{ "http": { "port": 80, "path": "/pkgs/dev.jpg", "keep": "picture",
|
|
199
|
+
"auth": { "digest": true, "user": "rokudev", "password": "{field:password}" } } }],
|
|
200
|
+
"use": [{ "http": { "method": "POST", "port": 8060, "path": "/keypress/{key}" } }],
|
|
201
|
+
"type": [{ "http": { "method": "POST", "port": 8060, "path": "/keypress/Lit_{text}" } }],
|
|
202
|
+
"stop": [{ "http": { "method": "POST", "port": 8060, "path": "/exit-app/dev" } }],
|
|
203
|
+
"remove": [{ "http": { "method": "POST", "port": 80, "path": "/plugin_install",
|
|
204
|
+
"auth": { "digest": true, "user": "rokudev", "password": "{field:password}" },
|
|
205
|
+
"form": { "mysubmit": "Delete", "archive": "" } } }],
|
|
206
|
+
"logs": [{ "stream": { "port": 8085 } }],
|
|
207
|
+
"keys": { "home": "Home", "up": "Up", "down": "Down", "left": "Left", "right": "Right", "select": "Select", "back": "Back" }
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### app
|
|
212
|
+
|
|
213
|
+
What's built for it: `{"lamp": "tv-web"}` for Lamp's own TV web app, or a kind you declare. A declared kind becomes
|
|
214
|
+
a kind of app people can wish for ("a Roku app that…"): `files` is each new app's scaffold, where `{{NAME}}` is the
|
|
215
|
+
app's name; `rules` is what its builder is told about writing for the device (the language, the layout, the screen,
|
|
216
|
+
how input arrives, where its output is printed, and how it plays sound: the device's own way for short effects and
|
|
217
|
+
for music, the formats it plays, and that a game keeps both quiet with a way to turn them off), as the only guide
|
|
218
|
+
they get; `package` is the shell command that
|
|
219
|
+
makes the package from the app's folder, run there in the app's sandbox with the system's own tools (`zip`, `tar`),
|
|
220
|
+
never anything to download; `output` is where it leaves it, which `"@{package}"` sends.
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
"app": { "declared": {
|
|
224
|
+
"files": { "manifest": "title={{NAME}}\nmajor_version=1\nmm_icon_focus_hd=pkg:/images/icon_focus_hd.png\n…", "source/main.brs": "sub Main()\n…\nend sub\n" },
|
|
225
|
+
"rules": "What a builder needs to know to write apps for it, in a few sentences.",
|
|
226
|
+
"package": "rm -f build/app.zip && mkdir -p build images && zip -qr build/app.zip manifest source components images",
|
|
227
|
+
"output": "build/app.zip",
|
|
228
|
+
"icons": { "images/icon_focus_hd.png": "290x218", "images/icon_focus_fhd.png": "540x405" }
|
|
229
|
+
} }
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The package step runs in the app's sandbox like every build.
|
|
233
|
+
|
|
234
|
+
`"support"` gives the app Lamp's building blocks (AI through the person's Mac, saved data, the package's own files),
|
|
235
|
+
by library to where they go in the app's folder: `"web": "Web/lamp.js"` for an app that's a web page (a script its
|
|
236
|
+
`index.html` loads before the app's own), `"brightscript": "components/Lamp"` for a Roku channel (a folder its
|
|
237
|
+
components include). Lamp writes them before every build, so keep them out of `files`, and make sure the package step
|
|
238
|
+
takes them into the package. Lamp tells the app where it is and gives it its token on the device itself.
|
|
239
|
+
|
|
240
|
+
`"icons"` gives the app its icon on the device, wherever the device shows one (a channel's poster on a Roku's home
|
|
241
|
+
screen, a tile, a splash screen, a launcher): by path in the app's folder to its size in pixels,
|
|
242
|
+
`"images/icon_focus_hd.png": "290x218"`, one for each picture the device's manifest names, at the sizes its maker
|
|
243
|
+
documents. Lamp draws the icon it made for the app at each path before every build (a dark tile until there is one), so name those paths in the scaffold's manifest, keep them out of `files`, and make
|
|
244
|
+
sure the package step takes them in. Never draw an icon in the scaffold or the package step. A device that shows no icon
|
|
245
|
+
for an app needs none.
|
|
246
|
+
|
|
247
|
+
`"support"` may also name `"three"`, three.js (the 3D library, with its light addons), as a folder in the app's web
|
|
248
|
+
folder (`"three": "Web/three"`): for a device whose web view runs WebGL 2 and ES modules and whose apps may be games or 3D
|
|
249
|
+
scenes. Lamp writes it with the others; say in the rules to load it through an import map (`"three"` to
|
|
250
|
+
`./three/three.module.js`, `"three/addons/"` to `./three/addons/`) from a module script.
|
|
251
|
+
|
|
252
|
+
`"preview": "Web"` is for a web app: the folder whose `index.html` Lamp opens at 1920x1080 in a window on the person's Mac,
|
|
253
|
+
for the builder to look at and try as it works (a TV app's preview), since the device's own screen can only be pictured,
|
|
254
|
+
not played. Play still puts the app on the device. Give one whenever the app is a web page; the rules should then say the
|
|
255
|
+
app must also work with the keyboard (arrows, Enter, Escape for the device's Back), which is how the preview is used.
|
|
256
|
+
|
|
257
|
+
`"wrap": "msix"` is for a device that takes Windows app packages (an Xbox in Developer Mode, through its Device
|
|
258
|
+
Portal): the package step leaves a `.zip` of the app's files, and Lamp makes the package itself, writing its manifest
|
|
259
|
+
(started at `start`, `index.html` unless said), its logos from the app's icon, and its signature with a certificate of
|
|
260
|
+
Lamp's. Install it with the package and `"@{certificate}"` in one form, and launch it by `{base64:appUserModelID}` and
|
|
261
|
+
`{base64:packageFullName}`. Never write a manifest or sign anything in the package step. With `"host": "webview2"` beside it, the
|
|
262
|
+
pages are shown in Lamp's own host for Chromium's WebView2 rather than the system's older EdgeHTML: much faster, WebGL 2
|
|
263
|
+
and current JavaScript, with the app's console in its log. Use it for a web app on an Xbox; `start` is then `index.html`.
|
|
264
|
+
|
|
265
|
+
`"purpose"` says in a few words what the kind is for ("an app with menus and pages"), for a device that takes more than
|
|
266
|
+
one kind. The integrations Lamp ships may offer more kinds beside `app` in `kinds` (the Xbox's native 3D games,
|
|
267
|
+
`{"lamp": "native-game"}`); an integration you write has only `app`.
|
|
268
|
+
|
|
269
|
+
`"runs"`, beside `app`, says in one plain sentence what the device runs ("Only its own channels, written in BrightScript
|
|
270
|
+
and driven by the remote: no web pages, no 3D"). Lamp gives it as the reason when something the device can't run is asked
|
|
271
|
+
of it, so write it for the person, from the device's documentation.
|
|
272
|
+
|
|
273
|
+
## Checking it before you send
|
|
274
|
+
|
|
275
|
+
- Every step has a check that asks the device (or a field the step itself asks for).
|
|
276
|
+
- Every `{…}` is one of Lamp's values above, and a field is only in a sign-in, form, header or body.
|
|
277
|
+
- Titles and lines are short and in plain words, for someone who has never done this.
|
|
278
|
+
- A step written from documentation says where (`known.source`).
|