@@ -10,9 +10,10 @@ export type AbilityInit = {
1010 inventoryIsInfinite ?: boolean ;
1111} ;
1212export type AbilityEnableOptions = {
13- copy : boolean ;
14- paste : boolean ;
15- cut : boolean ;
13+ // 回数 or Number.POSITIVE_INFINITY
14+ copy : number ;
15+ paste : number ;
16+ cut : number ;
1617} ;
1718type History = {
1819 at : { x : number ; y : number } ;
@@ -22,6 +23,10 @@ type History = {
2223 before : Block | null ;
2324 after : Block | null ;
2425 } ;
26+ enabled : {
27+ before : AbilityEnableOptions ;
28+ after : AbilityEnableOptions ;
29+ } ;
2530} ;
2631export class AbilityControl {
2732 history : History [ ] = [ ] ;
@@ -32,27 +37,30 @@ export class AbilityControl {
3237 focused : Coords | undefined ;
3338 constructor ( cx : Context , options ?: AbilityInit ) {
3439 this . enabled = options ?. enabled ?? {
35- copy : true ,
36- paste : true ,
37- cut : true ,
40+ copy : Number . POSITIVE_INFINITY ,
41+ paste : Number . POSITIVE_INFINITY ,
42+ cut : Number . POSITIVE_INFINITY ,
3843 } ;
3944 this . inventoryIsInfinite = options ?. inventoryIsInfinite ?? false ;
4045 cx . uiContext . update ( ( prev ) => ( {
4146 ...prev ,
4247 inventory : this . inventory ,
4348 inventoryIsInfinite : this . inventoryIsInfinite ,
49+ ...this . enabled ,
50+ undo : 0 ,
51+ redo : 0 ,
4452 } ) ) ;
4553 document . addEventListener ( "copy" , ( e ) => {
4654 e . preventDefault ( ) ;
47- if ( this . enabled . copy ) this . copy ( cx ) ;
55+ if ( this . enabled . copy > 0 ) this . copy ( cx ) ;
4856 } ) ;
4957 document . addEventListener ( "cut" , ( e ) => {
5058 e . preventDefault ( ) ;
51- if ( this . enabled . cut ) this . cut ( cx ) ;
59+ if ( this . enabled . cut > 0 ) this . cut ( cx ) ;
5260 } ) ;
5361 document . addEventListener ( "paste" , ( e ) => {
5462 e . preventDefault ( ) ;
55- if ( this . enabled . paste ) this . paste ( cx ) ;
63+ if ( this . enabled . paste > 0 ) this . paste ( cx ) ;
5664 } ) ;
5765 }
5866 setInventory ( cx : Context , inventory : Block | null ) {
@@ -85,6 +93,10 @@ export class AbilityControl {
8593 const target = cx . grid . getBlock ( this . focused . x , this . focused . y ) ;
8694 if ( ! target || target !== Block . movable ) return ;
8795 this . setInventory ( cx , target ) ;
96+ cx . uiContext . update ( ( prev ) => ( {
97+ ...prev ,
98+ copy : -- this . enabled . copy ,
99+ } ) ) ;
88100 }
89101 paste ( cx : Context ) {
90102 if ( ! this . focused ) return ;
@@ -96,15 +108,23 @@ export class AbilityControl {
96108 if ( ! this . inventoryIsInfinite ) {
97109 this . setInventory ( cx , null ) ;
98110 }
99-
100- this . pushHistory ( {
111+ const prevEnabled = { ...this . enabled } ;
112+ cx . uiContext . update ( ( prev ) => ( {
113+ ...prev ,
114+ paste : -- this . enabled . paste ,
115+ } ) ) ;
116+ this . pushHistory ( cx , {
101117 at : { ...this . focused } ,
102118 from : Block . air ,
103119 to : prevInventory ,
104120 inventory : {
105121 before : prevInventory ,
106122 after : this . inventory ,
107123 } ,
124+ enabled : {
125+ before : prevEnabled ,
126+ after : this . enabled ,
127+ } ,
108128 } ) ;
109129 }
110130 cut ( cx : Context ) {
@@ -115,31 +135,51 @@ export class AbilityControl {
115135 const prevInventory = this . inventory ;
116136 this . setInventory ( cx , target ) ;
117137 cx . grid . setBlock ( cx , this . focused . x , this . focused . y , Block . air ) ;
118-
119- this . pushHistory ( {
138+ const prevEnabled = { ...this . enabled } ;
139+ cx . uiContext . update ( ( prev ) => ( {
140+ ...prev ,
141+ cut : -- this . enabled . cut ,
142+ } ) ) ;
143+ this . pushHistory ( cx , {
120144 at : { ...this . focused } ,
121145 from : target ,
122146 to : Block . air ,
123147 inventory : {
124148 before : prevInventory ,
125149 after : target ,
126150 } ,
151+ enabled : {
152+ before : prevEnabled ,
153+ after : this . enabled ,
154+ } ,
127155 } ) ;
128156 }
129157
130158 // History については、 `docs/history-stack.png` を参照のこと
131- pushHistory ( h : History ) {
159+ pushHistory ( cx : Context , h : History ) {
132160 this . history = this . history . slice ( 0 , this . historyIndex ) ;
133161 this . history . push ( h ) ;
134162 this . historyIndex = this . history . length ;
135163 console . log ( `history: ${ this . historyIndex } / ${ this . history . length } ` ) ;
164+ cx . uiContext . update ( ( prev ) => ( {
165+ ...prev ,
166+ undo : this . historyIndex ,
167+ redo : 0 ,
168+ } ) ) ;
136169 }
137170 undo ( cx : Context ) {
138171 if ( this . historyIndex <= 0 ) return ;
139172 this . historyIndex -- ; // undo は、巻き戻し後の index で計算する
140173 const op = this . history [ this . historyIndex ] ;
141174 cx . grid . setBlock ( cx , op . at . x , op . at . y , op . from ) ;
142175 this . setInventory ( cx , op . inventory . before ) ;
176+ this . enabled = op . enabled . before ;
177+ cx . uiContext . update ( ( prev ) => ( {
178+ ...prev ,
179+ ...this . enabled ,
180+ undo : this . historyIndex ,
181+ redo : this . history . length - this . historyIndex ,
182+ } ) ) ;
143183 console . log ( `history: ${ this . historyIndex } / ${ this . history . length } ` ) ;
144184 }
145185 redo ( cx : Context ) {
@@ -148,20 +188,27 @@ export class AbilityControl {
148188 this . historyIndex ++ ; // redo は、巻き戻し前の index
149189 this . setInventory ( cx , op . inventory . after ) ;
150190 cx . grid . setBlock ( cx , op . at . x , op . at . y , op . to ) ;
191+ this . enabled = op . enabled . after ;
192+ cx . uiContext . update ( ( prev ) => ( {
193+ ...prev ,
194+ ...this . enabled ,
195+ undo : this . historyIndex ,
196+ redo : this . history . length - this . historyIndex ,
197+ } ) ) ;
151198 console . log ( `history: ${ this . historyIndex } / ${ this . history . length } ` ) ;
152199 }
153- handleKeyDown ( cx : Context , e : KeyboardEvent , onGround : boolean ) {
200+ handleKeyDown ( cx : Context , e : KeyboardEvent /* , onGround: boolean*/ ) {
154201 if ( ! ( e . ctrlKey || e . metaKey ) ) return ;
155202
156- if ( this . enabled . paste && onGround && e . key === "v" ) {
157- this . paste ( cx ) ;
158- }
159- if ( this . enabled . copy && onGround && e . key === "c" ) {
160- this . copy ( cx ) ;
161- }
162- if ( this . enabled . cut && onGround && e . key === "x" ) {
163- this . cut ( cx ) ;
164- }
203+ // if (this.enabled.paste > 0 && onGround && e.key === "v") {
204+ // this.paste(cx);
205+ // }
206+ // if (this.enabled.copy > 0 && onGround && e.key === "c") {
207+ // this.copy(cx);
208+ // }
209+ // if (this.enabled.cut > 0 && onGround && e.key === "x") {
210+ // this.cut(cx);
211+ // }
165212 if ( e . key === "z" ) {
166213 this . undo ( cx ) ;
167214 e . preventDefault ( ) ;
0 commit comments