Merge origin/master

This commit is contained in:
honfika@gmail.com
2014-09-07 20:31:42 +02:00
9 changed files with 501 additions and 12 deletions

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.commonshape;
import com.jpexs.decompiler.flash.types.MATRIX;
@@ -101,6 +102,22 @@ public class Matrix {
public Point transform(Point point) {
return transform(point.x, point.y);
}
public Point deltaTransform(double x, double y){
Point result = new Point(
scaleX * x + rotateSkew1 * y,
rotateSkew0 * x + scaleY * y);
return result;
}
public Point deltaTransform(Point point) {
return deltaTransform(point.x, point.y);
}
public java.awt.Point deltaTransform(java.awt.Point point) {
Point p = deltaTransform(point.x, point.y);
return new java.awt.Point((int) p.x, (int) p.y);
}
public java.awt.Point transform(java.awt.Point point) {
Point p = transform(point.x, point.y);
@@ -228,4 +245,48 @@ public class Matrix {
public String toString() {
return "[Matrix scale:" + scaleX + "," + scaleY + ", rotate:" + rotateSkew0 + "," + rotateSkew1 + ", translate:" + translateX + "," + translateY + "]";
}
public Matrix inverse(Matrix m){
double a=m.scaleX;
double b=m.rotateSkew0;
double c=m.rotateSkew1;
double d=m.scaleY;
double tx=m.translateX;
double ty=m.translateY;
double a2=d/(a*d-b*c);
double b2=-b/(a*d-b*c);
double c2=-c/(a*d-b*c);
double d2=a*(a*d-b*c);
double tx2=(c*ty-d*tx)/(a*d-b*c);
double ty2=-(a*ty-b*tx)/(a*d-b*c);
Matrix ret=new Matrix();
ret.scaleX = a2;
ret.rotateSkew0 = b2;
ret.rotateSkew1 = c2;
ret.scaleY = d2;
ret.translateX = tx2;
ret.translateY = ty2;
return ret;
}
public double getTotalSkewAngleX(){
Point px = deltaTransform(new Point(0,1));
return ((180/Math.PI) * Math.atan2(px.y, px.x) - 90);
}
public double getTotalSkewAngleY(){
Point py = deltaTransform(new Point(1,0));
return ((180/Math.PI) * Math.atan2(py.y, py.x));
}
public double getTotalScaleX(){
return Math.sqrt(scaleX * scaleX + rotateSkew0 * rotateSkew0);
}
public double getTotalScaleY(){
return Math.sqrt(rotateSkew1 * rotateSkew1 + scaleY * scaleY);
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
@@ -48,6 +49,7 @@ public class DepthState {
private final SWF swf;
public Frame frame;
public long instanceId;
public boolean motionTween = false;
private static AtomicLong lastInstanceId = new AtomicLong(0);

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
@@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
@@ -39,7 +41,9 @@ import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
@@ -55,6 +59,7 @@ public class Timeline {
public RECT displayRect;
public int frameRate;
public List<Tag> tags;
public Map<Integer,Integer> depthMaxFrame= new HashMap<Integer, Integer>();
public int getMaxDepth() {
int max_depth = 0;
@@ -186,6 +191,51 @@ public class Timeline {
if (tagAdded) {
frames.add(frame);
}
detectTweens();
for(int d=1;d<=getMaxDepth();d++){
for(int f=frames.size()-1;f>=0;f--){
if(frames.get(f).layers.get(d) != null){
depthMaxFrame.put(d, f+1);
break;
}
}
}
}
private boolean compare(int a, int b, int c, int tolerance) {
return Math.abs((b - a) - (c - b))<tolerance;
}
private void detectTweens() {
for (int d = 1; d <= getMaxDepth(); d++) {
int characterId = -1;
int len = 0;
for (int f = 0; f <= frames.size(); f++) {
DepthState ds = f>=frames.size()?null:frames.get(f).layers.get(d);
if(f<frames.size() && ds!=null && ds.characterId == characterId && ds.characterId!=-1){
len++;
}else{
if(characterId!=-1){
List<MATRIX> matrices=new ArrayList<>();
for(int k=0;k<len;k++){
matrices.add(frames.get(f-len+k).layers.get(d).matrix);
}
List<TweenRange> ranges=TweenDetector.detectRanges(matrices);
for(TweenRange r:ranges){
System.out.println(""+r);
for(int t = r.startPosition;t<=r.endPosition;t++){
frames.get(f-len+t).layers.get(d).motionTween = true;
frames.get(f-len+t).layers.get(d).key = false;
}
frames.get(r.startPosition).layers.get(d).key = true;
}
}
len = 1;
}
characterId = ds==null?-1:ds.characterId;
}
}
}
public void getNeededCharacters(Set<Integer> usedCharacters) {

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.types.MATRIX;
import java.util.ArrayList;
import java.util.List;
/**
*
* NOT WORKING STUB!!! FIXME
*
* @author JPEXS
*/
public class TweenDetector {
public static List<TweenRange> detectRanges(List<MATRIX> matrices) {
//TODO: make this working :-(
return new ArrayList<>();
/*
List<TweenRange> ret = new ArrayList<>();
double tolerance = 1;
int min = 3;
int startpos = 0;
Double last = null;
int i = min;
List<Double> translateX=new ArrayList<>();
List<Double> translateY=new ArrayList<>();
List<Double> scaleX=new ArrayList<>();
List<Double> scaleY=new ArrayList<>();
List<Double> rotateSkew0=new ArrayList<>();
List<Double> rotateSkew1=new ArrayList<>();
Set<MATRIX> ms=new HashSet<MATRIX>();
ms.addAll(matrices);
if(ms.size()==1){
return new ArrayList<>();
}
for(MATRIX n:matrices){
//...
}
for (; startpos + i <= matrices.size() + 1; i++) {
double errTranslateX = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(translateX, startpos, i);
double errTranslateY = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(translateY, startpos, i);
double errScaleX = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(scaleX, startpos, i);
double errScaleY = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(scaleY, startpos, i);
double errRotateSkew0 = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(rotateSkew0, startpos, i);
double errRotateSkew1 = startpos + i > matrices.size() ? Double.MAX_VALUE : getErrorLevel(rotateSkew1, startpos, i);
double err = startpos + i > matrices.size()?Double.MAX_VALUE:(errTranslateX/20+errTranslateY/20+0.1*errScaleX+0.1*errScaleY+errRotateSkew0/360+errRotateSkew1/360);
if (err > tolerance) {
if (last == null) {
startpos++;
i = min - 1;
continue;
}
ret.add(new TweenRange(startpos, startpos+i-1-1));
startpos = startpos + i -1;
i = min - 1;
last = null;
continue;
}
last = err;
}
return ret;*/
}
private static double getErrorLevel(List<Double> yValues, int start, int len) {
double[] ret = calc(yValues, start, len);
double a = ret[0];
double b = ret[1];
double sumdelta = 0;
double maxdelta = 0;
for (int i = start; i < start + len; i++) {
double yorig = yValues.get(i);
double ynew = a + b * (i - start);
double ydelta = Math.abs(ynew - yorig);
sumdelta += ydelta;
if(ydelta>maxdelta){
maxdelta = ydelta;
}
}
return maxdelta; //sumdelta / len;
}
private static double[] calc(List<Double> yValues, int start, int len) {
List<Double> xValues = new ArrayList<>();
for (int i = 0; i < len; i++) {
xValues.add((double)i);
}
yValues = yValues.subList(start, start + len);
// get the value of the gradient using the formula b = cov[x,y] / var[x]
double b = covariance(xValues, yValues) / variance(xValues);
// get the value of the y-intercept using the formula a = ybar + b * xbar
double a = mean(yValues) - b * mean(xValues);
return new double[]{a, b};
}
/*
* Calculate the covariance of two sets of data
*
* @param x
* The first set of data
* @param y
* The second set of data
* @return The covariance of x and y
*/
private static double covariance(List<Double> x, List<Double> y) {
double xmean = mean(x);
double ymean = mean(y);
double result = 0;
for (int i = 0; i < x.size(); i++) {
result += (x.get(i) - xmean) * (y.get(i) - ymean);
}
result /= x.size() - 1;
return result;
}
/**
* Calculate the mean of a data set
*
* @param data The data set to calculate the mean of
* @return The mean of the data set
*/
private static double mean(List<Double> data) {
double sum = 0;
for (int i = 0; i < data.size(); i++) {
sum += data.get(i);
}
return sum / data.size();
}
/**
* Calculate the variance of a data set
*
* @param data The data set to calculate the variance of
* @return The variance of the data set
*/
private static double variance(List<Double> data) {
// Get the mean of the data set
double mean = mean(data);
double sumOfSquaredDeviations = 0;
// Loop through the data set
for (int i = 0; i < data.size(); i++) {
// sum the difference between the data element and the mean squared
sumOfSquaredDeviations += Math.pow(data.get(i) - mean, 2);
}
// Divide the sum by the length of the data set - 1 to get our result
return sumOfSquaredDeviations / (data.size() - 1);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.timeline;
/**
*
* @author JPEXS
*/
public class TweenRange {
public int startPosition;
public int endPosition;
public TweenRange(int startPosition, int endPosition) {
this.startPosition = startPosition;
this.endPosition = endPosition;
}
@Override
public String toString() {
return "["+startPosition+"-"+endPosition+"]";
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.types.annotations.Calculated;
@@ -177,4 +178,49 @@ public class MATRIX implements Serializable {
public boolean isEmpty() {
return (translateX == 0) && (translateY == 0) && (!hasRotate) && (!hasScale);
}
@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + this.getScaleX();
hash = 37 * hash + this.getScaleY();
hash = 37 * hash + this.getRotateSkew0();
hash = 37 * hash + this.getRotateSkew1();
hash = 37 * hash + this.translateX;
hash = 37 * hash + this.translateY;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MATRIX other = (MATRIX) obj;
if (this.getScaleX() != other.getScaleX()) {
return false;
}
if (this.getScaleY() != other.getScaleY()) {
return false;
}
if (this.getRotateSkew0() != other.getRotateSkew0()) {
return false;
}
if (this.getRotateSkew1() != other.getRotateSkew1()) {
return false;
}
if (this.translateX != other.translateX) {
return false;
}
if (this.translateY != other.translateY) {
return false;
}
return true;
}
}