BOOM commit birthing animation done and animation factory fleshed out

This commit is contained in:
Peter Cottle 2012-09-29 19:08:13 -07:00
parent bc4b9246eb
commit 23ee6944e2
6 changed files with 106 additions and 20 deletions

View file

@ -1,13 +1,41 @@
/****************** /******************
* This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time. * This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time.
* The tricky thing is that when a new commit has to be "born," say in the middle of a rebase or something, it must animate * The tricky thing is that when a new commit has to be "born," say in the middle of a rebase
* out from the parent position to it's birth position. * or something, it must animate out from the parent position to it's birth position.
* These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree, * These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree,
* store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots. * store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots.
* and then essentially animate the entire tree too. * and then essentially animate the entire tree too.
* not sure if this is necessary yet, so ill hold off for now. lets do some refs
*/ */
// essentially a static class
function AnimationFactory() {
}
AnimationFactory.prototype.genCommitBirthAnimation = function(animationQueue, commit) {
if (!animationQueue) {
throw new Error("Need animation queue to add closure to!");
}
var time = GRAPHICS.defaultAnimationTime * 1.0;
// essentially refresh the entire tree, but do a special thing for the commit
var visNode = commit.get('visNode');
var animation = function() {
// this takes care of refs and all that jazz, and updates all the positions
gitVisuals.refreshTree(time);
visNode.setBirthPosition();
visNode.setOutgoingEdgesBirthPosition();
visNode.parentInFront();
visNode.animateUpdatedPosition(time);
visNode.animateOutgoingEdges(time);
};
animationQueue.add(new Animation({
closure: animation
}));
};

View file

