1+ import { Track , UniformProxyFactory , VectorTrack } from "../../../cocos/animation/animation" ;
2+ import { AnimationClip } from "../../../cocos/animation/animation-clip" ;
3+ import { AnimationState } from "../../../cocos/animation/animation-state" ;
4+ import { Pass } from "../../../cocos/render-scene" ;
5+ import { Component , Node } from "../../../cocos/scene-graph" ;
6+ import { director , EffectAsset , js , Material , Vec3 } from "../../../exports/base" ;
7+ import { captureWarnIDs } from "../../utils/log-capture" ;
8+
9+ describe ( `Error sentences` , ( ) => {
10+ beforeAll ( ( ) => js . setClassName ( 'MaterialHost' , MaterialHost ) ) ;
11+ afterAll ( ( ) => js . unregisterClass ( MaterialHost ) ) ;
12+
13+ test ( `Warn if input target is not a material` , ( ) => {
14+ const origin = new Node ( 'SomeOrigin' ) ;
15+ const materialHost = origin . addComponent ( MaterialHost ) as MaterialHost ;
16+
17+ const track = new VectorTrack ( ) ;
18+ track . channels ( ) [ 0 ] . curve . assignSorted ( [ [ 0.0 , 0.0 ] ] ) ;
19+ track . path . toComponent ( MaterialHost ) ;
20+ track . proxy = new UniformProxyFactory ( ) ;
21+
22+ bindThenAssertWarn ( origin , track , [ 3940 , materialHost ] ) ;
23+ } ) ;
24+
25+ test ( `Warn if recorded pass index is invalid` , ( ) => {
26+ const origin = new Node ( 'SomeOrigin' ) ;
27+ const materialHost = origin . addComponent ( MaterialHost ) as MaterialHost ;
28+ const material = materialHost . material = mockMaterial ( [
29+ { uniforms : { } } ,
30+ { uniforms : { } } ,
31+ { uniforms : { } } ,
32+ ] ) ;
33+ material . name = 'SomeMaterial' ;
34+
35+ const track = new VectorTrack ( ) ;
36+ track . channels ( ) [ 0 ] . curve . assignSorted ( [ [ 0.0 , 0.0 ] ] ) ;
37+ track . path . toComponent ( MaterialHost ) . toProperty ( 'material' ) ;
38+
39+ const proxyFactory = track . proxy = new UniformProxyFactory ( ) ;
40+ for ( const passIndex of [ - 2 , - 1 , 3 , 4 ] ) {
41+ proxyFactory . passIndex = passIndex ;
42+ bindThenAssertWarn ( origin , track , [ 3941 , material . name , proxyFactory . passIndex ] ) ;
43+ }
44+ } ) ;
45+
46+ test ( `Warn if recorded uniform name is in invalid` , ( ) => {
47+ const origin = new Node ( 'SomeOrigin' ) ;
48+ const materialHost = origin . addComponent ( MaterialHost ) as MaterialHost ;
49+ const material = materialHost . material = mockMaterial ( [
50+ { uniforms : { 'SomeUniform' : { availableChannelCount : 3 } } } ,
51+ { uniforms : { } } ,
52+ { uniforms : { } } ,
53+ ] ) ;
54+ material . name = 'SomeMaterial' ;
55+
56+ const track = new VectorTrack ( ) ;
57+ track . channels ( ) [ 0 ] . curve . assignSorted ( [ [ 0.0 , 0.0 ] ] ) ;
58+ track . path . toComponent ( MaterialHost ) . toProperty ( 'material' ) ;
59+ const proxyFactory = track . proxy = new UniformProxyFactory ( ) ;
60+ proxyFactory . passIndex = 1 ;
61+ proxyFactory . uniformName = 'SomeUniform' ;
62+ proxyFactory . channelIndex = 4 ;
63+
64+ bindThenAssertWarn ( origin , track , [ 3942 , material . name , proxyFactory . passIndex , proxyFactory . uniformName ] ) ;
65+ } ) ;
66+
67+ test ( `Warn if recorded channel index is invalid` , ( ) => {
68+ const origin = new Node ( 'SomeOrigin' ) ;
69+ const materialHost = origin . addComponent ( MaterialHost ) as MaterialHost ;
70+ const material = materialHost . material = mockMaterial ( [
71+ { uniforms : { } } ,
72+ { uniforms : { 'SomeUniform' : { availableChannelCount : 3 } } } ,
73+ { uniforms : { } } ,
74+ ] ) ;
75+ material . name = 'SomeMaterial' ;
76+
77+ const track = new VectorTrack ( ) ;
78+ track . channels ( ) [ 0 ] . curve . assignSorted ( [ [ 0.0 , 0.0 ] ] ) ;
79+ track . path . toComponent ( MaterialHost ) . toProperty ( 'material' ) ;
80+ const proxyFactory = track . proxy = new UniformProxyFactory ( ) ;
81+ proxyFactory . passIndex = 1 ;
82+ proxyFactory . uniformName = 'SomeUniform' ;
83+
84+ for ( const channelIndex of [ - 1 , - 2 , 3 , 4 ] ) {
85+ proxyFactory . channelIndex = channelIndex ;
86+ bindThenAssertWarn ( origin , track , [ 3943 , material . name , proxyFactory . passIndex , proxyFactory . uniformName , proxyFactory . channelIndex ] ) ;
87+ }
88+ } ) ;
89+
90+ class MaterialHost extends Component {
91+ public declare material : Material ;
92+ }
93+
94+ function bindThenAssertWarn (
95+ root : Node ,
96+ track : Track ,
97+ expectedCapturedWarns : [ warnId : number , ...optionalParams : any [ ] ]
98+ ) {
99+ const animationClip = new AnimationClip ( ) ;
100+ animationClip . name = 'Meow' ;
101+ animationClip . duration = 1.0 ;
102+ animationClip . addTrack ( track ) ;
103+
104+ const warnWatcher = captureWarnIDs ( ) ;
105+
106+ const state = new AnimationState ( animationClip ) ;
107+ state . initialize ( root ) ;
108+
109+ expect ( warnWatcher . captured ) . toHaveLength ( 2 ) ;
110+ expect ( warnWatcher . captured [ 0 ] ) . toStrictEqual ( expectedCapturedWarns ) ;
111+ expect ( warnWatcher . captured [ 1 ] ) . toStrictEqual ( [ 3937 , 'Meow' , root . name ] ) ;
112+ warnWatcher . clear ( ) ;
113+ warnWatcher . stop ( ) ;
114+ }
115+
116+ function mockMaterial ( passMocks : Array < {
117+ uniforms : Record < string , { availableChannelCount : number } > ;
118+ } > ) {
119+ const passes = passMocks . map ( ( passMock ) => {
120+ const pass = new Pass ( director . root ! ) ;
121+ jest . spyOn ( pass , 'getHandle' ) . mockImplementation ( ( name , offset ) => {
122+ const uniformMock = passMock . uniforms [ name ] ;
123+ if ( ! uniformMock ) {
124+ return 0 ;
125+ }
126+ if ( typeof offset !== 'undefined' && ( offset < 0 || offset >= uniformMock . availableChannelCount ) ) {
127+ return 0 ;
128+ }
129+ return 1 ;
130+ } ) ;
131+ return pass ;
132+ } ) ;
133+
134+ const material = new Material ( ) ;
135+ jest . spyOn ( material , 'passes' , 'get' ) . mockReturnValue ( passes ) ;
136+
137+ return material ;
138+ }
139+ } ) ;
0 commit comments