|
@@ -13,12 +13,47 @@ class CurveEditor extends Component {
|
|
|
var width = 0;
|
|
|
var height = 0;
|
|
|
|
|
|
+ var refreshTimer : haxe.Timer = null;
|
|
|
+
|
|
|
public function new(root, curve : hide.prefab.Curve) {
|
|
|
super(root);
|
|
|
this.curve = curve;
|
|
|
svg = new hide.comp.SVG(root);
|
|
|
- svg.element.resize((e) -> refresh());
|
|
|
- svg.element.addClass("hide-curve-editor");
|
|
|
+ var root = svg.element;
|
|
|
+ root.resize((e) -> refresh());
|
|
|
+ root.addClass("hide-curve-editor");
|
|
|
+ root.mousedown(function(e) {
|
|
|
+ if(e.which == 2) {
|
|
|
+ var lastX = e.clientX;
|
|
|
+ var lastY = e.clientY;
|
|
|
+ root.mousemove(function(e) {
|
|
|
+ var dt = (e.clientX - lastX) / xScale;
|
|
|
+ var dv = (e.clientY - lastY) / yScale;
|
|
|
+ xOffset += dt;
|
|
|
+ yOffset += dv;
|
|
|
+ lastX = e.clientX;
|
|
|
+ lastY = e.clientY;
|
|
|
+ refresh(true);
|
|
|
+ });
|
|
|
+ root.mouseup(function(e) {
|
|
|
+ root.off("mousemove");
|
|
|
+ root.off("mouseup");
|
|
|
+ refresh();
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ });
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ root.on("mousewheel", function(e) {
|
|
|
+ var step = e.originalEvent.wheelDelta > 0 ? 1.0 : -1.0;
|
|
|
+ if(hxd.Key.isDown(hxd.Key.SHIFT))
|
|
|
+ yScale *= Math.pow(1.125, step);
|
|
|
+ else
|
|
|
+ xScale *= Math.pow(1.125, step);
|
|
|
+ refresh();
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
inline function xt(x: Float) return (x + xOffset) * xScale;
|
|
@@ -26,24 +61,23 @@ class CurveEditor extends Component {
|
|
|
inline function ixt(px: Float) return px / xScale - xOffset;
|
|
|
inline function iyt(py: Float) return (py - height/2) / yScale - yOffset;
|
|
|
|
|
|
- public function refresh(?animKey: hide.prefab.Curve.CurveKey) {
|
|
|
+ public function refresh(?anim: Bool = false, ?animKey: hide.prefab.Curve.CurveKey) {
|
|
|
width = Math.round(svg.element.width());
|
|
|
height = Math.round(svg.element.height());
|
|
|
var root = svg.element;
|
|
|
svg.clear();
|
|
|
- if(animKey == null) {
|
|
|
- untyped window.gc();
|
|
|
+ if(!anim && animKey == null) {
|
|
|
+ if(refreshTimer != null) {
|
|
|
+ refreshTimer.stop();
|
|
|
+ }
|
|
|
+ refreshTimer = haxe.Timer.delay(function() {
|
|
|
+ refreshTimer = null;
|
|
|
+ untyped window.gc();
|
|
|
+ }, 100);
|
|
|
}
|
|
|
|
|
|
- var graph = svg.group(root, "graph"); //, {transform: 'translate(0, ${height/2})'});
|
|
|
+ var graph = svg.group(root, "graph");
|
|
|
var background = svg.group(graph, "background");
|
|
|
- // svg.line(background, 0, 0, width, 0).addClass("axis");
|
|
|
-
|
|
|
- // var gridSteps = Math.ceil(curve.duration);
|
|
|
- // var hgrid = svg.group(root, "hgrid");
|
|
|
- // for(i in 0...gridSteps) {
|
|
|
- // svg.line(hgrid, xt(i), 0, xt(i), height);
|
|
|
- // }
|
|
|
|
|
|
var minX = Math.floor(ixt(0));
|
|
|
var maxX = Math.ceil(ixt(width));
|
|
@@ -86,80 +120,70 @@ class CurveEditor extends Component {
|
|
|
}
|
|
|
|
|
|
for(key in curve.keys) {
|
|
|
- if(animKey != null && key != animKey)
|
|
|
+ if(anim && (animKey == null || key != animKey))
|
|
|
continue;
|
|
|
var kx = xt(key.time);
|
|
|
var ky = yt(key.value);
|
|
|
- function addHandle(handle) {
|
|
|
+ var keyHandle = addRect(kx, ky);
|
|
|
+ if(anim || animKey == null) {
|
|
|
+ keyHandle.mousedown(function(e) {
|
|
|
+ if(e.which != 1) return;
|
|
|
+ var offx = e.clientX - keyHandle.offset().left;
|
|
|
+ var offy = e.clientY - keyHandle.offset().top;
|
|
|
+ var offset = svg.element.offset();
|
|
|
+ root.mousemove(function(e) {
|
|
|
+ var lx = e.clientX - offset.left - offx;
|
|
|
+ var ly = e.clientY - offset.top - offy;
|
|
|
+ var nkx = ixt(lx);
|
|
|
+ var nky = iyt(ly);
|
|
|
+ key.time = nkx;
|
|
|
+ key.value = nky;
|
|
|
+ refresh(true, key);
|
|
|
+ });
|
|
|
+ root.mouseup(function(e) {
|
|
|
+ root.off("mousemove");
|
|
|
+ root.off("mouseup");
|
|
|
+ refresh();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ function addHandle(handle: hide.prefab.Curve.CurveHandle) {
|
|
|
if(handle == null) return null;
|
|
|
var px = xt(key.time + handle.dt);
|
|
|
var py = yt(key.value + handle.dv);
|
|
|
svg.line(vectorsGroup, kx, ky, px, py);
|
|
|
var circle = svg.circle(handlesGroup, px, py, size/2);
|
|
|
+ if(anim || animKey == null) {
|
|
|
+ circle.mousedown(function(e) {
|
|
|
+ if(e.which != 1) return;
|
|
|
+ var offx = e.clientX - circle.offset().left;
|
|
|
+ var offy = e.clientY - circle.offset().top;
|
|
|
+ var offset = svg.element.offset();
|
|
|
+ var other = handle == key.prevHandle ? key.nextHandle : key.prevHandle;
|
|
|
+ var otherLen = hxd.Math.distance(other.dt * xScale, other.dv * yScale);
|
|
|
+ root.mousemove(function(e) {
|
|
|
+ var lx = e.clientX - offset.left - offx;
|
|
|
+ var ly = e.clientY - offset.top - offy;
|
|
|
+ var ndt = ixt(lx) - key.time;
|
|
|
+ var ndv = iyt(ly) - key.value;
|
|
|
+ handle.dt = ndt;
|
|
|
+ handle.dv = ndv;
|
|
|
+ var angle = Math.atan2(ly - ky, lx - kx);
|
|
|
+ other.dt = Math.cos(angle + Math.PI) * otherLen / xScale;
|
|
|
+ other.dv = Math.sin(angle + Math.PI) * otherLen / yScale;
|
|
|
+ refresh(true, key);
|
|
|
+ });
|
|
|
+ root.mouseup(function(e) {
|
|
|
+ root.off("mousemove");
|
|
|
+ root.off("mouseup");
|
|
|
+ refresh();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
return circle;
|
|
|
}
|
|
|
var pHandle = addHandle(key.prevHandle);
|
|
|
var nHandle = addHandle(key.nextHandle);
|
|
|
- var keyHandle = addRect(kx, ky);
|
|
|
-
|
|
|
- if(animKey != null)
|
|
|
- continue;
|
|
|
- keyHandle.mousedown(function(e) {
|
|
|
- var startT = key.time;
|
|
|
- var startV = key.value;
|
|
|
- var offx = e.clientX - keyHandle.offset().left;
|
|
|
- var offy = e.clientY - keyHandle.offset().top;
|
|
|
- var offset = svg.element.offset();
|
|
|
- root.mousemove(function(e) {
|
|
|
- var lx = e.clientX - offset.left - offx;
|
|
|
- var ly = e.clientY - offset.top - offy;
|
|
|
- var nkx = ixt(lx);
|
|
|
- var nky = iyt(ly);
|
|
|
- key.time = nkx;
|
|
|
- key.value = nky;
|
|
|
- refresh(key);
|
|
|
- // keyHandle.attr({
|
|
|
- // x: lx,
|
|
|
- // y: ly});
|
|
|
- // pHandle.attr({
|
|
|
- // cx: xt(nkx + key.prevHandle.dt),
|
|
|
- // cy: yt(nky + key.prevHandle.dv)});
|
|
|
- // nHandle.attr({
|
|
|
- // cx: xt(nkx + key.nextHandle.dt),
|
|
|
- // cy: yt(nky + key.nextHandle.dv)});
|
|
|
- });
|
|
|
- root.mouseup(function(e) {
|
|
|
- root.off("mousemove");
|
|
|
- root.off("mouseup");
|
|
|
- refresh();
|
|
|
- });
|
|
|
- });
|
|
|
- pHandle.mousedown(function(e) {
|
|
|
- var startT = key.prevHandle.dt;
|
|
|
- var startV = key.prevHandle.dv;
|
|
|
- var offx = e.clientX - pHandle.offset().left;
|
|
|
- var offy = e.clientY - pHandle.offset().top;
|
|
|
- var offset = svg.element.offset();
|
|
|
- var nhLen = hxd.Math.distance(key.nextHandle.dt * xScale, key.nextHandle.dv * yScale);
|
|
|
- var phLen = hxd.Math.distance(key.prevHandle.dt * xScale, key.prevHandle.dv * yScale);
|
|
|
- root.mousemove(function(e) {
|
|
|
- var lx = e.clientX - offset.left - offx;
|
|
|
- var ly = e.clientY - offset.top - offy;
|
|
|
- var ndt = ixt(lx) - key.time;
|
|
|
- var ndv = iyt(ly) - key.value;
|
|
|
- key.prevHandle.dt = ndt;
|
|
|
- key.prevHandle.dv = ndv;
|
|
|
- var angle = Math.atan2(ly - ky, lx - kx);
|
|
|
- key.nextHandle.dt = Math.cos(angle + Math.PI) * nhLen / xScale;
|
|
|
- key.nextHandle.dv = Math.sin(angle + Math.PI) * nhLen / yScale;
|
|
|
- refresh(key);
|
|
|
- });
|
|
|
- root.mouseup(function(e) {
|
|
|
- root.off("mousemove");
|
|
|
- root.off("mouseup");
|
|
|
- refresh();
|
|
|
- });
|
|
|
- });
|
|
|
}
|
|
|
}
|
|
|
}
|