Tutorials, extensions, and source files for ActionScript, Flash, and other Adobe products.

 

senocular.com ActionScript Library

history.as

Name: history - movieclip drawing history: maintains drawing commands so they can be reused or copied.
Author: senocular: www.senocular.com
Date: 1899-12-31T00:53:16.100
Documentation:
MovieClip HISTORY: Saves dynamic drawing actions within
a history object in a movieclip (includes
createEmptyMovieClip). Basically the drawing methods and
createEmptyMovieclip are rewritten with the
same name but with an h on the end i.e. moveToh(0,0);
When the h is included, the function is retained in the
movieclip's history object.  this history can be recalled
by using myMovieClip.history.recall(); which will run
through and run those saved methods again.  clear is not
saved though there is a clearh() clears the clip and clears
the history of all drawing methods (not createEmptyMovieclip).
The history of a movieclip is added whenever an h
version of any of the methods are run.

myMovieClip.lineStyleh(1,0xff,100);
myMovieClip.moveToh(100,100);
myMovieClip.lineToh(200,200);
trace(myMovieClip.history);
myMovieClip.history.recall();
// etc...

Methods:
history(mc, records);
history.setEpoch(mc);
history.getEpoch();
history.setRecords(records);
history.getRecords();
history.addEvent(func, args [, hist])
history.shareWith(mc);
history.copyTo(mc);
history.copy();
history.claim();
history.clear();
history.recall([mc]);
history.toString();

MovieClipObj.duplicateWithHistory(name, depth [, claim]);
MovieClipObj.empty();
MovieClipObj.lineStyleh();
MovieClipObj.beginFillh();
MovieClipObj.beginGradientFillh();
MovieClipObj.endFillh();
MovieClipObj.moveToh();
MovieClipObj.lineToh();
MovieClipObj.curveToh();
MovieClipObj.createEmptyMovieClipObjh(name, depth);
MovieClipObj.clearh();


- I chose to not override the drawing methods for reasons of speed - using the normal
methods would be (obviously) much faster without all this history recording involved

Example:
with(this.createEmptyMovieClip("thing",1)){
	lineStyleh(1,0);
	moveToh(50,50);
	beginFillh(0xffaa00);
	lineToh(100,50);
	lineToh(100,100);
	lineToh(150,100);
	endFillh();
	trace(history);
	with(createEmptyMovieCliph("added", 1)){
		lineStyleh(5,0xff0000);
		moveToh(75,75);
		lineToh(125,75);
		trace(history);
	}
}
thing.duplicateWithHistory("thing2",2);
thing2._x += 100;
trace(thing2.history);

