From 61b309eb0b5fffa5c317d97af6b904cda9914ec8 Mon Sep 17 00:00:00 2001 From: Mykhailo Shchurov Date: Wed, 12 Apr 2017 23:15:31 +0300 Subject: [PATCH] Fixed SampleTextureAtlasPacker ordering Imrpoved burst sample Removed rain sample --- build.gradle | 2 +- particleview/build.gradle | 2 +- .../SimpleTextureAtlasPacker.java | 37 +++- sample/src/main/AndroidManifest.xml | 4 - .../particleview/sample/MainActivity.java | 7 - .../sample/burst/BurstParticle.java | 10 +- .../sample/burst/BurstParticleSystem.java | 27 ++- .../sample/rain/RainActivity.java | 53 ------ .../sample/rain/RainParticle.java | 51 ------ .../sample/rain/RainParticleSystem.java | 167 ------------------ sample/src/main/res/layout/activity_main.xml | 7 - 11 files changed, 70 insertions(+), 297 deletions(-) delete mode 100644 sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainActivity.java delete mode 100644 sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticle.java delete mode 100644 sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticleSystem.java diff --git a/build.gradle b/build.gradle index 32ed3fc..e8fc89b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' // NOTE: Do not place your application dependencies here; they belong diff --git a/particleview/build.gradle b/particleview/build.gradle index 81a0979..cec58f8 100644 --- a/particleview/build.gradle +++ b/particleview/build.gradle @@ -11,7 +11,7 @@ android { minSdkVersion 14 targetSdkVersion 25 versionCode 5 - versionName "0.9.8" + versionName "0.9.9" } buildTypes { release { diff --git a/particleview/src/main/java/com/github/shchurov/particleview/SimpleTextureAtlasPacker.java b/particleview/src/main/java/com/github/shchurov/particleview/SimpleTextureAtlasPacker.java index daab2bb..7998e77 100644 --- a/particleview/src/main/java/com/github/shchurov/particleview/SimpleTextureAtlasPacker.java +++ b/particleview/src/main/java/com/github/shchurov/particleview/SimpleTextureAtlasPacker.java @@ -34,16 +34,17 @@ public TextureAtlas pack(List drawableIds, Resources res, int atlasWidt } public TextureAtlas pack(List bitmaps, int atlasWidth, int atlasHeight) { - TextureAtlas atlas = new TextureAtlas(atlasWidth, atlasHeight); freeRects.add(new Rect(0, 0, atlasWidth, atlasHeight)); List sortedBitmaps = sortBitmaps(bitmaps); Rect out = new Rect(); + List regions = new ArrayList<>(); for (Bitmap bmp : sortedBitmaps) { + int index = bitmaps.indexOf(bmp); boolean rotate = findPositionForBitmap(bmp.getWidth() + 2 * PADDING, bmp.getHeight() + 2 * PADDING, out); if (rotate) { bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), rotationMatrix, false); } - atlas.addRegion(out.left + PADDING, out.top + PADDING, rotate, bmp); + regions.add(new Region(index, out.left + PADDING, out.top + PADDING, rotate, bmp)); for (int i = 0; i < freeRects.size(); i++) { if (splitRect(freeRects.get(i), out)) { freeRects.remove(i--); @@ -52,6 +53,11 @@ public TextureAtlas pack(List bitmaps, int atlasWidth, int atlasHeight) cleanUpFreeRects(); } freeRects.clear(); + TextureAtlas atlas = new TextureAtlas(atlasWidth, atlasHeight); + List sortedRegions = sortRegionsToOriginalOrder(regions); + for (Region r : sortedRegions) { + atlas.addRegion(r.x, r.y, r.cwRotated, r.bitmap); + } return atlas; } @@ -66,6 +72,17 @@ public int compare(Bitmap b1, Bitmap b2) { return sorted; } + private List sortRegionsToOriginalOrder(List regions) { + List sorted = new ArrayList<>(regions); + Collections.sort(sorted, new Comparator() { + @Override + public int compare(Region o1, Region o2) { + return o1.index - o2.index; + } + }); + return sorted; + } + private boolean findPositionForBitmap(int bmpWidth, int bmpHeight, Rect out) { out.setEmpty(); int minShortExtra = Integer.MAX_VALUE; @@ -143,4 +160,20 @@ private void cleanUpFreeRects() { } } + private class Region { + final int index; + final int x; + final int y; + final boolean cwRotated; + final Bitmap bitmap; + + Region(int index, int x, int y, boolean cwRotated, Bitmap bitmap) { + this.index = index; + this.x = x; + this.y = y; + this.cwRotated = cwRotated; + this.bitmap = bitmap; + } + } + } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index d092fcb..e9e6f63 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -24,10 +24,6 @@ android:name=".spinner.SpinnerActivity" android:screenOrientation="portrait"/> - - diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/MainActivity.java b/sample/src/main/java/com/github/shchurov/particleview/sample/MainActivity.java index 41ff1e1..ec82a69 100644 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/MainActivity.java +++ b/sample/src/main/java/com/github/shchurov/particleview/sample/MainActivity.java @@ -8,7 +8,6 @@ import com.github.shchurov.particleview.sample.burst.BurstActivity; import com.github.shchurov.particleview.sample.getting_started.GettingStartedActivity; -import com.github.shchurov.particleview.sample.rain.RainActivity; import com.github.shchurov.particleview.sample.spinner.SpinnerActivity; public class MainActivity extends AppCompatActivity { @@ -35,11 +34,5 @@ public void onClick(View view) { SpinnerActivity.start(MainActivity.this); } }); - findViewById(R.id.btnRain).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - RainActivity.start(MainActivity.this); - } - }); } } diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticle.java b/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticle.java index 3d1b595..2b55bce 100644 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticle.java +++ b/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticle.java @@ -11,8 +11,14 @@ class BurstParticle extends Particle { float vr; double timeLeft; - BurstParticle(float x, float y, int texture, float vx, float vy, float vr, double timeLeft) { - super(SIZE, SIZE, x, y, texture); + BurstParticle() { + super(SIZE, SIZE, 0, 0, 0); + } + + void setup(float x, float y, int textureIndex, float vx, float vy, float vr, double timeLeft) { + setX(x); + setY(y); + setTextureIndex(textureIndex); this.vx = vx; this.vy = vy; this.vr = vr; diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticleSystem.java b/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticleSystem.java index 59a1de3..22c6309 100644 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticleSystem.java +++ b/sample/src/main/java/com/github/shchurov/particleview/sample/burst/BurstParticleSystem.java @@ -6,6 +6,7 @@ import com.github.shchurov.particleview.ParticleSystem; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Random; @@ -26,6 +27,7 @@ class BurstParticleSystem implements ParticleSystem { private List particles = new ArrayList<>(); private Queue originsQueue = new ConcurrentLinkedQueue<>(); private Random random = new Random(); + private ParticlesPool pool = new ParticlesPool(); @Override public int getMaxCount() { @@ -52,6 +54,7 @@ private void updateExistingParticles(double timeDelta) { BurstParticle p = particles.get(i); if ((p.timeLeft -= timeDelta) < 0) { particles.remove(i--); + pool.recycle(p); continue; } p.setX(p.getX() + (float) (p.vx * timeDelta)); @@ -69,10 +72,30 @@ private void pollOrigins() { float vx = (random.nextBoolean() ? 1 : -1) * MAX_VX * random.nextFloat(); float vy = (random.nextBoolean() ? 1 : -1) * MAX_VY * random.nextFloat(); float vr = (random.nextBoolean() ? 1 : -1) * MAX_VR * random.nextFloat(); - particles.add(new BurstParticle(origin.x, origin.y, random.nextInt(TEXTURE_COUNT), vx, vy, vr, - BURST_DURATION)); + BurstParticle p = pool.obtain(origin.x, origin.y, random.nextInt(TEXTURE_COUNT), vx, vy, vr, + BURST_DURATION); + particles.add(p); } } } + private class ParticlesPool { + + Queue pool = new LinkedList<>(); + + BurstParticle obtain(float x, float y, int textureIndex, float vx, float vy, float vr, double timeLeft) { + BurstParticle p = pool.poll(); + if (p == null) { + p = new BurstParticle(); + } + p.setup(x, y, textureIndex, vx, vy, vr, timeLeft); + return p; + } + + void recycle(BurstParticle p) { + pool.add(p); + } + + } + } diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainActivity.java b/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainActivity.java deleted file mode 100644 index b257a33..0000000 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainActivity.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.github.shchurov.particleview.sample.rain; - - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.View; - -import com.github.shchurov.particleview.ParticleView; -import com.github.shchurov.particleview.sample.R; -import com.github.shchurov.particleview.sample.SampleTextureAtlasFactory; - -public class RainActivity extends AppCompatActivity { - - private ParticleView particleView; - - public static void start(Context context) { - Intent i = new Intent(context, RainActivity.class); - context.startActivity(i); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_rain); - particleView = (ParticleView) findViewById(R.id.particleView); - final RainParticleSystem particleSystem = new RainParticleSystem(); - particleView.setTextureAtlasFactory(new SampleTextureAtlasFactory(getResources())); - particleView.setFpsLogEnabled(true); - final View vFloor = findViewById(R.id.vFloor); - vFloor.post(new Runnable() { - @Override - public void run() { - particleSystem.setDimensions(particleView.getWidth(), (int) vFloor.getY()); - particleView.setParticleSystem(particleSystem); - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - particleView.startRendering(); - } - - @Override - protected void onPause() { - super.onPause(); - particleView.stopRendering(); - } - -} diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticle.java b/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticle.java deleted file mode 100644 index 7650a38..0000000 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticle.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.github.shchurov.particleview.sample.rain; - - -import com.github.shchurov.particleview.Particle; - -class RainParticle extends Particle { - - private static final int SIZE_PRIMARY = 24; - private static final int SIZE_SECONDARY = 12; - - float vx; - float vy; - boolean primary; - double timeLeft; - - static RainParticle createPrimary(float x, float y, int textureIndex, float vx, float vy) { - RainParticle p = new RainParticle(); - p.setupAsPrimary(x, y, textureIndex, vx, vy); - return p; - } - - static RainParticle createSecondary(float x, float y, int textureIndex, float vx, float vy, double timeLeft) { - RainParticle p = new RainParticle(); - p.setupAsSecondary(x, y, textureIndex, vx, vy, timeLeft); - return p; - - } - - void setupAsPrimary(float x, float y, int textureIndex, float vx, float vy) { - setup(true, x, y, textureIndex, vx, vy, 0); - } - - private void setup(boolean primary, float x, float y, int textureIndex, float vx, float vy, double timeLeft) { - int size = primary ? SIZE_PRIMARY : SIZE_SECONDARY; - setWidth(size); - setHeight(size); - setX(x); - setY(y); - setTextureIndex(textureIndex); - this.primary = primary; - this.vx = vx; - this.vy = vy; - this.timeLeft = timeLeft; - setAlpha(1f); - } - - void setupAsSecondary(float x, float y, int textureIndex, float vx, float vy, double timeLeft) { - setup(false, x, y, textureIndex, vx, vy, timeLeft); - } - -} diff --git a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticleSystem.java b/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticleSystem.java deleted file mode 100644 index c998f82..0000000 --- a/sample/src/main/java/com/github/shchurov/particleview/sample/rain/RainParticleSystem.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.github.shchurov.particleview.sample.rain; - - -import com.github.shchurov.particleview.Particle; -import com.github.shchurov.particleview.ParticleSystem; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Random; - -import static com.github.shchurov.particleview.sample.SampleTextureAtlasFactory.TEXTURE_COUNT; - -class RainParticleSystem implements ParticleSystem { - - private static final int INTENSITY = 150; - private static final boolean WIND_DIRECTION_LEFT = true; - private static final int G = 600; - private static final int MIN_PRIMARY_VX = 20; - private static final int PRIMARY_VX_RANGE = 60; - private static final int MIN_PRIMARY_VY = 700; - private static final int PRIMARY_VY_RANGE = 150; - private static final int MIN_SECONDARY_VX = 0; - private static final int SECONDARY_VX_RANGE = 150; - private static final int MIN_SECONDARY_VY = 50; - private static final int SECONDARY_VY_RANGE = 500; - private static final double SECONDARY_DURATION = 1.5; - private static final double SECONDARY_FADE_DURATION = 0.3; - private static final int SECONDARY_COUNT = 7; - private static final float MAX_COUNT_RESERVE = 1.05f; - private static final double REVERSED_INTENSITY = 1.0 / INTENSITY; - - private List particles = new ArrayList<>(); - private ParticlesPool pool = new ParticlesPool(); - private Random random = new Random(); - private int minSpawnX; - private int spawnXRange; - private int height; - private int maxCount; - private double extraTime; - - @SuppressWarnings("ConstantConditions") - void setDimensions(int width, int height) { - this.height = height; - int v0 = MIN_PRIMARY_VY; - double primaryDuration = (-v0 + Math.sqrt(Math.pow(v0, 2) + 2 * G * height)) / G; - int maxDx = (int) ((MIN_PRIMARY_VX + PRIMARY_VX_RANGE) * primaryDuration); - minSpawnX = WIND_DIRECTION_LEFT ? 0 : -maxDx; - spawnXRange = width + maxDx; - maxCount = (int) (MAX_COUNT_RESERVE * INTENSITY * (SECONDARY_DURATION * SECONDARY_COUNT + primaryDuration)); - } - - @Override - public int getMaxCount() { - return maxCount; - } - - @Override - public List getParticles() { - return particles; - } - - @Override - public void update(double timeDelta) { - updateExistingParticles(timeDelta); - spawnPrimaryParticles(timeDelta); - } - - private void updateExistingParticles(double timeDelta) { - for (int i = 0; i < particles.size(); i++) { - RainParticle p = particles.get(i); - if (!p.primary) { - p.timeLeft -= timeDelta; - p.setAlpha(Math.min(1f, (float) (p.timeLeft / SECONDARY_FADE_DURATION))); - if (p.timeLeft <= 0) { - particles.remove(i--); - pool.recycle(p); - continue; - } - } - p.setX(p.getX() + (float) (p.vx * timeDelta)); - float dvy = (float) (G * timeDelta); - p.vy += dvy; - float y = p.getY() + (float) ((p.vy - dvy / 2) * timeDelta); - if (y > height) { - if (p.primary) { - spawnSecondaryParticles(p.getX()); - particles.remove(i--); - pool.recycle(p); - } else { - p.setY(height); - p.vx = 0; - } - } else { - p.setY(y); - } - } - } - - private void spawnSecondaryParticles(float x) { - for (int i = 0; i < SECONDARY_COUNT; i++) { - RainParticle p = pool.obtainSecondary( - x, - height, - random.nextInt(TEXTURE_COUNT), - (random.nextBoolean() ? 1 : -1) * (MIN_SECONDARY_VX + nextGaussianInt(SECONDARY_VX_RANGE)), - -MIN_SECONDARY_VY - nextGaussianInt(SECONDARY_VY_RANGE), - SECONDARY_DURATION - ); - particles.add(p); - } - } - - private int nextGaussianInt(int n) { - // using 99.7 rule - double d = Math.max(-3, Math.min(3, random.nextGaussian())); - return (int) ((d + 3) * (n - 1) / 6); - } - - @SuppressWarnings("ConstantConditions") - private void spawnPrimaryParticles(double timeDelta) { - double time = timeDelta + extraTime; - int n = (int) (time / REVERSED_INTENSITY); - extraTime = time % REVERSED_INTENSITY; - for (int i = 0; i < n; i++) { - RainParticle p = pool.obtainPrimary( - minSpawnX + random.nextInt(spawnXRange), - 0, - random.nextInt(TEXTURE_COUNT), - (WIND_DIRECTION_LEFT ? -1 : 1) * (MIN_PRIMARY_VX + random.nextInt(PRIMARY_VX_RANGE)), - MIN_PRIMARY_VY + random.nextInt(PRIMARY_VY_RANGE)); - particles.add(p); - } - } - - private class ParticlesPool { - - Queue pool = new LinkedList<>(); - - RainParticle obtainPrimary(float x, float y, int textureIndex, float vx, float vy) { - RainParticle p = pool.poll(); - if (p == null) { - p = RainParticle.createPrimary(x, y, textureIndex, vx, vy); - } else { - p.setupAsPrimary(x, y, textureIndex, vx, vy); - } - return p; - } - - RainParticle obtainSecondary(float x, float y, int textureIndex, float vx, float vy, double timeLeft) { - RainParticle p = pool.poll(); - if (p == null) { - p = RainParticle.createSecondary(x, y, textureIndex, vx, vy, timeLeft); - } else { - p.setupAsSecondary(x, y, textureIndex, vx, vy, timeLeft); - } - return p; - } - - void recycle(RainParticle p) { - pool.add(p); - } - - } - -} diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index fd5722e..c528ce3 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -38,13 +38,6 @@ android:layout_marginTop="8dp" android:text="Spinner"/> -