this.type='CmdXXX';// Required: has to match the object-name!
this.type='DoSomethingCommand';// Required: has to match the object-name!
this.name='Set/Do/Update XXX';// Required: description of the command, used in Sidebar.History
this.name='Set/Do/Update Something';// Required: description of the command, used in Sidebar.History
// TODO: store all the relevant information needed to
// TODO: store all the relevant information needed to
// restore the old and the new state
// restore the old and the new state
...
@@ -46,7 +46,7 @@ And as part of the prototype you need to implement four functions
...
@@ -46,7 +46,7 @@ And as part of the prototype you need to implement four functions
-**fromJSON:** which deserializes the command
-**fromJSON:** which deserializes the command
```javascript
```javascript
CmdXXX.prototype={
DoSomethingCommand.prototype={
execute:function(){
execute:function(){
...
@@ -62,21 +62,21 @@ CmdXXX.prototype = {
...
@@ -62,21 +62,21 @@ CmdXXX.prototype = {
toJSON:function(){
toJSON:function(){
varoutput=Cmd.prototype.toJSON.call(this);// Required: Call 'toJSON'-method of prototype 'Cmd'
varoutput=Command.prototype.toJSON.call(this);// Required: Call 'toJSON'-method of prototype 'Command'
// TODO: serialize all the necessary information as part of 'output' (JSON-format)
// TODO: serialize all the necessary information as part of 'output' (JSON-format)
// so that it can be restored in 'fromJSON'
// so that it can be restored in 'fromJSON'
returnoutput;
returnoutput;
},
},
fromJSON:function(json){
fromJSON:function(json){
Cmd.prototype.fromJSON.call(this,json);// Required: Call 'fromJSON'-method of prototype 'Cmd'
Command.prototype.fromJSON.call(this,json);// Required: Call 'fromJSON'-method of prototype 'Command'
// TODO: restore command from json
// TODO: restore command from json
}
}
};
};
...
@@ -89,9 +89,9 @@ To execute a command we need an instance of the main editor-object. The editor-o
...
@@ -89,9 +89,9 @@ To execute a command we need an instance of the main editor-object. The editor-o
On **editor** we then call **.execute(...)*** with the new command-object which in turn calls **history.execute(...)** and adds the command to the undo-stack.
On **editor** we then call **.execute(...)*** with the new command-object which in turn calls **history.execute(...)** and adds the command to the undo-stack.
```javascript
```javascript
editor.execute(newCmdXXX());
editor.execute(newDoSomethingCommand());
```
```
### Updatable commands ###
### Updatable commands ###
...
@@ -99,7 +99,7 @@ editor.execute( new CmdXXX() );
...
@@ -99,7 +99,7 @@ editor.execute( new CmdXXX() );
Some commands are also **updatable**. By default a command is not updatable. Making a command updatable means that you
Some commands are also **updatable**. By default a command is not updatable. Making a command updatable means that you
have to implement a fifth function 'update' as part of the prototype. In it only the 'new' state gets updated while the old one stays the same.
have to implement a fifth function 'update' as part of the prototype. In it only the 'new' state gets updated while the old one stays the same.
Here as an example is the update-function of **CmdSetColor**:
Here as an example is the update-function of **SetColorCommand**:
```javascript
```javascript
update:function(cmd){
update:function(cmd){
...
@@ -112,15 +112,15 @@ update: function ( cmd ) {
...
@@ -112,15 +112,15 @@ update: function ( cmd ) {
#### List of updatable commands
#### List of updatable commands
-CmdSetColor
-SetColorCommand
-CmdSetGeometry
-SetGeometryCommand
-CmdSetMaterialColor
-SetMaterialColorCommand
-CmdSetMaterialValue
-SetMaterialValueCommand
-CmdSetPosition
-SetPositionCommand
-CmdSetRotation
-SetRotationCommand
-CmdSetScale
-SetScaleCommand
-CmdSetValue
-SetValueCommand
-CmdSetScriptValue
-SetScriptValueCommand
The idea behind 'updatable commands' is that two commands of the same type which occur
The idea behind 'updatable commands' is that two commands of the same type which occur
within a short period of time should be merged into one.
within a short period of time should be merged into one.
// var perspectiveCamera = aPerspectiveCamera( 'Name your perspectiveCamera' );
// var perspectiveCamera = aPerspectiveCamera( 'Name your perspectiveCamera' );
// in most cases you'll need to add the object to work with
// in most cases you'll need to add the object to work with
editor.execute(newCmdAddObject(box));
editor.execute(newAddObjectCommand(box));
// your test begins here...
// your test begins here...
});
});
```
```
The predefined code is just meant to ease the development, you do not have to stick with it.
The predefined code is just meant to ease the development, you do not have to stick with it.
However, the test should cover at least one `editor.execute()`, one `editor.undo()` and one `editor.redo()` call.
However, the test should cover at least one `editor.execute()`, one `editor.undo()` and one `editor.redo()` call.
Best practice is to call `editor.execute( new CmdXXX( {custom parameters} ) )`**twice**. Since you'll have to do one undo (go one step back), it is recommended to have a custom state for comparison. Try to avoid assertions `ok()` against default values.
Best practice is to call `editor.execute( new DoSomethingCommand( {custom parameters} ) )`**twice**. Since you'll have to do one undo (go one step back), it is recommended to have a custom state for comparison. Try to avoid assertions `ok()` against default values.
#### Assertions ####
#### Assertions ####
After performing `editor.execute()` twice, you can do your first assertion to check whether the executes are done correctly.
After performing `editor.execute()` twice, you can do your first assertion to check whether the executes are done correctly.
ok(object[item]==valueBefore," OK, the attribute '"+item+"' is correct after first execute (expected: '"+valueBefore+"', actual: '"+object[item]+"')");
ok(object[item]==valueBefore," OK, the attribute '"+item+"' is correct after first execute (expected: '"+valueBefore+"', actual: '"+object[item]+"')");