Refactoring of Easing detector

This commit is contained in:
Jindra Petřík
2023-12-09 22:25:39 +01:00
parent 4480af4edd
commit 1e1d30935f
4 changed files with 83 additions and 148 deletions

View File

@@ -1,144 +0,0 @@
/*
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.xfl;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.math.BezierEdge;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*
* @author JPEXS
*/
public class Easing extends JFrame {
public Easing() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 800);
setContentPane(new JPanel(){
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int ease = 100;
//290
GeneralPath gp = new GeneralPath();
gp.moveTo(0, 290);
g.setColor(Color.RED);
for (int i = 0; i <= 100; i++) {
double ptSize = 290 / 100.0;
double pct = framePercentToRatio(i, ease);
//System.out.println("pct="+pct);
/*g.drawLine((int)Math.round(i*ptSize), 290-(int)Math.round(pct*ptSize),
(int)Math.round(i*ptSize), 290-(int)Math.round(pct*ptSize)); */
gp.lineTo(i*ptSize, 290-pct*ptSize);
}
Graphics2D g2d = (Graphics2D)g;
g2d.draw(gp);
g.setColor(Color.black);
g.drawRect(0, 0, 290, 290);
}
});
}
public static double framePercentToRatio(double framePercent, int ease) {
BezierEdge be = new BezierEdge(0,0,50,65535 / 2 + ease * 65535 / 100 / 2, 100,65535);
BezierEdge line = new BezierEdge(framePercent, 0, framePercent, 65535);
return be.getIntersections(line).get(0).getY();
}
public static double ratioToFramePercent(double ratio, int ease) {
BezierEdge be = new BezierEdge(0,0,50,50 + ease / 2.0, 100,65535);
BezierEdge line = new BezierEdge(0, ratio, 100, ratio);
return be.getIntersections(line).get(0).getX();
}
public static Integer getEaseFromShapeRatios(List<Integer> ratios) {
if (ratios.isEmpty()) {
return null;
}
if (ratios.get(0) != 0) {
ratios.add(0, 0);
}
if (ratios.get(ratios.size() - 1) != 65535) {
ratios.add(65535);
}
int ease = 100;
while(true) {
double minDist = Double.MAX_VALUE;
double maxDist = Double.MIN_VALUE;
for (int f = 0; f < ratios.size(); f++) {
double framePct = f * 100 / (double)(ratios.size() - 1);
double tweenPct = ratios.get(f);
double tweenPctShouldBe = Math.round(framePercentToRatio(framePct, ease));
double dist = tweenPctShouldBe - tweenPct;
if (dist > maxDist) {
maxDist = dist;
}
if (dist < minDist) {
minDist = dist;
}
}
if (minDist > -5 && maxDist < 5) {
break;
}
if (ease == -100) {
return null;
}
ease--;
}
return ease;
}
public static void main(String[] args) throws Exception {
SWF swf = new SWF(new FileInputStream("c:\\flash_testdata\\morphshape_ease\\morphshape_ease.swf"), true, false);
List<Integer> ratios = new ArrayList<>();
for (Tag t : swf.getTags()) {
if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) t;
int ratio = place.getRatio();
if (ratio > -1) {
ratios.add(ratio);
}
}
}
Integer ease = getEaseFromShapeRatios(ratios);
System.err.println("ease = " + ease);
//System.setProperty("sun.java2d.uiScale", "1.0");
//new Easing().setVisible(true);
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.xfl;
import com.jpexs.decompiler.flash.math.BezierEdge;
import java.util.List;
/**
*
* @author JPEXS
*/
public class EasingDetector {
public static double framePercentToRatio(double framePercent, int ease) {
BezierEdge be = new BezierEdge(0, 0, 50, 65535 / 2 + ease * 65535 / 100 / 2, 100, 65535);
BezierEdge line = new BezierEdge(framePercent, 0, framePercent, 65535);
return be.getIntersections(line).get(0).getY();
}
public static double ratioToFramePercent(double ratio, int ease) {
BezierEdge be = new BezierEdge(0, 0, 50, 50 + ease / 2.0, 100, 65535);
BezierEdge line = new BezierEdge(0, ratio, 100, ratio);
return be.getIntersections(line).get(0).getX();
}
public static Integer getEaseFromShapeRatios(List<Integer> ratios) {
if (ratios.isEmpty()) {
return null;
}
if (ratios.get(0) != 0) {
ratios.add(0, 0);
}
if (ratios.get(ratios.size() - 1) != 65535) {
ratios.add(65535);
}
int ease = 100;
while (true) {
double minDist = Double.MAX_VALUE;
double maxDist = Double.MIN_VALUE;
for (int f = 0; f < ratios.size(); f++) {
double framePct = f * 100 / (double) (ratios.size() - 1);
double tweenPct = ratios.get(f);
double tweenPctShouldBe = Math.round(framePercentToRatio(framePct, ease));
double dist = tweenPctShouldBe - tweenPct;
if (dist > maxDist) {
maxDist = dist;
}
if (dist < minDist) {
minDist = dist;
}
}
if (minDist > -5 && maxDist < 5) {
break;
}
if (ease == -100) {
return null;
}
ease--;
}
return ease;
}
}

View File

@@ -2722,7 +2722,7 @@ public class XFLConverter {
convertShape(swf, characters, matrix, m.getShapeNum() == 1 ? 3 : 4, endShape.shapeRecords, m.getFillStyles().getFillStylesAt(65535), m.getLineStyles().getLineStylesAt(m.getShapeNum(), 65535), true, false, addLastWriter);
}
Integer ease = Easing.getEaseFromShapeRatios(morphShapeRatios);
Integer ease = EasingDetector.getEaseFromShapeRatios(morphShapeRatios);
Integer acceleration = null;
if (ease != null) {
acceleration = -ease;

View File

@@ -103,14 +103,14 @@ public class MorphShapeFixer extends ShapeFixer {
boolean doRemove = false;
if (
fillStyles0.get(i1) != 0 && fillStyles1.get(i1) == 0
&& fillStyles1.get(i2) != 0 && fillStyles0.get(i2) == 0
&& fillStyles1.get(i2) != 0 && fillStyles0.get(i2) == 0
) {
fillStyles1.set(i1, fillStyles1.get(i2));
doRemove = true;
} else if (
fillStyles1.get(i1) != 0 && fillStyles0.get(i1) == 0
&& fillStyles0.get(i2) != 0 && fillStyles1.get(i2) == 0
) {
&& fillStyles0.get(i2) != 0 && fillStyles1.get(i2) == 0
) {
fillStyles0.set(i1, fillStyles0.get(i2));
doRemove = true;
}