1

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

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

不幸的是,我看不到任何找到这些信息的方法。我所掌握的有关元素的任何信息似乎都没有暗示发生了任何类型的翻转。如何检测翻转?如果不能通过算法完成,我会接受动画师必须手动指示符号已被翻转(通过创建某种插件,为他们提供一个复选框,该复选框使用 setPersistentData( ),例如),但我也不知道如何制作那种插件。帮助!

4

3 回答 3

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。

于 2011-10-07T11:05:31.037 回答
0

scaleX 或矩阵不起作用吗?http://help.adobe.com/en_US/flash/cs/extend/WS5b3ccc516d4fbf351e63e3d118a9024f3f-7f6c.html

于 2011-10-03T12:31:43.203 回答
0

这是 Electrodruid 的解决方案,包含几个便利功能:

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));

感谢您的代码电德鲁伊。

于 2017-02-02T20:08:30.630 回答