mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-07 12:25:09 +00:00
Addedd #2138 Morphshapes - detect classic easing
This commit is contained in:
144
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/Easing.java
Normal file
144
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/Easing.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -2463,7 +2463,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertFrame(Scene scene, boolean shapeTween, SoundStreamFrameRange soundStreamRange, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||
private static void convertFrame(Scene scene, boolean shapeTween, SoundStreamFrameRange soundStreamRange, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer, Integer acceleration) throws XMLStreamException {
|
||||
DefineSoundTag sound = null;
|
||||
if (startSound != null) {
|
||||
SWF swf = startSound.getSwf();
|
||||
@@ -2478,6 +2478,9 @@ public class XFLConverter {
|
||||
if (shapeTween) {
|
||||
writer.writeAttribute("tweenType", "shape");
|
||||
writer.writeAttribute("keyMode", KEY_MODE_SHAPE_TWEEN);
|
||||
if (acceleration != null) {
|
||||
writer.writeAttribute("acceleration", acceleration);
|
||||
}
|
||||
} else {
|
||||
writer.writeAttribute("keyMode", KEY_MODE_NORMAL);
|
||||
}
|
||||
@@ -2567,6 +2570,7 @@ public class XFLConverter {
|
||||
int ratio = -1;
|
||||
boolean shapeTween = false;
|
||||
MorphShapeTag shapeTweener = null;
|
||||
List<Integer> morphShapeRatios = new ArrayList<>();
|
||||
int lastTweenRatio = -1;
|
||||
|
||||
//Add ShowFrameTag to the end when there is one last missing
|
||||
@@ -2711,15 +2715,20 @@ public class XFLConverter {
|
||||
MorphShapeTag m = shapeTweener;
|
||||
XFLXmlWriter addLastWriter = new XFLXmlWriter();
|
||||
SHAPEWITHSTYLE endShape = m.getShapeAtRatio(65535); //lastTweenRatio);
|
||||
convertShape(swf, characters, matrix, m.getShapeNum() == 1 ? 3 : 4, endShape.shapeRecords, m.getFillStyles().getFillStylesAt(lastTweenRatio), m.getLineStyles().getLineStylesAt(m.getShapeNum(), lastTweenRatio), true, false, addLastWriter);
|
||||
//duration--;
|
||||
convertFrame(scene, true, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||
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 acceleration = null;
|
||||
if (ease != null) {
|
||||
acceleration = -ease;
|
||||
}
|
||||
convertFrame(scene, true, null, null, frame - duration, duration, "", lastElements, files, writer2, acceleration);
|
||||
duration = 1;
|
||||
lastElements = addLastWriter.toString();
|
||||
lastCharacter = m;
|
||||
lastMatrix = matrix;
|
||||
shapeTweener = null;
|
||||
shapeTweenNow = true;
|
||||
morphShapeRatios.clear();
|
||||
}
|
||||
if (!shapeTweenNow) {
|
||||
if (character instanceof ShapeTag && standaloneShapeTweener != null) {
|
||||
@@ -2747,7 +2756,8 @@ public class XFLConverter {
|
||||
standaloneShapeTweener = m;
|
||||
standaloneShapeTweenerMatrix = matrix;
|
||||
convertSymbolInstance(instanceName, matrix, colorTransForm, cacheAsBitmap, blendMode, filters, isVisible, backGroundColor, clipActions, metadata, character, characters, tags, flaVersion, elementsWriter);
|
||||
} else {
|
||||
} else {
|
||||
morphShapeRatios.add(ratio == -1 ? 0 : ratio);
|
||||
if (lastCharacter == m && Objects.equals(matrix, lastMatrix)) {
|
||||
elementsWriter.writeCharactersRaw(lastElements);
|
||||
} else {
|
||||
@@ -2781,7 +2791,7 @@ public class XFLConverter {
|
||||
frame++;
|
||||
String elements = elementsWriter.toString();
|
||||
if (!elements.equals(lastElements) && frame > 0) {
|
||||
convertFrame(scene, false, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||
convertFrame(scene, false, null, null, frame - duration, duration, "", lastElements, files, writer2, null);
|
||||
duration = 1;
|
||||
} else if (frame == 0) {
|
||||
duration = 1;
|
||||
@@ -2819,7 +2829,7 @@ public class XFLConverter {
|
||||
}
|
||||
if (!lastElements.isEmpty() || writer2.length() > 0) {
|
||||
frame++;
|
||||
convertFrame(scene, false, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2);
|
||||
convertFrame(scene, false, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2, null);
|
||||
}
|
||||
afterStr = "</frames>" + afterStr;
|
||||
|
||||
@@ -3236,10 +3246,10 @@ public class XFLConverter {
|
||||
|
||||
if (startFrame != 0) {
|
||||
// empty frames should be added
|
||||
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer);
|
||||
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer, null);
|
||||
}
|
||||
|
||||
convertFrame(scene, false, soundStreamRanges.get(i), null, startFrame, duration, "", "", files, writer);
|
||||
convertFrame(scene, false, soundStreamRanges.get(i), null, startFrame, duration, "", "", files, writer, null);
|
||||
|
||||
writer.writeEndElement();
|
||||
writer.writeEndElement();
|
||||
@@ -3254,10 +3264,10 @@ public class XFLConverter {
|
||||
|
||||
if (startFrame != 0) {
|
||||
// empty frames should be added
|
||||
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer);
|
||||
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer, null);
|
||||
}
|
||||
|
||||
convertFrame(scene, false, null, startSounds.get(i), startFrame, duration, "", "", files, writer);
|
||||
convertFrame(scene, false, null, startSounds.get(i), startFrame, duration, "", "", files, writer, null);
|
||||
|
||||
writer.writeEndElement();
|
||||
writer.writeEndElement();
|
||||
|
||||
Reference in New Issue
Block a user