diff --git a/report/schemas.api.md b/report/schemas.api.md index 21b2f7a5..5358f5a4 100644 --- a/report/schemas.api.md +++ b/report/schemas.api.md @@ -2639,6 +2639,16 @@ export namespace IPFSv2 { validate: ValidateFunction; } +// Warning: (ae-missing-release-tag) "IPhysicsController" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IPhysicsController { + // Warning: (ae-incompatible-release-tags) The symbol "setSpringBonesParams" is marked as @public, but its signature references "SpringBoneParams" which is marked as @alpha + // + // (undocumented) + setSpringBonesParams(itemHash: string, params: Record): Promise; +} + // Warning: (ae-missing-release-tag) "IPreviewController" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2646,6 +2656,8 @@ export interface IPreviewController { // (undocumented) emote: IEmoteController; // (undocumented) + physics: IPhysicsController; + // (undocumented) scene: ISceneController; } @@ -4004,8 +4016,8 @@ export type PreviewMessagePayload = T extends Prev options: PreviewOptions; } : T extends PreviewMessageType.CONTROLLER_REQUEST ? { id: string; - namespace: 'scene' | 'emote'; - method: 'getScreenshot' | 'getMetrics' | 'changeZoom' | 'changeCameraPosition' | 'panCamera' | 'cleanup' | 'getLength' | 'isPlaying' | 'play' | 'pause' | 'stop' | 'goTo' | 'enableSound' | 'disableSound' | 'hasSound' | 'setUsername'; + namespace: 'scene' | 'emote' | 'physics'; + method: 'getScreenshot' | 'getMetrics' | 'changeZoom' | 'changeCameraPosition' | 'panCamera' | 'cleanup' | 'getLength' | 'isPlaying' | 'play' | 'pause' | 'stop' | 'goTo' | 'enableSound' | 'disableSound' | 'hasSound' | 'setUsername' | 'setSpringBonesParams'; params: any[]; } : T extends PreviewMessageType.CONTROLLER_RESPONSE ? { id: string; @@ -4896,6 +4908,23 @@ export namespace SpawnPoint { validate: ValidateFunction; } +// @alpha (undocumented) +export type SpringBoneParams = { + stiffness: number; + gravityPower: number; + gravityDir: [number, number, number]; + dragForce: number; + center?: number; +}; + +// @alpha (undocumented) +export namespace SpringBoneParams { + const // (undocumented) + schema: JSONSchema; + const // (undocumented) + validate: ValidateFunction; +} + // Warning: (ae-missing-release-tag) "StandardProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -6005,7 +6034,7 @@ export namespace WorldUndeploymentEvent { // src/dapps/preview/preview-config.ts:22:3 - (ae-incompatible-release-tags) The symbol "bodyShape" is marked as @public, but its signature references "BodyShape" which is marked as @alpha // src/dapps/preview/preview-config.ts:27:3 - (ae-incompatible-release-tags) The symbol "type" is marked as @public, but its signature references "PreviewType" which is marked as @alpha // src/dapps/preview/preview-message.ts:38:7 - (ae-incompatible-release-tags) The symbol "options" is marked as @public, but its signature references "PreviewOptions" which is marked as @alpha -// src/dapps/preview/preview-message.ts:77:7 - (ae-forgotten-export) The symbol "EmoteEventPayload" needs to be exported by the entry point index.d.ts +// src/dapps/preview/preview-message.ts:78:7 - (ae-forgotten-export) The symbol "EmoteEventPayload" needs to be exported by the entry point index.d.ts // src/dapps/rentals-listings.ts:85:3 - (ae-incompatible-release-tags) The symbol "network" is marked as @public, but its signature references "Network" which is marked as @alpha // src/dapps/rentals-listings.ts:126:3 - (ae-incompatible-release-tags) The symbol "network" is marked as @public, but its signature references "Network" which is marked as @alpha // src/dapps/rentals-listings.ts:128:3 - (ae-incompatible-release-tags) The symbol "chainId" is marked as @public, but its signature references "ChainId" which is marked as @alpha diff --git a/src/dapps/preview/index.ts b/src/dapps/preview/index.ts index 3e30bafe..e56512bd 100644 --- a/src/dapps/preview/index.ts +++ b/src/dapps/preview/index.ts @@ -7,6 +7,7 @@ export * from './preview-message' export * from './preview-options' export * from './preview-projection' export * from './preview-type' +export * from './spring-bone-params' export * from './wearable-representation-definition' export * from './wearable-representation-with-blobs' export * from './wearable-definition' diff --git a/src/dapps/preview/preview-controller.ts b/src/dapps/preview/preview-controller.ts index bfcb7237..121bc93d 100644 --- a/src/dapps/preview/preview-controller.ts +++ b/src/dapps/preview/preview-controller.ts @@ -3,10 +3,12 @@ import type { Metrics } from '../../platform/item/metrics' import type { PreviewEmoteEventType } from './preview-emote-event-type' import { SocialEmoteAnimation } from './social-emote-animation' import { EmoteDefinition } from './emote-definition' +import { SpringBoneParams } from './spring-bone-params' export interface IPreviewController { scene: ISceneController emote: IEmoteController + physics: IPhysicsController } export type EmoteEvents = { @@ -43,3 +45,7 @@ export interface IEmoteController { emote: EmoteDefinition | null events: Emitter } + +export interface IPhysicsController { + setSpringBonesParams(itemHash: string, params: Record): Promise +} diff --git a/src/dapps/preview/preview-message.ts b/src/dapps/preview/preview-message.ts index 0d8cda6d..2b28321e 100644 --- a/src/dapps/preview/preview-message.ts +++ b/src/dapps/preview/preview-message.ts @@ -39,7 +39,7 @@ export type PreviewMessagePayload = T extends Prev : T extends PreviewMessageType.CONTROLLER_REQUEST ? { id: string - namespace: 'scene' | 'emote' + namespace: 'scene' | 'emote' | 'physics' method: | 'getScreenshot' | 'getMetrics' @@ -57,6 +57,7 @@ export type PreviewMessagePayload = T extends Prev | 'disableSound' | 'hasSound' | 'setUsername' + | 'setSpringBonesParams' params: any[] } : T extends PreviewMessageType.CONTROLLER_RESPONSE diff --git a/src/dapps/preview/spring-bone-params.ts b/src/dapps/preview/spring-bone-params.ts new file mode 100644 index 00000000..92733efe --- /dev/null +++ b/src/dapps/preview/spring-bone-params.ts @@ -0,0 +1,32 @@ +import { generateLazyValidator, JSONSchema, ValidateFunction } from '../../validation' + +/** @alpha */ +export type SpringBoneParams = { + stiffness: number + gravityPower: number + gravityDir: [number, number, number] + dragForce: number + center?: number +} + +/** @alpha */ +export namespace SpringBoneParams { + export const schema: JSONSchema = { + type: 'object', + properties: { + stiffness: { type: 'number', minimum: 0, maximum: 5 }, + gravityPower: { type: 'number', minimum: 0, maximum: 10 }, + gravityDir: { + type: 'array', + items: [{ type: 'number' }, { type: 'number' }, { type: 'number' }], + minItems: 3, + maxItems: 3 + }, + dragForce: { type: 'number', minimum: 0, maximum: 1 }, + center: { type: 'integer', minimum: 0, nullable: true } + }, + required: ['stiffness', 'gravityPower', 'gravityDir', 'dragForce'] + } + + export const validate: ValidateFunction = generateLazyValidator(schema) +} diff --git a/test/dapps/preview/spring-bone-params.spec.ts b/test/dapps/preview/spring-bone-params.spec.ts new file mode 100644 index 00000000..f7a26ad6 --- /dev/null +++ b/test/dapps/preview/spring-bone-params.spec.ts @@ -0,0 +1,52 @@ +import expect from 'expect' +import { SpringBoneParams } from '../../../src' +import { testTypeSignature } from '../../test-utils' + +describe('SpringBoneParams tests', () => { + const springBoneParams: SpringBoneParams = { + stiffness: 1.5, + gravityPower: 3.0, + gravityDir: [0, -1, 0], + dragForce: 0.4 + } + + testTypeSignature(SpringBoneParams, springBoneParams) + + it('static tests must pass', () => { + expect(SpringBoneParams.validate(springBoneParams)).toEqual(true) + expect(SpringBoneParams.validate(null)).toEqual(false) + expect(SpringBoneParams.validate({})).toEqual(false) + }) + + it('validates with optional center field', () => { + expect(SpringBoneParams.validate({ ...springBoneParams, center: 5 })).toEqual(true) + }) + + it('validates without optional center field', () => { + expect(SpringBoneParams.validate({ ...springBoneParams })).toEqual(true) + }) + + it('rejects stiffness out of range', () => { + expect(SpringBoneParams.validate({ ...springBoneParams, stiffness: 6 })).toEqual(false) + expect(SpringBoneParams.validate({ ...springBoneParams, stiffness: -1 })).toEqual(false) + }) + + it('rejects gravityPower out of range', () => { + expect(SpringBoneParams.validate({ ...springBoneParams, gravityPower: 11 })).toEqual(false) + expect(SpringBoneParams.validate({ ...springBoneParams, gravityPower: -0.1 })).toEqual(false) + }) + + it('rejects dragForce out of range', () => { + expect(SpringBoneParams.validate({ ...springBoneParams, dragForce: 1.1 })).toEqual(false) + expect(SpringBoneParams.validate({ ...springBoneParams, dragForce: -0.01 })).toEqual(false) + }) + + it('rejects gravityDir with wrong length', () => { + expect(SpringBoneParams.validate({ ...springBoneParams, gravityDir: [0, -1] as any })).toEqual(false) + expect(SpringBoneParams.validate({ ...springBoneParams, gravityDir: [0, -1, 0, 0] as any })).toEqual(false) + }) + + it('rejects missing required fields', () => { + expect(SpringBoneParams.validate({ stiffness: 1, gravityPower: 1, gravityDir: [0, -1, 0] })).toEqual(false) + }) +})