JSFL:检测元素何时被翻转

时间:2011-10-03 12:20:35

标签: flash flip jsfl

我正在JSFL中编写导出器,将Flash动画导出为可在自定义播放器中重放的格式。导出器基本上遍历时间轴并遍历每个关键帧的所有元素,并写出元素的名称,位置,旋转,缩放和局部偏移。这些被读入自定义播放器,该播放器将数据提供给精灵引擎以重新创建动画的每个帧。

我想要做的是检测给定的元素是否已被翻转(即在Flash中选择元素(符号),然后修改 - >转换 - >翻转水平)以便导出器可以包含该信息,允许播放器中的精灵引擎翻转纹理的UV以复制Flash中发生的事情。这对于(比如)对一个角色的右手使用一个符号,并将其翻转为左手,而不是必须创建一个全新的符号是有用的。

不幸的是,我看不出有任何方法可以找到这些信息。我可用于元素的信息似乎都没有暗示任何类型的翻转已经发生。如何检测翻转?如果它不能通过算法完成,我会让动画师不得不手动指示一个符号被翻转(通过创建某种插件给他们一个勾选框,用setPersistentData将值写入Element中) ),例如),但我不知道如何制作这种插件。救命啊!

3 个答案:

答案 0 :(得分:3)

scaleX不起作用,似乎总是给出正值。最后,我必须对矩阵进行此操作以获得答案。这是基于我们知道矩阵总是包含2D旋转的想法,并且我们知道角度,因此我们可以摆脱矩阵元素的旋转,只留下比例。这太可怕但它似乎有效。

此外,旋转有时会以NaN形式出现,特别是在元素翻转时。使用skewX的值似乎适用于你知道没有偏斜的东西,但我希望我的导出器能够处理偏斜的元素,所以我认为这可能是另一个问题的基础。

var rotationRadians;
if(isNaN(someElement.rotation)) {
    rotationRadians = someElement.skewX * Math.PI / 180;
}
else {
    rotationRadians = someElement.rotation * Math.PI / 180;
}   

var sinRot = Math.sin(rotationRadians);
var cosRot = Math.cos(rotationRadians);
var SOME_EPSILON = 0.01;
var flipScaleX, flipScaleY;

if(Math.abs(cosRot) <  SOME_EPSILON) {
    // Avoid divide by zero. We can use sine and the other two elements of the matrix instead.
    flipScaleX = (someElement.matrix.b / sinRot);
    flipScaleY = (someElement.matrix.c / -sinRot);
}
else {
    flipScaleX = someElement.matrix.a / cosRot;
    flipScaleY = someElement.matrix.d / cosRot;
}

如果水平翻转,flipScaleX会出现在〜-1,否则会出现~1。如果它垂直翻转,则flipScaleY为〜-1,否则为~1。

答案 1 :(得分:0)

答案 2 :(得分:0)

这里的电驱动解决方案包装在几个便利功能中:

function isFlippedHorizontally (element) {
  return Math.round(getFlip(element)[0]) == -1;
}

function isFlippedVertically (element) {
  return Math.round(getFlip(element)[0]) == -1;
}

function getFlip (element) {
  var rotationRadians;
  if(isNaN(element.rotation)) {
    rotationRadians = element.skewX * Math.PI / 180;
  }
  else {
    rotationRadians = element.rotation * Math.PI / 180;
  }

  var sinRot = Math.sin(rotationRadians);
  var cosRot = Math.cos(rotationRadians);
  var SOME_EPSILON = 0.01;
  var flipScaleX, flipScaleY;

  if(Math.abs(cosRot) <  SOME_EPSILON) {
    // Avoid divide by zero. We can use sine and the other two elements of the matrix instead.
    flipScaleX = (element.matrix.b / sinRot);
    flipScaleY = (element.matrix.c / -sinRot);
  }
  else {
    flipScaleX = element.matrix.a / cosRot;
    flipScaleY = element.matrix.d / cosRot;
  }
  return [flipScaleX, flipScaleY];
}

用法示例:

var element = currentDoc.getTimeline().layers[0].frames[0].elements[0];
trace("Element is flipped:" + isFlippedHorizontally(element));

感谢代码electrodruid。