// output:
thing.history.recall = function(){
	this.lineStyle(1,0);
	this.moveTo(50,50);
	this.beginFill(16755200);
	this.lineTo(100,50);
	this.lineTo(100,100);
	this.lineTo(150,100);
	this.endFill();
}
added.history.recall = function(){
	this.lineStyle(5,16711680);
	this.moveTo(75,75);
	this.lineTo(125,75);
}
thing2.history.recall = function(){
	this.lineStyle(1,0);
	this.moveTo(50,50);
	this.beginFill(16755200);
	this.lineTo(100,50);
	this.lineTo(100,100);
	this.lineTo(150,100);
	this.endFill();
	this.createEmptyMovieClip("added",1);
	this.added.history.recall = function(){
		this.lineStyle(5,16711680);
		this.moveTo(75,75);
		this.lineTo(125,75);
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
HistoryArchive = function(mc, ary){
	this.epoch = mc;
	if (!ary) this.records = [];
	else this.records = ary;
}
HistoryArchive.prototype.setEpoch = function(mc){ this.epoch = mc; }
HistoryArchive.prototype.getEpoch = function(){ return this.epoch; }
HistoryArchive.prototype.setRecords = function(ary){ this.records = ary; }
HistoryArchive.prototype.getRecords = function(){ return this.records; }
HistoryArchive.prototype.addEvent = function(func, args, hist){
	var rec = this.records[this.records.length] = {event:func,incidents:args.slice()};
	if (hist) rec.history = hist;
}
HistoryArchive.prototype.shareWith = function(mc){
	if (!mc.history) mc.history = new HistoryArchive(mc, this.getRecords());
	else mc.history.setRecords(this.getRecords());
}
HistoryArchive.prototype.copyTo = function(mc){
	mc.history = this.copy();
	mc.history.setEpoch(mc);
}
HistoryArchive.prototype.copy = function(){
	var hist = new HistoryArchive(this.epoch);
	var L = this.records.length;
	for (var i=0;i<L;i++){
		hist.records[i] = {
			event: this.records[i].event,
			incidents: this.records[i].incidents.slice()
		}
		if (this.records[i].history) hist.records[i].history = this.records[i].history.copy();
	}
	return hist;
}
HistoryArchive.prototype.claim = function(){
	this.epoch.history = this.copy();
}
HistoryArchive.prototype.clear = function(){
	this.records = [];
}
HistoryArchive.prototype.recall = function(mc){
	if (mc == undefined) mc = this.epoch;
	var mt, L = this.records.length;
	for (var i=0;i<L;i++){
		if (this.records[i].event == "createEmptyMovieClip"){
			mt = mc.createEmptyMovieClip.apply(mc, this.records[i].incidents);
			mt.history = new HistoryArchive(mt, this.records[i].history.getRecords());
			mt.history.recall();
		}else mc[this.records[i].event].apply(mc, this.records[i].incidents);
	}
}
HistoryArchive.prototype.toString = function(depth, name){
	var tabs = "", output = "";
	if (depth){
		tabs = new Array(depth+1).join("\t");
		name = "this."+name;
	}else name = this.epoch._name;
	output += tabs+name+".history.recall = function(){";
	var L = this.records.length;
	for (var i=0;i<L;i++){
		if (this.records[i].event == "createEmptyMovieClip"){
			output += "\n\tthis."+this.records[i].event+"(\""+this.records[i].incidents[0]+"\","+this.records[i].incidents[1]+");";
			if (this.records[i].history.records.length){
				output += "\n"+this.records[i].history.toString(depth+1, this.records[i].incidents[0]);
			}
		}else output += "\n\t"+tabs+"this."+this.records[i].event+"("+this.records[i].incidents+");";
	}
	return output + "\n"+tabs+"}";
}
MovieClip.prototype.duplicateWithHistory = function(name, depth, claim){
	var mc = this.createEmptyMovieClip.call(this._parent, name, depth);
	if (claim) this.history.copyTo(mc);
	else this.history.shareWith(mc);
	mc.history.recall();
}
MovieClip.prototype.empty = function(){
	this.clear();
	for (var p in this) if (this[p] instanceof MovieClip && this[p]._parent == this) this[p].removeMovieClip();
}
L=(meths = ["lineStyle","beginFill","beginGradientFill","endFill","moveTo","lineTo","curveTo"]).length;
while(L--){
	MovieClip.prototype[meths[L]+"h"] = function(){
		if (!this.history) this.history = new HistoryArchive(this);
		this.history.addEvent(arguments.callee.meth,arguments);
		this[arguments.callee.meth].apply(this, arguments);
	}
	MovieClip.prototype[meths[L]+"h"].meth = meths[L];
}
MovieClip.prototype.createEmptyMovieCliph = function(name, depth){
	if (!this.history) this.history = new HistoryArchive(this);
	var mc = this.createEmptyMovieClip(name, depth);
	mc.history = new HistoryArchive(mc);
	this.history.addEvent("createEmptyMovieClip",arguments,mc.history);
	return mc;
}
MovieClip.prototype.clearh = function(){
	this.clear();
	if (!this.history) this.history = new HistoryArchive(this);
	var recs = this.history.records.slice(), L = recs.length;
	this.history.records.length = 0;
	for (var i=0;i<L;i++) if (recs[i].event == "createEmptyMovieClip") this.history.records[this.history.records.length] = recs[i];
}