@ -230,7 +230,9 @@ GitEngine.prototype.commitStarter = function() {
if (this.commandOptions['-am']) { if (this.commandOptions['-am']) {
this.command.addWarning("Don't worry about adding files or commit messages in this demo"); this.command.addWarning("Don't worry about adding files or commit messages in this demo");
} }
this.commit();
var newCommit = this.commit();
animationFactory.genCommitBirthAnimation(this.animationQueue, newCommit);
}; };
GitEngine.prototype.commit = function() { GitEngine.prototype.commit = function() {
@ -248,6 +250,7 @@ GitEngine.prototype.commit = function() {
var targetBranch = this.HEAD.get('target'); var targetBranch = this.HEAD.get('target');
targetBranch.set('target', newCommit); targetBranch.set('target', newCommit);
} }
return newCommit;
}; };
GitEngine.prototype.resolveId = function(idOrTarget) { GitEngine.prototype.resolveId = function(idOrTarget) {
@ -750,22 +753,23 @@ GitEngine.prototype.dispatch = function(command, callback) {
} catch (err) { } catch (err) {
if (err instanceof GitError || if (err instanceof GitError ||
err instanceof CommandResult) { err instanceof CommandResult) {
// short circuit animation by just setting error and returning // short circuit animation by just setting error and returning
command.set('error', err); command.set('error', err);
callback(); callback();
return; return;
} else { } else {
throw err; throw err;
} }
} }
this.animationQueue.add(new Animation({ // only add the refresh if we didn't do manual animations
closure: function() { if (!this.animationQueue.get('animations').length) {
gitVisuals.refreshTree(); this.animationQueue.add(new Animation({
} closure: function() {
})); gitVisuals.refreshTree();
}
}));
}
// animation queue will call the callback when its done // animation queue will call the callback when its done
this.animationQueue.start(); this.animationQueue.start();

View file

@ -8,10 +8,13 @@ var gitVisuals = null;
var commandCollection = null; var commandCollection = null;
var commandBuffer = null; var commandBuffer = null;
var animationFactory = null;
var paper = null; var paper = null;
$(document).ready(function(){ $(document).ready(function(){
animationFactory = new AnimationFactory();
// the two major collections that affect everything // the two major collections that affect everything
var commitCollection = new CommitCollection(); var commitCollection = new CommitCollection();
commandCollection = new CommandCollection(); commandCollection = new CommandCollection();

View file

@ -320,6 +320,7 @@ var VisNode = Backbone.Model.extend({
defaults: { defaults: {
depth: undefined, depth: undefined,
maxWidth: null, maxWidth: null,
outgoingEdges: null,
id: null, id: null,
pos: null, pos: null,
radius: null, radius: null,
@ -346,6 +347,8 @@ var VisNode = Backbone.Model.extend({
initialize: function() { initialize: function() {
this.validateAtInit(); this.validateAtInit();
this.set('outgoingEdges', []);
}, },
setDepthBasedOn: function(depthIncrement) { setDepthBasedOn: function(depthIncrement) {
@ -394,7 +397,8 @@ var VisNode = Backbone.Model.extend({
this.get('circle').stop().animate({ this.get('circle').stop().animate({
cx: pos.x, cx: pos.x,
cy: pos.y, cy: pos.y,
opacity: opacity opacity: opacity,
r: this.getRadius()
}, },
speed !== undefined ? speed : this.get('animationSpeed'), speed !== undefined ? speed : this.get('animationSpeed'),
easing || this.get('animationEasing') easing || this.get('animationEasing')
@ -410,6 +414,45 @@ var VisNode = Backbone.Model.extend({
return this.get('radius') || GRAPHICS.nodeRadius; return this.get('radius') || GRAPHICS.nodeRadius;
}, },
getParentScreenCoords: function() {
return this.get('commit').get('parents')[0].get('visNode').getScreenCoords();
},
setBirthPosition: function() {
// utility method for animating it out from underneath a parent
var parentCoords = this.getParentScreenCoords();
this.get('circle').attr({
cx: parentCoords.x,
cy: parentCoords.y,
opacity: 0,
r: 0,
});
},
animateOutgoingEdges: function(speed, easing) {
_.each(this.get('outgoingEdges'), function(edge) {
edge.animateUpdatedPath(speed, easing);
}, this);
},
setOutgoingEdgesBirthPosition: function() {
var parentCoords = this.getParentScreenCoords();
_.each(this.get('outgoingEdges'), function(edge) {
var headPos = edge.get('head').getScreenCoords();
var path = edge.genSmoothBezierPathStringFromCoords(parentCoords, headPos);
edge.get('path').stop().attr({
path: path,
opacity: 0
});
}, this);
},
parentInFront: function() {
// woof!
this.get('commit').get('parents')[0].get('visNode').get('circle').toFront();
},
genGraphics: function(paper) { genGraphics: function(paper) {
var pos = this.getScreenCoords(); var pos = this.getScreenCoords();
var circle = cuteSmallCircle(paper, pos.x, pos.y, { var circle = cuteSmallCircle(paper, pos.x, pos.y, {
@ -438,11 +481,17 @@ var VisEdge = Backbone.Model.extend({
initialize: function() { initialize: function() {
this.validateAtInit(); this.validateAtInit();
this.get('tail').get('outgoingEdges').push(this);
}, },
genSmoothBezierPathString: function(tail, head) { genSmoothBezierPathString: function(tail, head) {
var tailPos = tail.getScreenCoords(); var tailPos = tail.getScreenCoords();
var headPos = head.getScreenCoords(); var headPos = head.getScreenCoords();
return this.genSmoothBezierPathStringFromCoords(tailPos, headPos);
},
genSmoothBezierPathStringFromCoords: function(tailPos, headPos) {
// we need to generate the path and control points for the bezier. format // we need to generate the path and control points for the bezier. format
// is M(move abs) C (curve to) (control point 1) (control point 2) (final point) // is M(move abs) C (curve to) (control point 1) (control point 2) (final point)
// the control points have to be __below__ to get the curve starting off straight. // the control points have to be __below__ to get the curve starting off straight.
@ -465,8 +514,8 @@ var VisEdge = Backbone.Model.extend({
}; };
// first offset tail and head by radii // first offset tail and head by radii
tailPos = offset(tailPos, -1, tail.getRadius()); tailPos = offset(tailPos, -1, this.get('tail').getRadius());
headPos = offset(headPos, 1, head.getRadius()); headPos = offset(headPos, 1, this.get('head').getRadius());
var str = ''; var str = '';
// first move to bottom of tail // first move to bottom of tail
@ -514,6 +563,10 @@ var VisEdge = Backbone.Model.extend({
animateUpdatedPath: function(speed, easing) { animateUpdatedPath: function(speed, easing) {
var newPath = this.getBezierCurve(); var newPath = this.getBezierCurve();
this.animateUpdatedPathFromPath(newPath, speed, easing);
},
animateUpdatedPathFromPath: function(newPath, speed, easing) {
var opacity = this.getOpacity(); var opacity = this.getOpacity();
this.get('path').toBack(); this.get('path').toBack();

View file

@ -81,12 +81,12 @@ GitVisuals.prototype.toScreenCoords = function(pos) {
**************************************/ **************************************/
GitVisuals.prototype.refreshTree = function() { GitVisuals.prototype.refreshTree = function(speed) {
// this method can only be called after graphics are rendered // this method can only be called after graphics are rendered
this.calcTreeCoords(); this.calcTreeCoords();
this.calcGraphicsCoords(); this.calcGraphicsCoords();
this.animateAll(); this.animateAll(speed);
}; };
GitVisuals.prototype.refreshTreeHarsh = function() { GitVisuals.prototype.refreshTreeHarsh = function() {

View file

@ -6,13 +6,11 @@ integrate animation into all git commands
animation factory? stuff like: animation factory? stuff like:
-commitBirthAnimation(snapshotBefore, snapshotAfter, commit)
-highlightCommit(50, 'targetColor') // during search -highlightCommit(50, 'targetColor') // during search
-clearHighlightsAllNodes -clearHighlightsAllNodes
ALSO other big things: ALSO other big things:
- Text on commit nodes - Text on commit nodes
- Division in their rings based on how many / what branches they are part of - Division in their rings based on how many / what branches they are part of
- Color on branch edges?? - Color on branch edges??