OSDN Git Service

[added] TWL Layout method to eat events.
authornathan.sweet <nathan.sweet@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Mon, 27 Dec 2010 11:52:36 +0000 (11:52 +0000)
committernathan.sweet <nathan.sweet@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Mon, 27 Dec 2010 11:52:36 +0000 (11:52 +0000)
[added] Ability to set max size on Bag and Array pools.
[removed] Pool. Replaced all Pool usage with BagPool (which doesn't do a memory copy when items are returned to the pool as Pool's use of ArrayList did).
[changed] TextureAtlas, renamed methods to findRegion and createSprite to better reflect the operation cost.
[removed] IntHashMap and LongHashMap.
[added] ObjectMap, IdentityMap, IntMap, and LongMap. These use open addressing with linear probing to avoid allocation of entry nodes on put. See JGO thread for performance. Changes HashMap usage to ObjectMap.
[removed] LocklessThreadQueue. Replaced by AtomicQueue.

44 files changed:
backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java
backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidMultiTouchHandler.java
backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidSingleTouchHandler.java
backends/gdx-backend-jogl/src/com/badlogic/gdx/backends/jogl/JoglInput.java
backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglInput.java
backends/gdx-backends-angle/src/com/badlogic/gdx/backends/angle/AngleInput.java
demos/rtm/src/com/badlogic/rtm/LevelRenderer.java
extensions/twl/gdx-twl/src/com/badlogic/gdx/twl/Layout.java
extensions/twl/gdx-twl/src/com/badlogic/gdx/twl/renderer/GdxCacheContext.java
gdx/src/com/badlogic/gdx/graphics/TextureAtlas.java
gdx/src/com/badlogic/gdx/graphics/glutils/ShaderProgram.java
gdx/src/com/badlogic/gdx/graphics/keyframed/KeyframedModel.java
gdx/src/com/badlogic/gdx/graphics/particles/ParticleEffect.java
gdx/src/com/badlogic/gdx/graphics/texturedict/TextureDict.java
gdx/src/com/badlogic/gdx/physics/box2d/World.java
gdx/src/com/badlogic/gdx/scenes/scene2d/Group.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/Delay.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/FadeIn.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/FadeOut.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/FadeTo.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/Forever.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/MoveBy.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/MoveTo.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/Parallel.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/Repeat.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/RotateBy.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/RotateTo.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/ScaleTo.java
gdx/src/com/badlogic/gdx/scenes/scene2d/actions/Sequence.java
gdx/src/com/badlogic/gdx/utils/ArrayPool.java
gdx/src/com/badlogic/gdx/utils/BagPool.java
gdx/src/com/badlogic/gdx/utils/IdentityMap.java [new file with mode: 0644]
gdx/src/com/badlogic/gdx/utils/IntHashMap.java [deleted file]
gdx/src/com/badlogic/gdx/utils/IntMap.java [new file with mode: 0644]
gdx/src/com/badlogic/gdx/utils/LocklessThreadQueue.java [deleted file]
gdx/src/com/badlogic/gdx/utils/LongHashMap.java [deleted file]
gdx/src/com/badlogic/gdx/utils/LongMap.java [new file with mode: 0644]
gdx/src/com/badlogic/gdx/utils/ObjectMap.java [new file with mode: 0644]
gdx/src/com/badlogic/gdx/utils/Pool.java [deleted file]
gdx/src/com/badlogic/gdx/utils/PooledLinkedList.java
gdx/src/com/badlogic/gdx/utils/Sort.java [new file with mode: 0644]
tests/gdx-tests/src/com/badlogic/gdx/tests/AtlasIssueTest.java
tests/gdx-tests/src/com/badlogic/gdx/tests/FilterPerformanceTest.java
tests/gdx-tests/src/com/badlogic/gdx/tests/TextureAtlasTest.java

index 3afe892..5004a1b 100644 (file)
@@ -33,8 +33,7 @@ import android.widget.EditText;
 \r
 import com.badlogic.gdx.Input;\r
 import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 /**\r
  * An implementation of the {@link Input} interface for Android.\r
@@ -66,19 +65,17 @@ public final class AndroidInput implements Input, OnKeyListener, OnTouchListener
                int pointer;\r
        }\r
 \r
-       Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
-               @Override public KeyEvent createObject () {\r
+       BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+               protected KeyEvent newObject () {\r
                        return new KeyEvent();\r
                }\r
-       }, 1000);\r
-\r
-       Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+       };\r
 \r
-               @Override public TouchEvent createObject () {\r
+       BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+               protected TouchEvent newObject () {\r
                        return new TouchEvent();\r
                }\r
-       }, 1000);\r
+       };\r
 \r
        ArrayList<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
        ArrayList<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
@@ -223,7 +220,7 @@ public final class AndroidInput implements Input, OnKeyListener, OnTouchListener
                                        case KeyEvent.KEY_TYPED:\r
                                                processor.keyTyped(e.keyChar);\r
                                        }\r
-                                       freeKeyEvents.free(e);\r
+                                       usedKeyEvents.removeValue(e, true);\r
                                }\r
 \r
                                len = touchEvents.size();\r
@@ -239,19 +236,19 @@ public final class AndroidInput implements Input, OnKeyListener, OnTouchListener
                                        case TouchEvent.TOUCH_DRAGGED:\r
                                                processor.touchDragged(e.x, e.y, e.pointer);\r
                                        }\r
-                                       freeTouchEvents.free(e);\r
+                                       usedTouchEvents.removeValue(e, true);\r
                                }\r
                        } else {\r
                                int len = touchEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
                                        TouchEvent e = touchEvents.get(i);\r
 // Log.d("AndroidInput", "synch touch: " + (System.nanoTime() - e.timeStamp) / 1000000.0f);\r
-                                       freeTouchEvents.free(e);\r
+                                       usedTouchEvents.removeValue(e, true);\r
                                }\r
 \r
                                len = keyEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeKeyEvents.free(keyEvents.get(i));\r
+                                       usedKeyEvents.removeValue(keyEvents.get(i), true);\r
                                }\r
                        }\r
 \r
@@ -290,7 +287,7 @@ public final class AndroidInput implements Input, OnKeyListener, OnTouchListener
                        KeyEvent event = null;\r
                        switch (e.getAction()) {\r
                        case android.view.KeyEvent.ACTION_DOWN:\r
-                               event = freeKeyEvents.newObject();\r
+                               event = usedKeyEvents.add();\r
                                event.keyChar = 0;\r
                                event.keyCode = e.getKeyCode();\r
                                event.type = KeyEvent.KEY_DOWN;\r
@@ -298,13 +295,13 @@ public final class AndroidInput implements Input, OnKeyListener, OnTouchListener
                                keys.add(event.keyCode);\r
                                break;\r
                        case android.view.KeyEvent.ACTION_UP:\r
-                               event = freeKeyEvents.newObject();\r
+                               event = usedKeyEvents.add();\r
                                event.keyChar = 0;\r
                                event.keyCode = e.getKeyCode();\r
                                event.type = KeyEvent.KEY_UP;\r
                                keyEvents.add(event);\r
 \r
-                               event = freeKeyEvents.newObject();\r
+                               event = usedKeyEvents.add();\r
                                event.keyChar = character;\r
                                event.keyCode = 0;\r
                                event.type = KeyEvent.KEY_TYPED;\r
index cb546c7..29d2661 100644 (file)
@@ -73,7 +73,7 @@ public class AndroidMultiTouchHandler implements AndroidTouchHandler {
        private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer) {\r
                long timeStamp = System.nanoTime();\r
                synchronized (input) {\r
-                       TouchEvent event = input.freeTouchEvents.newObject();\r
+                       TouchEvent event = input.usedTouchEvents.add();\r
                        event.timeStamp = timeStamp;\r
                        event.pointer = pointer;\r
                        event.x = x;\r
index 4aa6499..57b697c 100644 (file)
@@ -52,7 +52,7 @@ public class AndroidSingleTouchHandler implements AndroidTouchHandler {
        private void postTouchEvent (AndroidInput input, int type, int x, int y, int pointer) {\r
                long timeStamp = System.nanoTime();\r
                synchronized (input) {\r
-                       TouchEvent event = input.freeTouchEvents.newObject();\r
+                       TouchEvent event = input.usedTouchEvents.add();\r
                        event.timeStamp = timeStamp;\r
                        event.pointer = 0;\r
                        event.x = x;\r
index 230b169..35a785b 100644 (file)
@@ -28,8 +28,7 @@ import javax.swing.SwingUtilities;
 \r
 import com.badlogic.gdx.Input;\r
 import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class JoglInput implements Input, MouseMotionListener, MouseListener, KeyListener {\r
        class KeyEvent {\r
@@ -53,19 +52,17 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
                int pointer;\r
        }\r
 \r
-       Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
-               @Override public KeyEvent createObject () {\r
+       BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+               protected KeyEvent newObject () {\r
                        return new KeyEvent();\r
                }\r
-       }, 1000);\r
-\r
-       Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+       };\r
 \r
-               @Override public TouchEvent createObject () {\r
+       BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+               protected TouchEvent newObject () {\r
                        return new TouchEvent();\r
                }\r
-       }, 1000);\r
+       };\r
 \r
        List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
        List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
@@ -167,7 +164,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
                                        case KeyEvent.KEY_TYPED:\r
                                                processor.keyTyped(e.keyChar);\r
                                        }\r
-                                       freeKeyEvents.free(e);\r
+                                       usedKeyEvents.removeValue(e, true);\r
                                }\r
 \r
                                len = touchEvents.size();\r
@@ -183,17 +180,17 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
                                        case TouchEvent.TOUCH_DRAGGED:\r
                                                processor.touchDragged(e.x, e.y, e.pointer);\r
                                        }\r
-                                       freeTouchEvents.free(e);\r
+                                       usedTouchEvents.removeValue(e, true);\r
                                }\r
                        } else {\r
                                int len = touchEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeTouchEvents.free(touchEvents.get(i));\r
+                                       usedTouchEvents.removeValue(touchEvents.get(i), true);\r
                                }\r
 \r
                                len = keyEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeKeyEvents.free(keyEvents.get(i));\r
+                                       usedKeyEvents.removeValue(keyEvents.get(i), true);\r
                                }\r
                        }\r
 \r
@@ -220,7 +217,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void mouseDragged (MouseEvent e) {\r
                synchronized (this) {\r
-                       TouchEvent event = freeTouchEvents.newObject();\r
+                       TouchEvent event = usedTouchEvents.add();\r
                        event.pointer = 0;\r
                        event.x = e.getX();\r
                        event.y = e.getY();\r
@@ -249,7 +246,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void mousePressed (MouseEvent e) {\r
                synchronized (this) {\r
-                       TouchEvent event = freeTouchEvents.newObject();\r
+                       TouchEvent event = usedTouchEvents.add();\r
                        event.pointer = 0;\r
                        event.x = e.getX();\r
                        event.y = e.getY();\r
@@ -264,7 +261,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void mouseReleased (MouseEvent e) {\r
                synchronized (this) {\r
-                       TouchEvent event = freeTouchEvents.newObject();\r
+                       TouchEvent event = usedTouchEvents.add();\r
                        event.pointer = 0;\r
                        event.x = e.getX();\r
                        event.y = e.getY();\r
@@ -279,7 +276,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void keyPressed (java.awt.event.KeyEvent e) {\r
                synchronized (this) {\r
-                       KeyEvent event = freeKeyEvents.newObject();\r
+                       KeyEvent event = usedKeyEvents.add();\r
                        event.keyChar = 0;\r
                        event.keyCode = translateKeyCode(e.getKeyCode());\r
                        event.type = KeyEvent.KEY_DOWN;\r
@@ -290,7 +287,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void keyReleased (java.awt.event.KeyEvent e) {\r
                synchronized (this) {\r
-                       KeyEvent event = freeKeyEvents.newObject();\r
+                       KeyEvent event = usedKeyEvents.add();\r
                        event.keyChar = 0;\r
                        event.keyCode = translateKeyCode(e.getKeyCode());\r
                        event.type = KeyEvent.KEY_UP;\r
@@ -301,7 +298,7 @@ public class JoglInput implements Input, MouseMotionListener, MouseListener, Key
 \r
        @Override public void keyTyped (java.awt.event.KeyEvent e) {\r
                synchronized (this) {\r
-                       KeyEvent event = freeKeyEvents.newObject();\r
+                       KeyEvent event = usedKeyEvents.add();\r
                        event.keyChar = e.getKeyChar();\r
                        event.keyCode = 0;\r
                        event.type = KeyEvent.KEY_TYPED;\r
index 61b5160..38ea83f 100644 (file)
@@ -25,8 +25,7 @@ import org.lwjgl.input.Mouse;
 import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.Input;\r
 import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 /**\r
  * An implementation of the {@link Input} interface hooking a Jogl panel for input.\r
@@ -56,19 +55,17 @@ final class LwjglInput implements Input {
                int pointer;\r
        }\r
 \r
-       Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
-               @Override public KeyEvent createObject () {\r
+       BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+               protected KeyEvent newObject () {\r
                        return new KeyEvent();\r
                }\r
-       }, 1000);\r
-\r
-       Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+       };\r
 \r
-               @Override public TouchEvent createObject () {\r
+       BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+               protected TouchEvent newObject () {\r
                        return new TouchEvent();\r
                }\r
-       }, 1000);\r
+       };\r
 \r
        List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
        List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
@@ -178,7 +175,7 @@ final class LwjglInput implements Input {
                                        case KeyEvent.KEY_TYPED:\r
                                                processor.keyTyped(e.keyChar);\r
                                        }\r
-                                       freeKeyEvents.free(e);\r
+                                       usedKeyEvents.removeValue(e, true);\r
                                }\r
 \r
                                len = touchEvents.size();\r
@@ -194,17 +191,17 @@ final class LwjglInput implements Input {
                                        case TouchEvent.TOUCH_DRAGGED:\r
                                                processor.touchDragged(e.x, e.y, e.pointer);\r
                                        }\r
-                                       freeTouchEvents.free(e);\r
+                                       usedTouchEvents.removeValue(e, true);\r
                                }\r
                        } else {\r
                                int len = touchEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeTouchEvents.free(touchEvents.get(i));\r
+                                       usedTouchEvents.removeValue(touchEvents.get(i), true);\r
                                }\r
 \r
                                len = keyEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeKeyEvents.free(keyEvents.get(i));\r
+                                       usedKeyEvents.removeValue(keyEvents.get(i), true);\r
                                }\r
                        }\r
 \r
@@ -464,7 +461,7 @@ final class LwjglInput implements Input {
                                if (isButtonPressed()) {\r
                                        if (mousePressed == false) {\r
                                                mousePressed = true;\r
-                                               TouchEvent event = freeTouchEvents.newObject();\r
+                                               TouchEvent event = usedTouchEvents.add();\r
                                                event.x = x;\r
                                                event.y = y;\r
                                                event.pointer = 0;\r
@@ -474,7 +471,7 @@ final class LwjglInput implements Input {
                                                mouseY = y;\r
                                        } else {\r
                                                if (mouseX != x || mouseY != y) {\r
-                                                       TouchEvent event = freeTouchEvents.newObject();\r
+                                                       TouchEvent event = usedTouchEvents.add();\r
                                                        event.x = x;\r
                                                        event.y = y;\r
                                                        event.pointer = 0;\r
@@ -489,7 +486,7 @@ final class LwjglInput implements Input {
                                                mouseX = x;\r
                                                mouseY = y;\r
                                                mousePressed = false;\r
-                                               TouchEvent event = freeTouchEvents.newObject();\r
+                                               TouchEvent event = usedTouchEvents.add();\r
                                                event.x = x;\r
                                                event.y = y;\r
                                                event.pointer = 0;\r
@@ -514,13 +511,13 @@ final class LwjglInput implements Input {
                                        int keyCode = getGdxKeyCode(Keyboard.getEventKey());\r
                                        char keyChar = Keyboard.getEventCharacter();\r
 \r
-                                       KeyEvent event = freeKeyEvents.newObject();\r
+                                       KeyEvent event = usedKeyEvents.add();\r
                                        event.keyCode = keyCode;\r
                                        event.keyChar = 0;\r
                                        event.type = KeyEvent.KEY_DOWN;\r
                                        keyEvents.add(event);\r
 \r
-                                       event = freeKeyEvents.newObject();\r
+                                       event = usedKeyEvents.add();\r
                                        event.keyCode = 0;\r
                                        event.keyChar = keyChar;\r
                                        event.type = KeyEvent.KEY_TYPED;\r
@@ -529,7 +526,7 @@ final class LwjglInput implements Input {
                                } else {\r
                                        int keyCode = LwjglInput.getGdxKeyCode(Keyboard.getEventKey());\r
 \r
-                                       KeyEvent event = freeKeyEvents.newObject();\r
+                                       KeyEvent event = usedKeyEvents.add();\r
                                        event.keyCode = keyCode;\r
                                        event.keyChar = 0;\r
                                        event.type = KeyEvent.KEY_UP;\r
index 8874abc..3263217 100644 (file)
@@ -23,8 +23,7 @@ import javax.swing.SwingUtilities;
 import com.badlogic.anglejni.ESLoop;\r
 import com.badlogic.gdx.Input;\r
 import com.badlogic.gdx.InputProcessor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class AngleInput implements Input {\r
 \r
@@ -49,19 +48,17 @@ public class AngleInput implements Input {
                int pointer;\r
        }\r
 \r
-       Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(new PoolObjectFactory<KeyEvent>() {\r
-\r
-               @Override public KeyEvent createObject () {\r
+       BagPool<KeyEvent> usedKeyEvents = new BagPool<KeyEvent>(16, 1000) {\r
+               protected KeyEvent newObject () {\r
                        return new KeyEvent();\r
                }\r
-       }, 1000);\r
-\r
-       Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(new PoolObjectFactory<TouchEvent>() {\r
+       };\r
 \r
-               @Override public TouchEvent createObject () {\r
+       BagPool<TouchEvent> usedTouchEvents = new BagPool<TouchEvent>(16, 1000) {\r
+               protected TouchEvent newObject () {\r
                        return new TouchEvent();\r
                }\r
-       }, 1000);\r
+       };\r
 \r
        List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
        List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
@@ -171,7 +168,7 @@ public class AngleInput implements Input {
                                        case KeyEvent.KEY_TYPED:\r
                                                processor.keyTyped(e.keyChar);\r
                                        }\r
-                                       freeKeyEvents.free(e);\r
+                                       usedKeyEvents.removeValue(e, true);\r
                                }\r
 \r
                                len = touchEvents.size();\r
@@ -187,17 +184,17 @@ public class AngleInput implements Input {
                                        case TouchEvent.TOUCH_DRAGGED:\r
                                                processor.touchDragged(e.x, e.y, e.pointer);\r
                                        }\r
-                                       freeTouchEvents.free(e);\r
+                                       usedTouchEvents.removeValue(e, true);\r
                                }\r
                        } else {\r
                                int len = touchEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeTouchEvents.free(touchEvents.get(i));\r
+                                       usedTouchEvents.removeValue(touchEvents.get(i), true);\r
                                }\r
 \r
                                len = keyEvents.size();\r
                                for (int i = 0; i < len; i++) {\r
-                                       freeKeyEvents.free(keyEvents.get(i));\r
+                                       usedKeyEvents.removeValue(keyEvents.get(i), true);\r
                                }\r
                        }\r
 \r
@@ -216,7 +213,7 @@ public class AngleInput implements Input {
 \r
        void registerKeyEvent (int action, int key, int uniCode) {\r
                synchronized (this) {\r
-                       KeyEvent event = freeKeyEvents.newObject();\r
+                       KeyEvent event = usedKeyEvents.add();\r
                        event.keyChar = (char)uniCode;\r
                        event.keyCode = translateKey(key);\r
 \r
@@ -240,7 +237,7 @@ public class AngleInput implements Input {
                if (button != 1) return;\r
 \r
                synchronized (this) {\r
-                       TouchEvent event = freeTouchEvents.newObject();\r
+                       TouchEvent event = usedTouchEvents.add();\r
                        event.x = x;\r
                        event.y = y;\r
                        event.pointer = 0;\r
index d65c8d2..6a1f3ca 100644 (file)
@@ -104,7 +104,7 @@ public class LevelRenderer implements ApplicationListener {
 \r
                                int type = Integer.parseInt(reader.readLine());\r
                                String textureId = reader.readLine();\r
-                               TextureRegion region = atlas.getRegion(textureId);\r
+                               TextureRegion region = atlas.findRegion(textureId);\r
                                float u = region.getU();\r
                                float v = region.getV();\r
 \r
@@ -142,7 +142,7 @@ public class LevelRenderer implements ApplicationListener {
 \r
                                        int type = Integer.parseInt(reader.readLine());\r
                                        String textureId = reader.readLine();\r
-                                       TextureRegion region = atlas.getRegion(textureId);\r
+                                       TextureRegion region = atlas.findRegion(textureId);\r
                                        float u = region.getU();\r
                                        float v = region.getV();\r
 \r
index 27d6daf..2ffb204 100644 (file)
@@ -14,6 +14,7 @@
 package com.badlogic.gdx.twl;\r
 \r
 import de.matthiasmann.twl.DialogLayout;\r
+import de.matthiasmann.twl.Event;\r
 import de.matthiasmann.twl.Widget;\r
 \r
 /**\r
@@ -21,6 +22,8 @@ import de.matthiasmann.twl.Widget;
  * @author Nathan Sweet\r
  */\r
 public class Layout extends DialogLayout {\r
+       private boolean eatEvents;\r
+\r
        public Layout () {\r
                setTheme("");\r
        }\r
@@ -29,6 +32,19 @@ public class Layout extends DialogLayout {
                setTheme(theme);\r
        }\r
 \r
+       public Layout (boolean eatEvents) {\r
+               this.eatEvents = eatEvents;\r
+       }\r
+\r
+       public Layout (String theme, boolean eatEvents) {\r
+               setTheme(theme);\r
+               this.eatEvents = eatEvents;\r
+       }\r
+\r
+       protected boolean handleEvent (Event evt) {\r
+               return eatEvents;\r
+       }\r
+\r
        public Direction horizontal () {\r
                return new Direction(true);\r
        }\r
index 90bfe3e..1c279b9 100644 (file)
@@ -15,10 +15,10 @@ package com.badlogic.gdx.twl.renderer;
 
 import java.io.IOException;
 import java.net.URL;
-import java.util.HashMap;
 
 import com.badlogic.gdx.files.FileHandle;
 import com.badlogic.gdx.graphics.BitmapFont;
+import com.badlogic.gdx.utils.ObjectMap;
 
 import de.matthiasmann.twl.renderer.CacheContext;
 
@@ -27,8 +27,8 @@ import de.matthiasmann.twl.renderer.CacheContext;
  */
 class GdxCacheContext implements CacheContext {
        final GdxRenderer renderer;
-       private final HashMap<String, GdxTexture> textures = new HashMap();
-       private final HashMap<String, BitmapFont> fonts = new HashMap();
+       private final ObjectMap<String, GdxTexture> textures = new ObjectMap();
+       private final ObjectMap<String, BitmapFont> fonts = new ObjectMap();
        private boolean valid = true;
 
        GdxCacheContext (GdxRenderer renderer) {
index 9a00e0a..b66c432 100644 (file)
@@ -186,7 +186,7 @@ public class TextureAtlas {
         * should be cached rather than calling this method multiple times.\r
         * @return The region, or null.\r
         */\r
-       public AtlasRegion getRegion (String name) {\r
+       public AtlasRegion findRegion (String name) {\r
                for (int i = 0, n = regions.size(); i < n; i++)\r
                        if (regions.get(i).name.equals(name)) return regions.get(i);\r
                return null;\r
@@ -197,7 +197,7 @@ public class TextureAtlas {
         * the result should be cached rather than calling this method multiple times.\r
         * @return The region, or null.\r
         */\r
-       public AtlasRegion getRegion (String name, int index) {\r
+       public AtlasRegion findRegion (String name, int index) {\r
                for (int i = 0, n = regions.size(); i < n; i++) {\r
                        AtlasRegion region = regions.get(i);\r
                        if (!region.name.equals(name)) continue;\r
@@ -211,7 +211,7 @@ public class TextureAtlas {
         * Returns all regions with the specified name, ordered by smallest to largest {@link AtlasRegion#index index}. This method\r
         * uses string comparison to find the regions, so the result should be cached rather than calling this method multiple times.\r
         */\r
-       public List<AtlasRegion> getRegions (String name) {\r
+       public List<AtlasRegion> findRegions (String name) {\r
                ArrayList<AtlasRegion> matched = new ArrayList();\r
                for (int i = 0, n = regions.size(); i < n; i++) {\r
                        AtlasRegion region = regions.get(i);\r
@@ -223,9 +223,9 @@ public class TextureAtlas {
        /**\r
         * Returns all regions in the atlas as sprites. This method creates a new sprite for each region, so the result should be\r
         * stored rather than calling this method multiple times.\r
-        * @see #getSprite(String)\r
+        * @see #createSprite(String)\r
         */\r
-       public List<Sprite> getSprites () {\r
+       public List<Sprite> createSprites () {\r
                ArrayList sprites = new ArrayList(regions.size());\r
                for (int i = 0, n = regions.size(); i < n; i++)\r
                        sprites.add(newSprite(regions.get(i)));\r
@@ -238,7 +238,7 @@ public class TextureAtlas {
         * find the region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.\r
         * @return The sprite, or null.\r
         */\r
-       public Sprite getSprite (String name) {\r
+       public Sprite createSprite (String name) {\r
                for (int i = 0, n = regions.size(); i < n; i++)\r
                        if (regions.get(i).name.equals(name)) return newSprite(regions.get(i));\r
                return null;\r
@@ -248,9 +248,9 @@ public class TextureAtlas {
         * Returns the first region found with the specified name and index as a sprite. This method uses string comparison to find the\r
         * region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.\r
         * @return The sprite, or null.\r
-        * @see #getSprite(String)\r
+        * @see #createSprite(String)\r
         */\r
-       public Sprite getSprite (String name, int index) {\r
+       public Sprite createSprite (String name, int index) {\r
                for (int i = 0, n = regions.size(); i < n; i++) {\r
                        AtlasRegion region = regions.get(i);\r
                        if (!region.name.equals(name)) continue;\r
@@ -264,9 +264,9 @@ public class TextureAtlas {
         * Returns all regions with the specified name as sprites, ordered by smallest to largest {@link AtlasRegion#index index}. This\r
         * method uses string comparison to find the regions and constructs new sprites, so the result should be cached rather than\r
         * calling this method multiple times.\r
-        * @see #getSprite(String)\r
+        * @see #createSprite(String)\r
         */\r
-       public List<Sprite> getSprites (String name) {\r
+       public List<Sprite> createSprites (String name) {\r
                ArrayList<Sprite> matched = new ArrayList();\r
                for (int i = 0, n = regions.size(); i < n; i++) {\r
                        AtlasRegion region = regions.get(i);\r
@@ -325,7 +325,7 @@ public class TextureAtlas {
                 * <br>\r
                 * When sprites are packed, if the original file name ends with a number, it is stored as the index and is not considered as\r
                 * part of the sprite's name. This is useful for keeping animation frames in order.\r
-                * @see TextureAtlas#getRegions(String)\r
+                * @see TextureAtlas#findRegions(String)\r
                 */\r
                public int index;\r
 \r
index 3640e2e..faa5f2f 100644 (file)
@@ -25,6 +25,7 @@ import com.badlogic.gdx.graphics.GL20;
 import com.badlogic.gdx.graphics.Mesh;\r
 import com.badlogic.gdx.math.Matrix3;\r
 import com.badlogic.gdx.math.Matrix4;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
 \r
 /**\r
  * <p>\r
@@ -68,10 +69,10 @@ public class ShaderProgram {
        private boolean isCompiled;\r
 \r
        /** uniform lookup **/\r
-       private final HashMap<String, Integer> uniforms = new HashMap<String, Integer>();\r
+       private final ObjectMap<String, Integer> uniforms = new ObjectMap<String, Integer>();\r
 \r
        /** attribute lookup **/\r
-       private final HashMap<String, Integer> attributes = new HashMap<String, Integer>();\r
+       private final ObjectMap<String, Integer> attributes = new ObjectMap<String, Integer>();\r
 \r
        /** program handle **/\r
        private int program;\r
index 462d2fe..ed4414a 100644 (file)
@@ -14,19 +14,18 @@ package com.badlogic.gdx.graphics.keyframed;
 \r
 import java.io.DataInputStream;\r
 import java.io.DataOutputStream;\r
-import java.util.HashMap;\r
 \r
-import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.graphics.GL10;\r
 import com.badlogic.gdx.graphics.Material;\r
 import com.badlogic.gdx.graphics.Mesh;\r
 import com.badlogic.gdx.graphics.VertexAttributes;\r
-import com.badlogic.gdx.utils.GdxRuntimeException;\r
 import com.badlogic.gdx.graphics.animation.Animator;\r
 import com.badlogic.gdx.graphics.loaders.md5.MD5Animation;\r
 import com.badlogic.gdx.graphics.loaders.md5.MD5Animator;\r
 import com.badlogic.gdx.graphics.loaders.md5.MD5Model;\r
 import com.badlogic.gdx.graphics.loaders.md5.MD5Renderer;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
 \r
 /**\r
  * An animated model with {@link KeyframeAnimation}s. Currently the animations can only be instanced from an {@link MD5Animation}.\r
@@ -38,7 +37,7 @@ import com.badlogic.gdx.graphics.loaders.md5.MD5Renderer;
 public class KeyframedModel {\r
        \r
        private Material[] mMaterials;\r
-       private HashMap<String, KeyframeAnimation> mAnimations = new HashMap<String, KeyframeAnimation>();\r
+       private ObjectMap<String, KeyframeAnimation> mAnimations = new ObjectMap<String, KeyframeAnimation>();\r
        private KeyframeAnimator mAnimator = null;\r
        private Mesh[] mTarget = null;\r
        private int mNumMeshes = 0;\r
index ddbd41e..c85736b 100644 (file)
@@ -144,7 +144,7 @@ public class ParticleEffect {
                        String imageName = new File(imagePath.replace('\\', '/')).getName();\r
                        int lastDotIndex = imageName.lastIndexOf('.');\r
                        if (lastDotIndex != -1) imageName = imageName.substring(0, lastDotIndex);\r
-                       Sprite sprite = atlas.getSprite(imageName);\r
+                       Sprite sprite = atlas.createSprite(imageName);\r
                        if (sprite == null) throw new IllegalArgumentException("SpriteSheet missing image: " + imageName);\r
                        emitter.setSprite(sprite);\r
                }\r
index 8b7381d..a01c1e9 100644 (file)
  */\r
 package com.badlogic.gdx.graphics.texturedict;\r
 \r
-import java.util.HashMap;\r
-import java.util.Map.Entry;\r
-\r
-import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.files.FileHandle;\r
 import com.badlogic.gdx.graphics.Texture;\r
 import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
 import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
 \r
 /**\r
 * <p>\r
@@ -34,7 +32,7 @@ import com.badlogic.gdx.graphics.Texture.TextureWrap;
 */\r
 public class TextureDict {\r
        \r
-       private static HashMap<String, TextureRef> sDictionary = new HashMap<String, TextureRef>();\r
+       private static ObjectMap<String, TextureRef> sDictionary = new ObjectMap<String, TextureRef>();\r
 \r
        /**\r
         * Loads a new texture into the dictionary as a reference counted {@link TextureRef}.\r
index 8066377..bf23711 100644 (file)
@@ -37,7 +37,7 @@ import com.badlogic.gdx.physics.box2d.joints.RevoluteJoint;
 import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;\r
 import com.badlogic.gdx.physics.box2d.joints.WeldJoint;\r
 import com.badlogic.gdx.physics.box2d.joints.WeldJointDef;\r
-import com.badlogic.gdx.utils.LongHashMap;\r
+import com.badlogic.gdx.utils.LongMap;\r
 \r
 /**\r
  * The world class manages all physics entities, dynamic simulation, and asynchronous queries. The world also contains efficient\r
@@ -49,13 +49,13 @@ public class World {
        private final long addr;\r
 \r
        /** all known bodies **/\r
-       protected final LongHashMap<Body> bodies = new LongHashMap<Body>(100);\r
+       protected final LongMap<Body> bodies = new LongMap<Body>(100);\r
 \r
        /** all known fixtures **/\r
-       protected final LongHashMap<Fixture> fixtures = new LongHashMap<Fixture>(100);\r
+       protected final LongMap<Fixture> fixtures = new LongMap<Fixture>(100);\r
 \r
        /** all known joints **/\r
-       protected final LongHashMap<Joint> joints = new LongHashMap<Joint>(100);\r
+       protected final LongMap<Joint> joints = new LongMap<Joint>(100);\r
 \r
        /** Contact filter **/\r
        protected ContactFilter contactFilter = null;\r
index 90d5a8c..7fba4e3 100644 (file)
@@ -15,9 +15,7 @@ package com.badlogic.gdx.scenes.scene2d;
 \r
 import java.util.ArrayList;\r
 import java.util.Collections;\r
-import java.util.HashMap;\r
 import java.util.List;\r
-import java.util.Map;\r
 \r
 import com.badlogic.gdx.Files.FileType;\r
 import com.badlogic.gdx.Gdx;\r
@@ -28,6 +26,7 @@ import com.badlogic.gdx.graphics.Texture.TextureWrap;
 import com.badlogic.gdx.math.Matrix3;\r
 import com.badlogic.gdx.math.Matrix4;\r
 import com.badlogic.gdx.math.Vector2;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
 \r
 /**\r
  * A group is an Actor that contains other Actors (also other Groups which are Actors).\r
@@ -48,7 +47,7 @@ public class Group extends Actor {
        protected final List<Actor> immutableChildren;\r
        protected final List<Group> groups; // TODO O(n) delete, baad.\r
        protected final List<Group> immutableGroups;\r
-       protected final Map<String, Actor> namesToActors;\r
+       protected final ObjectMap<String, Actor> namesToActors;\r
 \r
        public Actor lastTouchedChild;\r
        public Actor focusedActor = null;\r
@@ -64,7 +63,7 @@ public class Group extends Actor {
                this.immutableChildren = Collections.unmodifiableList(this.children);\r
                this.groups = new ArrayList<Group>();\r
                this.immutableGroups = Collections.unmodifiableList(this.groups);\r
-               this.namesToActors = new HashMap<String, Actor>();\r
+               this.namesToActors = new ObjectMap<String, Actor>();\r
        }\r
 \r
        protected void updateTransform () {\r
index 4aad7a1..03f2395 100644 (file)
@@ -15,22 +15,21 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class Delay implements Action {\r
-       static final Pool<Delay> pool = new Pool<Delay>(new PoolObjectFactory<Delay>() {\r
-               @Override public Delay createObject () {\r
+       static final BagPool<Delay> pool = new BagPool<Delay>(4, 100) {\r
+               protected Delay newObject () {\r
                        return new Delay();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float taken;\r
        protected float duration;\r
        protected Action action;\r
 \r
        public static Delay $ (Action action, float duration) {\r
-               Delay delay = pool.newObject();\r
+               Delay delay = pool.add();\r
                delay.duration = duration;\r
                delay.action = action;\r
                return delay;\r
@@ -51,7 +50,7 @@ public class Delay implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 0c289b8..1a46097 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class FadeIn implements Action {\r
-       static final Pool<FadeIn> pool = new Pool<FadeIn>(new PoolObjectFactory<FadeIn>() {\r
-               @Override public FadeIn createObject () {\r
+       static final BagPool<FadeIn> pool = new BagPool<FadeIn>(4, 100) {\r
+               protected FadeIn newObject () {\r
                        return new FadeIn();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float startAlpha = 0;\r
        protected float deltaAlpha = 0;\r
@@ -34,7 +33,7 @@ public class FadeIn implements Action {
        protected boolean done;\r
 \r
        public static FadeIn $ (float duration) {\r
-               FadeIn action = pool.newObject();\r
+               FadeIn action = pool.add();\r
                action.duration = duration;\r
                action.invDuration = 1 / duration;\r
                return action;\r
@@ -65,7 +64,7 @@ public class FadeIn implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index a7d4847..b39f86c 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class FadeOut implements Action {\r
-       static final Pool<FadeOut> pool = new Pool<FadeOut>(new PoolObjectFactory<FadeOut>() {\r
-               @Override public FadeOut createObject () {\r
+       static final BagPool<FadeOut> pool = new BagPool<FadeOut>(4, 100) {\r
+               protected FadeOut newObject () {\r
                        return new FadeOut();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float startAlpha = 0;\r
        protected float deltaAlpha = 0;\r
@@ -34,7 +33,7 @@ public class FadeOut implements Action {
        protected boolean done;\r
 \r
        public static FadeOut $ (float duration) {\r
-               FadeOut action = pool.newObject();\r
+               FadeOut action = pool.add();\r
                action.duration = duration;\r
                action.invDuration = 1 / duration;\r
                return action;\r
@@ -65,7 +64,7 @@ public class FadeOut implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 81c3999..2cad4f6 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class FadeTo implements Action {\r
-       static final Pool<FadeTo> pool = new Pool<FadeTo>(new PoolObjectFactory<FadeTo>() {\r
-               @Override public FadeTo createObject () {\r
+       static final BagPool<FadeTo> pool = new BagPool<FadeTo>(4, 100) {\r
+               protected FadeTo newObject () {\r
                        return new FadeTo();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float toAlpha = 0;\r
        protected float startAlpha;\r
@@ -35,7 +34,7 @@ public class FadeTo implements Action {
        protected boolean done;\r
 \r
        public static FadeTo $ (float alpha, float duration) {\r
-               FadeTo action = pool.newObject();\r
+               FadeTo action = pool.add();\r
                if (alpha < 0) alpha = 0;\r
                if (alpha > 1) alpha = 1;\r
                action.toAlpha = alpha;\r
@@ -68,7 +67,7 @@ public class FadeTo implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 7c859b5..c56d513 100644 (file)
@@ -15,21 +15,20 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class Forever implements Action {\r
-       static final Pool<Forever> pool = new Pool<Forever>(new PoolObjectFactory<Forever>() {\r
-               @Override public Forever createObject () {\r
+       static final BagPool<Forever> pool = new BagPool<Forever>(4, 100) {\r
+               protected Forever newObject () {\r
                        return new Forever();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected Action action;\r
        protected Actor target;\r
 \r
        public static Forever $ (Action action) {\r
-               Forever forever = pool.newObject();\r
+               Forever forever = pool.add();\r
                forever.action = action;\r
                return forever;\r
        }\r
@@ -54,7 +53,7 @@ public class Forever implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
                action.finish();\r
        }\r
 \r
index 9e93410..c6c1e5f 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class MoveBy implements Action {\r
-       static final Pool<MoveBy> pool = new Pool<MoveBy>(new PoolObjectFactory<MoveBy>() {\r
-               @Override public MoveBy createObject () {\r
+       static final BagPool<MoveBy> pool = new BagPool<MoveBy>(4, 100) {\r
+               protected MoveBy newObject () {\r
                        return new MoveBy();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float x;\r
        protected float y;\r
@@ -38,7 +37,7 @@ public class MoveBy implements Action {
        protected boolean done;\r
 \r
        public static MoveBy $ (float x, float y, float duration) {\r
-               MoveBy action = pool.newObject();\r
+               MoveBy action = pool.add();\r
                action.x = x;\r
                action.y = y;\r
                action.duration = duration;\r
@@ -73,7 +72,7 @@ public class MoveBy implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index bab3489..8e3f2c6 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class MoveTo implements Action {\r
-       static final Pool<MoveTo> pool = new Pool<MoveTo>(new PoolObjectFactory<MoveTo>() {\r
-               @Override public MoveTo createObject () {\r
+       static final BagPool<MoveTo> pool = new BagPool<MoveTo>(4, 100) {\r
+               protected MoveTo newObject () {\r
                        return new MoveTo();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float x;\r
        protected float y;\r
@@ -38,7 +37,7 @@ public class MoveTo implements Action {
        protected boolean done;\r
 \r
        public static MoveTo $ (float x, float y, float duration) {\r
-               MoveTo action = pool.newObject();\r
+               MoveTo action = pool.add();\r
                action.x = x;\r
                action.y = y;\r
                action.duration = duration;\r
@@ -73,7 +72,7 @@ public class MoveTo implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 3d90d12..6a17d70 100644 (file)
@@ -18,18 +18,17 @@ import java.util.List;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class Parallel implements Action {\r
-       static final Pool<Parallel> pool = new Pool<Parallel>(new PoolObjectFactory<Parallel>() {\r
-               @Override public Parallel createObject () {\r
+       static final BagPool<Parallel> pool = new BagPool<Parallel>(4, 100) {\r
+               protected Parallel newObject () {\r
                        return new Parallel();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        public static Parallel $ (Action... actions) {\r
-               Parallel action = pool.newObject();\r
+               Parallel action = pool.add();\r
                action.actions.clear();\r
                int len = actions.length;\r
                for (int i = 0; i < len; i++)\r
@@ -59,14 +58,14 @@ public class Parallel implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
                int len = 0;\r
                for (int i = 0; i < len; i++)\r
                        actions.get(i).finish();\r
        }\r
 \r
        @Override public Action copy () {\r
-               Parallel action = pool.newObject();\r
+               Parallel action = pool.add();\r
                action.actions.clear();\r
                int len = actions.size();\r
                for (int i = 0; i < len; i++)\r
index 355e575..5135d64 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class Repeat implements Action {\r
-       static final Pool<Repeat> pool = new Pool<Repeat>(new PoolObjectFactory<Repeat>() {\r
-               @Override public Repeat createObject () {\r
+       static final BagPool<Repeat> pool = new BagPool<Repeat>(4, 100) {\r
+               protected Repeat newObject () {\r
                        return new Repeat();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected Action action;\r
        protected Actor target;\r
@@ -31,7 +30,7 @@ public class Repeat implements Action {
        protected int finishedTimes;\r
 \r
        public static Repeat $ (Action action, int times) {\r
-               Repeat repeat = pool.newObject();\r
+               Repeat repeat = pool.add();\r
                repeat.action = action;\r
                repeat.times = times;\r
                repeat.finishedTimes = 0;\r
@@ -61,7 +60,7 @@ public class Repeat implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
                action.finish();\r
        }\r
 \r
index eccacac..de7393d 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class RotateBy implements Action {\r
-       static final Pool<RotateBy> pool = new Pool<RotateBy>(new PoolObjectFactory<RotateBy>() {\r
-               @Override public RotateBy createObject () {\r
+       static final BagPool<RotateBy> pool = new BagPool<RotateBy>(4, 100) {\r
+               protected RotateBy newObject () {\r
                        return new RotateBy();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float rotation;\r
        protected float startRotation;;\r
@@ -35,7 +34,7 @@ public class RotateBy implements Action {
        protected boolean done;\r
 \r
        public static RotateBy $ (float rotation, float duration) {\r
-               RotateBy action = pool.newObject();\r
+               RotateBy action = pool.add();\r
                action.rotation = rotation;\r
                action.duration = duration;\r
                action.invDuration = 1 / duration;\r
@@ -67,7 +66,7 @@ public class RotateBy implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 6e5f1f1..75a7e53 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class RotateTo implements Action {\r
-       static final Pool<RotateTo> pool = new Pool<RotateTo>(new PoolObjectFactory<RotateTo>() {\r
-               @Override public RotateTo createObject () {\r
+       static final BagPool<RotateTo> pool = new BagPool<RotateTo>(4, 100) {\r
+               protected RotateTo newObject () {\r
                        return new RotateTo();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float rotation;\r
        protected float startRotation;;\r
@@ -35,7 +34,7 @@ public class RotateTo implements Action {
        protected boolean done;\r
 \r
        public static RotateTo $ (float rotation, float duration) {\r
-               RotateTo action = pool.newObject();\r
+               RotateTo action = pool.add();\r
                action.rotation = rotation;\r
                action.duration = duration;\r
                action.invDuration = 1 / duration;\r
@@ -68,7 +67,7 @@ public class RotateTo implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 75ea2b8..878fc2b 100644 (file)
@@ -15,15 +15,14 @@ package com.badlogic.gdx.scenes.scene2d.actions;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class ScaleTo implements Action {\r
-       static final Pool<ScaleTo> pool = new Pool<ScaleTo>(new PoolObjectFactory<ScaleTo>() {\r
-               @Override public ScaleTo createObject () {\r
+       static final BagPool<ScaleTo> pool = new BagPool<ScaleTo>(4, 100) {\r
+               protected ScaleTo newObject () {\r
                        return new ScaleTo();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected float scaleX;\r
        protected float scaleY;\r
@@ -38,7 +37,7 @@ public class ScaleTo implements Action {
        protected boolean done;\r
 \r
        public static ScaleTo $ (float scaleX, float scaleY, float duration) {\r
-               ScaleTo action = pool.newObject();\r
+               ScaleTo action = pool.add();\r
                action.scaleX = scaleX;\r
                action.scaleY = scaleY;\r
                action.duration = duration;\r
@@ -76,7 +75,7 @@ public class ScaleTo implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
        }\r
 \r
        @Override public Action copy () {\r
index 0f3af46..026f92b 100644 (file)
@@ -18,22 +18,21 @@ import java.util.List;
 \r
 import com.badlogic.gdx.scenes.scene2d.Action;\r
 import com.badlogic.gdx.scenes.scene2d.Actor;\r
-import com.badlogic.gdx.utils.Pool;\r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+import com.badlogic.gdx.utils.BagPool;\r
 \r
 public class Sequence implements Action {\r
-       static final Pool<Sequence> pool = new Pool<Sequence>(new PoolObjectFactory<Sequence>() {\r
-               @Override public Sequence createObject () {\r
+       static final BagPool<Sequence> pool = new BagPool<Sequence>(4, 100) {\r
+               protected Sequence newObject () {\r
                        return new Sequence();\r
                }\r
-       }, 100);\r
+       };\r
 \r
        protected final List<Action> actions = new ArrayList<Action>();\r
        protected Actor target;\r
        protected int currAction = 0;\r
 \r
        public static Sequence $ (Action... actions) {\r
-               Sequence action = pool.newObject();\r
+               Sequence action = pool.add();\r
                action.actions.clear();\r
                int len = actions.length;\r
                for (int i = 0; i < len; i++)\r
@@ -65,14 +64,14 @@ public class Sequence implements Action {
        }\r
 \r
        @Override public void finish () {\r
-               pool.free(this);\r
+               pool.removeValue(this, true);\r
                int len = 0;\r
                for (int i = 0; i < len; i++)\r
                        actions.get(i).finish();\r
        }\r
 \r
        @Override public Action copy () {\r
-               Sequence action = pool.newObject();\r
+               Sequence action = pool.add();\r
                action.actions.clear();\r
                int len = actions.size();\r
                for (int i = 0; i < len; i++)\r
index a2831a2..92be935 100644 (file)
@@ -38,6 +38,7 @@ import java.util.NoSuchElementException;
 abstract public class ArrayPool<T> implements Iterable<T> {\r
        public T[] items;\r
        public int size;\r
+       public final int max;\r
 \r
        private ItemIterator iterator;\r
 \r
@@ -49,6 +50,14 @@ abstract public class ArrayPool<T> implements Iterable<T> {
        }\r
 \r
        public ArrayPool (int capacity) {\r
+               this(capacity, -1);\r
+       }\r
+\r
+       /**\r
+        * @param max The maximum size of this pool. See {@link #add()}.\r
+        */\r
+       public ArrayPool (int capacity, int max) {\r
+               this.max = max;\r
                this.items = (T[])new Object[capacity];\r
        }\r
 \r
@@ -63,12 +72,27 @@ abstract public class ArrayPool<T> implements Iterable<T> {
         * Creates a new array with {@link #items} of the specified type.\r
         */\r
        public ArrayPool (Class<T> arrayType, int capacity) {\r
+               this(arrayType, capacity, -1);\r
+       }\r
+\r
+       /**\r
+        * Creates a new array with {@link #items} of the specified type.\r
+        * @param max The maximum size of this pool. See {@link #add()}.\r
+        */\r
+       public ArrayPool (Class<T> arrayType, int capacity, int max) {\r
+               this.max = max;\r
                items = (T[])java.lang.reflect.Array.newInstance(arrayType, capacity);\r
        }\r
 \r
        abstract protected T newObject ();\r
 \r
+       /**\r
+        * Returns an object from this pool. The object may be new (from {@link #newObject()}) or reused (previously\r
+        * {@link #removeValue(Object, boolean) removed} from the pool). If this pool already contains {@link #max} objects, a new\r
+        * object is returned, but it is not added to the pool (it will be garbage collected).\r
+        */\r
        public T add () {\r
+               if (size == max) return newObject();\r
                T[] items = this.items;\r
                if (size == items.length) {\r
                        T item = newObject();\r
index 832864f..919cf6c 100644 (file)
@@ -27,6 +27,7 @@ import java.util.NoSuchElementException;
 abstract public class BagPool<T> implements Iterable<T> {\r
        public T[] items;\r
        public int size;\r
+       public final int max;\r
 \r
        private ItemIterator iterator;\r
 \r
@@ -38,6 +39,14 @@ abstract public class BagPool<T> implements Iterable<T> {
        }\r
 \r
        public BagPool (int capacity) {\r
+               this(capacity, -1);\r
+       }\r
+\r
+       /**\r
+        * @param max The maximum size of this pool. See {@link #add()}.\r
+        */\r
+       public BagPool (int capacity, int max) {\r
+               this.max = max;\r
                items = (T[])new Object[capacity];\r
        }\r
 \r
@@ -52,12 +61,27 @@ abstract public class BagPool<T> implements Iterable<T> {
         * Creates a new bag with {@link #items} of the specified type.\r
         */\r
        public BagPool (Class<T> arrayType, int capacity) {\r
+               this(arrayType, capacity, -1);\r
+       }\r
+\r
+       /**\r
+        * Creates a new bag with {@link #items} of the specified type.\r
+        * @param max The maximum size of this pool. See {@link #add()}.\r
+        */\r
+       public BagPool (Class<T> arrayType, int capacity, int max) {\r
+               this.max = max;\r
                items = (T[])java.lang.reflect.Array.newInstance(arrayType, capacity);\r
        }\r
 \r
        abstract protected T newObject ();\r
 \r
+       /**\r
+        * Returns an object from this pool. The object may be new (from {@link #newObject()}) or reused (previously\r
+        * {@link #removeValue(Object, boolean) removed} from the pool). If this pool already contains {@link #max} objects, a new\r
+        * object is returned, but it is not added to the pool (it will be garbage collected).\r
+        */\r
        public T add () {\r
+               if (size == max) return newObject();\r
                if (size == items.length) {\r
                        T item = newObject();\r
                        resize((int)(size * 1.75f), false)[size++] = item;\r
diff --git a/gdx/src/com/badlogic/gdx/utils/IdentityMap.java b/gdx/src/com/badlogic/gdx/utils/IdentityMap.java
new file mode 100644 (file)
index 0000000..1d4207c
--- /dev/null
@@ -0,0 +1,386 @@
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put.<br>\r
+ * <br>\r
+ * Warning: null cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class IdentityMap<K, V> {\r
+       static private final int EXTRA = 4;\r
+\r
+       public int size;\r
+\r
+       K[] keyTable;\r
+       V[] valueTable;\r
+       private float loadFactor;\r
+       private int mask, capacity, threshold;\r
+       private Entries entries;\r
+       private Values values;\r
+       private Keys keys;\r
+\r
+       public IdentityMap () {\r
+               this(16, 0.75f);\r
+       }\r
+\r
+       public IdentityMap (int initialCapacity) {\r
+               this(initialCapacity, 0.75f);\r
+       }\r
+\r
+       public IdentityMap (int initialCapacity, float loadFactor) {\r
+               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+               this.loadFactor = loadFactor;\r
+               threshold = (int)(capacity * loadFactor);\r
+               keyTable = (K[])new Object[capacity + EXTRA];\r
+               valueTable = (V[])new Object[capacity + EXTRA];\r
+               mask = capacity - 1;\r
+       }\r
+\r
+       public V put (K key, V value) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = System.identityHashCode(key) & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null || existingKey == key) break;\r
+                       index++;\r
+               }\r
+               keyTable[index] = key;\r
+               V oldValue = valueTable[index];\r
+               valueTable[index] = value;\r
+               if (size++ >= threshold || keyTable[keyTable.length - 1] != null) resize(capacity << 1);\r
+               return oldValue;\r
+       }\r
+\r
+       public void putAll (IdentityMap<K, V> map) {\r
+               ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+               for (Entry<K, V> entry : map.entries())\r
+                       put(entry.key, entry.value);\r
+       }\r
+\r
+       public V get (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = System.identityHashCode(key) & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return null;\r
+                       if (existingKey == key) return valueTable[index];\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+        * an expensive operation.\r
+        */\r
+       public boolean containsValue (Object value, boolean identity) {\r
+               V[] valueTable = this.valueTable;\r
+               if (value == null) {\r
+                       K[] keyTable = this.keyTable;\r
+                       for (int i = keyTable.length; i-- > 0;)\r
+                               if (keyTable[i] != null && valueTable[i] == null) return true;\r
+               } else if (identity) {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (valueTable[i] == value) return true;\r
+               } else {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (value.equals(valueTable[i])) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       public boolean containsKey (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = System.identityHashCode(key) & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return false;\r
+                       if (existingKey == key) return true;\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public V remove (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = System.identityHashCode(key) & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return null;\r
+                       if (existingKey == key) {\r
+                               keyTable[index] = null;\r
+                               V value = valueTable[index];\r
+                               valueTable[index] = null;\r
+                               return value;\r
+                       }\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public void clear () {\r
+               K[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = keyTable.length; i-- > 0;) {\r
+                       if (keyTable[i] != null) {\r
+                               keyTable[i] = null;\r
+                               valueTable[i] = null;\r
+                       }\r
+               }\r
+               size = 0;\r
+       }\r
+\r
+       /**\r
+        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+        * items to avoid multiple backing array resizes.\r
+        */\r
+       public void ensureCapacity (int additionalCapacity) {\r
+               int sizeNeeded = size + additionalCapacity;\r
+               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+       }\r
+\r
+       private void resize (int newSize) {\r
+               int newMask = newSize - 1;\r
+               mask = newMask;\r
+               capacity = newSize;\r
+               threshold = (int)(newSize * loadFactor);\r
+\r
+               newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+               K[] newKeyTable = (K[])new Object[newSize];\r
+               V[] newValueTable = (V[])new Object[newSize];\r
+\r
+               K[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = 0, n = keyTable.length; i < n; i++) {\r
+                       K key = keyTable[i];\r
+                       if (key != null) {\r
+                               int index = System.identityHashCode(key) & newMask;\r
+                               while (true) {\r
+                                       if (newKeyTable[index] == null) break;\r
+                                       index++;\r
+                               }\r
+                               if (index == newSize) {\r
+                                       // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+                                       resize(capacity << 1);\r
+                                       return;\r
+                               }\r
+                               newKeyTable[index] = key;\r
+                               newValueTable[index] = valueTable[i];\r
+                       }\r
+               }\r
+               this.keyTable = newKeyTable;\r
+               this.valueTable = newValueTable;\r
+       }\r
+\r
+       public String toString () {\r
+               if (size == 0) return "[]";\r
+               StringBuilder buffer = new StringBuilder(32);\r
+               buffer.append('[');\r
+\r
+               K[] keyTable = this.keyTable;\r
+               int i = keyTable.length;\r
+               while (i-- > 0) {\r
+                       K key = keyTable[i];\r
+                       if (key == null) continue;\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+                       break;\r
+               }\r
+               while (i-- > 0) {\r
+                       K key = keyTable[i];\r
+                       if (key == null) continue;\r
+                       buffer.append(", ");\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+               }\r
+               buffer.append(']');\r
+               return buffer.toString();\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+        * time this method is called.\r
+        */\r
+       public Entries<K, V> entries () {\r
+               if (entries == null)\r
+                       entries = new Entries(this);\r
+               else\r
+                       entries.reset();\r
+               return entries;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Values<V> values () {\r
+               if (values == null)\r
+                       values = new Values(this);\r
+               else\r
+                       values.reset();\r
+               return values;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Keys<K> keys () {\r
+               if (keys == null)\r
+                       keys = new Keys(this);\r
+               else\r
+                       keys.reset();\r
+               return keys;\r
+       }\r
+\r
+       static public class Entry<K, V> {\r
+               public K key;\r
+               public V value;\r
+\r
+               public String toString () {\r
+                       return key + "=" + value;\r
+               }\r
+       }\r
+\r
+       static public class Entries<K, V> implements Iterable<Entry<K, V>>, Iterator<Entry<K, V>> {\r
+               Entry<K, V> entry = new Entry();\r
+               int index = -1;\r
+               private final IdentityMap map;\r
+\r
+               public Entries (IdentityMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public Entry<K, V> next () {\r
+                       entry.key = (K)map.keyTable[index];\r
+                       entry.value = (V)map.valueTable[index];\r
+                       return entry;\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<Entry<K, V>> iterator () {\r
+                       return this;\r
+               }\r
+       }\r
+\r
+       static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+               int index = -1;\r
+               private final IdentityMap map;\r
+\r
+               public Values (IdentityMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public V next () {\r
+                       return (V)map.valueTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<V> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<V> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+\r
+       static public class Keys<K> implements Iterable<K>, Iterator<K> {\r
+               int index = -1;\r
+               private final IdentityMap map;\r
+\r
+               public Keys (IdentityMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public K next () {\r
+                       return (K)map.keyTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<K> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<K> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/IntHashMap.java b/gdx/src/com/badlogic/gdx/utils/IntHashMap.java
deleted file mode 100644 (file)
index 3d3d5aa..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.Iterator;\r
-\r
-/**\r
- * An unordered map that uses int keys. Avoids the boxing that occurs with HashMap<Integer, T>.\r
- * @author Nathan Sweet\r
- * @author christop widulle\r
- */\r
-public class IntHashMap<T> {\r
-       public int size;\r
-\r
-       Entry[] table;\r
-       private float loadFactor;\r
-       private int mask, capacity, threshold;\r
-       private Entries entries;\r
-       private Values values;\r
-       private Keys keys;\r
-\r
-       public IntHashMap () {\r
-               this(16, 0.75f);\r
-       }\r
-\r
-       public IntHashMap (int initialCapacity) {\r
-               this(initialCapacity, 0.75f);\r
-       }\r
-\r
-       public IntHashMap (int initialCapacity, float loadFactor) {\r
-               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
-               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
-               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
-               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
-               this.loadFactor = loadFactor;\r
-               threshold = (int)(capacity * loadFactor);\r
-               table = new Entry[capacity];\r
-               mask = capacity - 1;\r
-       }\r
-\r
-       public T put (int key, T value) {\r
-               int index = key & mask;\r
-               for (Entry e = table[index]; e != null; e = e.next) {\r
-                       if (e.key != key) continue;\r
-                       // Key already exists.\r
-                       Object oldValue = e.value;\r
-                       e.value = value;\r
-                       return (T)oldValue;\r
-               }\r
-               table[index] = new Entry(key, value, table[index]);\r
-               if (size++ >= threshold) resize(2 * capacity);\r
-               return null;\r
-       }\r
-\r
-       public T get (int key) {\r
-               int index = key & mask;\r
-               for (Entry e = table[index]; e != null; e = e.next)\r
-                       if (e.key == key) return (T)e.value;\r
-               return null;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
-        * time this method is called.\r
-        */\r
-       public IterableIterator<Entry<T>> entries () {\r
-               if (entries == null)\r
-                       entries = new Entries();\r
-               else\r
-                       entries.reset();\r
-               return entries;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
-        * this method is called.\r
-        */\r
-       public IterableIterator<T> values () {\r
-               if (values == null)\r
-                       values = new Values();\r
-               else\r
-                       values.reset();\r
-               return values;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
-        * this method is called.\r
-        */\r
-       public Keys keys () {\r
-               if (keys == null)\r
-                       keys = new Keys();\r
-               else\r
-                       keys.reset();\r
-               return keys;\r
-       }\r
-\r
-       /**\r
-        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
-        * an expensive operation.\r
-        */\r
-       public boolean containsValue (Object value, boolean identity) {\r
-               Entry[] table = this.table;\r
-               if (identity || value == null) {\r
-                       for (int i = table.length; i-- > 0;)\r
-                               for (Entry e = table[i]; e != null; e = e.next)\r
-                                       if (e.value == value) return true;\r
-               } else {\r
-                       for (int i = table.length; i-- > 0;)\r
-                               for (Entry e = table[i]; e != null; e = e.next)\r
-                                       if (value.equals(e.value)) return true;\r
-               }\r
-               return false;\r
-       }\r
-\r
-       public boolean containsKey (int key) {\r
-               int index = key & mask;\r
-               for (Entry e = table[index]; e != null; e = e.next)\r
-                       if (e.key == key) return true;\r
-               return false;\r
-       }\r
-\r
-       public T remove (int key) {\r
-               int index = key & mask;\r
-               Entry prev = table[index];\r
-               Entry e = prev;\r
-               while (e != null) {\r
-                       Entry next = e.next;\r
-                       if (e.key == key) {\r
-                               size--;\r
-                               if (prev == e)\r
-                                       table[index] = next;\r
-                               else\r
-                                       prev.next = next;\r
-                               return (T)e.value;\r
-                       }\r
-                       prev = e;\r
-                       e = next;\r
-               }\r
-               return null;\r
-       }\r
-\r
-       public void clear () {\r
-               Entry[] table = this.table;\r
-               for (int index = table.length; --index >= 0;)\r
-                       table[index] = null;\r
-               size = 0;\r
-       }\r
-\r
-       /**\r
-        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
-        * items to avoid multiple backing array resizes.\r
-        */\r
-       public void ensureCapacity (int additionalCapacity) {\r
-               int sizeNeeded = size + additionalCapacity;\r
-               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
-       }\r
-\r
-       private void resize (int newSize) {\r
-               Entry[] newTable = new Entry[newSize];\r
-               Entry[] table = this.table;\r
-               int bucketmask = newSize - 1;\r
-               for (int i = 0; i < table.length; i++) {\r
-                       Entry entry = table[i];\r
-                       if (entry != null) {\r
-                               table[i] = null;\r
-                               do {\r
-                                       Entry next = entry.next;\r
-                                       int index = entry.key & bucketmask;\r
-                                       entry.next = newTable[index];\r
-                                       newTable[index] = entry;\r
-                                       entry = next;\r
-                               } while (entry != null);\r
-                       }\r
-               }\r
-               this.table = newTable;\r
-               capacity = newSize;\r
-               threshold = (int)(newSize * loadFactor);\r
-               mask = capacity - 1;\r
-       }\r
-\r
-       public String toString () {\r
-               if (size == 0) return "[]";\r
-               StringBuilder buffer = new StringBuilder(32);\r
-               buffer.append('[');\r
-               Entry[] table = this.table;\r
-               int i = table.length;\r
-               while (i-- > 0) {\r
-                       Entry e = table[i];\r
-                       if (e == null) continue;\r
-                       buffer.append(e.key);\r
-                       buffer.append('=');\r
-                       buffer.append(e.value);\r
-                       for (e = e.next; e != null; e = e.next) {\r
-                               buffer.append(", ");\r
-                               buffer.append(e.key);\r
-                               buffer.append('=');\r
-                               buffer.append(e.value);\r
-                       }\r
-                       break;\r
-               }\r
-               while (i-- > 0) {\r
-                       for (Entry e = table[i]; e != null; e = e.next) {\r
-                               buffer.append(", ");\r
-                               buffer.append(e.key);\r
-                               buffer.append('=');\r
-                               buffer.append(e.value);\r
-                       }\r
-               }\r
-               buffer.append(']');\r
-               return buffer.toString();\r
-       }\r
-\r
-       class Entries implements IterableIterator {\r
-               private int index = -1;\r
-               Entry<T> entry = null;\r
-\r
-               public boolean hasNext () {\r
-                       if (entry != null && entry.next != null) {\r
-                               entry = entry.next;\r
-                               return true;\r
-                       }\r
-                       while (true) {\r
-                               index++;\r
-                               if (index >= table.length) return false;\r
-                               if (table[index] == null) continue;\r
-                               entry = table[index];\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-               public Object next () {\r
-                       return entry;\r
-               }\r
-\r
-               public void remove () {\r
-                       Entry prev = table[index];\r
-                       Entry e = prev;\r
-                       while (e != null) {\r
-                               Entry next = e.next;\r
-                               if (e == entry) {\r
-                                       size--;\r
-                                       if (prev == e)\r
-                                               table[index] = next;\r
-                                       else\r
-                                               prev.next = next;\r
-                                       return;\r
-                               }\r
-                               prev = e;\r
-                               e = next;\r
-                       }\r
-               }\r
-\r
-               void reset () {\r
-                       index = -1;\r
-                       entry = null;\r
-               }\r
-\r
-               public Iterator iterator () {\r
-                       return this;\r
-               }\r
-       }\r
-\r
-       class Values extends Entries {\r
-               public T next () {\r
-                       return entry.value;\r
-               }\r
-       }\r
-\r
-       public class Keys {\r
-               private int index = -1;\r
-               Entry<T> entry = null;\r
-\r
-               public boolean hasNext () {\r
-                       if (entry != null && entry.next != null) {\r
-                               entry = entry.next;\r
-                               return true;\r
-                       }\r
-                       while (true) {\r
-                               index++;\r
-                               if (index >= table.length) return false;\r
-                               if (table[index] == null) continue;\r
-                               entry = table[index];\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-               public int next () {\r
-                       return entry.key;\r
-               }\r
-\r
-               public void remove () {\r
-                       Entry prev = table[index];\r
-                       Entry e = prev;\r
-                       while (e != null) {\r
-                               Entry next = e.next;\r
-                               if (e == entry) {\r
-                                       size--;\r
-                                       if (prev == e)\r
-                                               table[index] = next;\r
-                                       else\r
-                                               prev.next = next;\r
-                                       return;\r
-                               }\r
-                               prev = e;\r
-                               e = next;\r
-                       }\r
-               }\r
-\r
-               void reset () {\r
-                       index = -1;\r
-                       entry = null;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * An entry in the map. The value may be changed directly.\r
-        */\r
-       static public class Entry<T> {\r
-               public final int key;\r
-               public T value;\r
-               Entry next;\r
-\r
-               Entry (int k, T v, Entry n) {\r
-                       key = k;\r
-                       value = v;\r
-                       next = n;\r
-               }\r
-\r
-               public String toString () {\r
-                       return key + "=" + value;\r
-               }\r
-       }\r
-}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/IntMap.java b/gdx/src/com/badlogic/gdx/utils/IntMap.java
new file mode 100644 (file)
index 0000000..33c5e49
--- /dev/null
@@ -0,0 +1,388 @@
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put. This class also avoids the boxing that occurs with\r
+ * HashMap<Integer, T>.<br>\r
+ * <br>\r
+ * Warning: Integer.MIN_VALUE cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class IntMap<V> {\r
+       static private final int EXTRA = 4;\r
+       static private final int EMPTY = Integer.MIN_VALUE;\r
+\r
+       public int size;\r
+\r
+       int[] keyTable;\r
+       V[] valueTable;\r
+       private float loadFactor;\r
+       private int mask, capacity, threshold;\r
+       private Entries entries;\r
+       private Values values;\r
+       private Keys keys;\r
+\r
+       public IntMap () {\r
+               this(16, 0.75f);\r
+       }\r
+\r
+       public IntMap (int initialCapacity) {\r
+               this(initialCapacity, 0.75f);\r
+       }\r
+\r
+       public IntMap (int initialCapacity, float loadFactor) {\r
+               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+               this.loadFactor = loadFactor;\r
+               threshold = (int)(capacity * loadFactor);\r
+               keyTable = new int[capacity + EXTRA];\r
+               for (int i = keyTable.length - 1; i >= 0; i--)\r
+                       keyTable[i] = EMPTY;\r
+               valueTable = (V[])new Object[capacity + EXTRA];\r
+               mask = capacity - 1;\r
+       }\r
+\r
+       public V put (int key, V value) {\r
+               int[] keyTable = this.keyTable;\r
+               int index = key & mask;\r
+               while (true) {\r
+                       int existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY || existingKey == key) break;\r
+                       index++;\r
+               }\r
+               keyTable[index] = key;\r
+               V oldValue = valueTable[index];\r
+               valueTable[index] = value;\r
+               if (size++ >= threshold || keyTable[keyTable.length - 1] != EMPTY) resize(capacity << 1);\r
+               return oldValue;\r
+       }\r
+\r
+       public void putAll (IntMap<V> map) {\r
+               ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+               for (Entry<V> entry : map.entries())\r
+                       put(entry.key, entry.value);\r
+       }\r
+\r
+       public V get (int key) {\r
+               int[] keyTable = this.keyTable;\r
+               int index = key & mask;\r
+               while (true) {\r
+                       int existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return null;\r
+                       if (existingKey == key) return valueTable[index];\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+        * an expensive operation.\r
+        */\r
+       public boolean containsValue (Object value, boolean identity) {\r
+               V[] valueTable = this.valueTable;\r
+               if (value == null) {\r
+                       int[] keyTable = this.keyTable;\r
+                       for (int i = keyTable.length; i-- > 0;)\r
+                               if (keyTable[i] != EMPTY && valueTable[i] == null) return true;\r
+               } else if (identity) {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (valueTable[i] == value) return true;\r
+               } else {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (value.equals(valueTable[i])) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       public boolean containsKey (int key) {\r
+               int[] keyTable = this.keyTable;\r
+               int index = key & mask;\r
+               while (true) {\r
+                       int existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return false;\r
+                       if (existingKey == key) return true;\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public V remove (int key) {\r
+               int[] keyTable = this.keyTable;\r
+               int index = key & mask;\r
+               while (true) {\r
+                       int existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return null;\r
+                       if (existingKey == key) {\r
+                               keyTable[index] = EMPTY;\r
+                               V value = valueTable[index];\r
+                               valueTable[index] = null;\r
+                               return value;\r
+                       }\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public void clear () {\r
+               int[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = keyTable.length; i-- > 0;) {\r
+                       if (keyTable[i] != EMPTY) {\r
+                               keyTable[i] = EMPTY;\r
+                               valueTable[i] = null;\r
+                       }\r
+               }\r
+               size = 0;\r
+       }\r
+\r
+       /**\r
+        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+        * items to avoid multiple backing array resizes.\r
+        */\r
+       public void ensureCapacity (int additionalCapacity) {\r
+               int sizeNeeded = size + additionalCapacity;\r
+               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+       }\r
+\r
+       private void resize (int newSize) {\r
+               int newMask = newSize - 1;\r
+               mask = newMask;\r
+               capacity = newSize;\r
+               threshold = (int)(newSize * loadFactor);\r
+\r
+               newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+               int[] newKeyTable = new int[newSize];\r
+               for (int i = newSize - 1; i >= 0; i--)\r
+                       newKeyTable[i] = EMPTY;\r
+               V[] newValueTable = (V[])new Object[newSize];\r
+\r
+               int[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = 0, n = keyTable.length; i < n; i++) {\r
+                       int key = keyTable[i];\r
+                       if (key != EMPTY) {\r
+                               int index = key & newMask;\r
+                               while (true) {\r
+                                       if (newKeyTable[index] == EMPTY) break;\r
+                                       index++;\r
+                               }\r
+                               if (index == newSize) {\r
+                                       // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+                                       resize(capacity << 1);\r
+                                       return;\r
+                               }\r
+                               newKeyTable[index] = key;\r
+                               newValueTable[index] = valueTable[i];\r
+                       }\r
+               }\r
+               this.keyTable = newKeyTable;\r
+               this.valueTable = newValueTable;\r
+       }\r
+\r
+       public String toString () {\r
+               if (size == 0) return "[]";\r
+               StringBuilder buffer = new StringBuilder(32);\r
+               buffer.append('[');\r
+\r
+               int[] keyTable = this.keyTable;\r
+               int i = keyTable.length;\r
+               while (i-- > 0) {\r
+                       int key = keyTable[i];\r
+                       if (key == EMPTY) continue;\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+                       break;\r
+               }\r
+               while (i-- > 0) {\r
+                       int key = keyTable[i];\r
+                       if (key == EMPTY) continue;\r
+                       buffer.append(", ");\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+               }\r
+               buffer.append(']');\r
+               return buffer.toString();\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+        * time this method is called.\r
+        */\r
+       public Entries<V> entries () {\r
+               if (entries == null)\r
+                       entries = new Entries(this);\r
+               else\r
+                       entries.reset();\r
+               return entries;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Values<V> values () {\r
+               if (values == null)\r
+                       values = new Values(this);\r
+               else\r
+                       values.reset();\r
+               return values;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Keys keys () {\r
+               if (keys == null)\r
+                       keys = new Keys(this);\r
+               else\r
+                       keys.reset();\r
+               return keys;\r
+       }\r
+\r
+       static public class Entry<V> {\r
+               public int key;\r
+               public V value;\r
+\r
+               public String toString () {\r
+                       return key + "=" + value;\r
+               }\r
+       }\r
+\r
+       static public class Entries<V> implements Iterable<Entry<V>>, Iterator<Entry<V>> {\r
+               Entry<V> entry = new Entry();\r
+               int index = -1;\r
+               private final IntMap map;\r
+\r
+               public Entries (IntMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       int[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public Entry<V> next () {\r
+                       entry.key = map.keyTable[index];\r
+                       entry.value = (V)map.valueTable[index];\r
+                       return entry;\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<Entry<V>> iterator () {\r
+                       return this;\r
+               }\r
+       }\r
+\r
+       static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+               int index = -1;\r
+               private final IntMap map;\r
+\r
+               public Values (IntMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       int[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public V next () {\r
+                       return (V)map.valueTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<V> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<V> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+\r
+       static public class Keys {\r
+               int index = -1;\r
+               private final IntMap map;\r
+\r
+               public Keys (IntMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       int[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public int next () {\r
+                       return map.keyTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public IntArray toArray () {\r
+                       IntArray array = new IntArray(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/LocklessThreadQueue.java b/gdx/src/com/badlogic/gdx/utils/LocklessThreadQueue.java
deleted file mode 100644 (file)
index c37f6ce..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-\r
-/**\r
- * A specialized lockless thread queue class template for doing single direction message passing from one thread to another.\r
- * \r
- * This queue class does NOT use the Synchronized method. However it is designed with atomic queue passing which makes it very\r
- * nice for non blocking event passing.\r
- * \r
- * This queue class keeps a fixed sized queue buffer which must be defined during initialization. If the queue buffer gets filled\r
- * up, any new queue request will get dropped.\r
- * \r
- * This queue class also handles object pooling such that no extra allocation will be used. This prevents bad GC trashing.\r
- */\r
-public class LocklessThreadQueue<T> {\r
-       /**\r
-        * Interface for an Object Factory for the initial buffer creation.\r
-        * @param <T> the type\r
-        */\r
-       public interface ObjectFactory<T> {\r
-               public T createObject ();\r
-       }\r
-\r
-       protected List<T> queueBuffer;\r
-       protected AtomicInteger head;\r
-       protected AtomicInteger tail;\r
-       protected int queueSize;\r
-\r
-       /**\r
-        * Constructor.\r
-        * @param factory Object factory for pre-buffered queue pool allocation.\r
-        * @param size Number of queue objects allowed before dropping queue request.\r
-        */\r
-       public LocklessThreadQueue (ObjectFactory<T> factory, int size) {\r
-               queueSize = size + 2;\r
-               queueBuffer = new ArrayList<T>(queueSize);\r
-               head = new AtomicInteger(0);\r
-               tail = new AtomicInteger(size + 1);\r
-\r
-               for (int i = 0; i < queueSize; ++i) {\r
-                       queueBuffer.add(factory.createObject());\r
-               }\r
-       }\r
-\r
-       /** Returns the next available preallocated object for preparation. */\r
-       public T prepare () {\r
-               int currHead = head.get();\r
-               int nextHead = (currHead + 1) % queueSize;\r
-               if (nextHead == tail.get()) return null;\r
-               return queueBuffer.get(currHead);\r
-       }\r
-\r
-       /**\r
-        * Push the next available object to the queue. This must be called after prepare is called for preparation. If it prepare()\r
-        * was not called, this will simply push the object unchanged from it's last queued state.\r
-        */\r
-       public void push () {\r
-               int nextHead = (head.get() + 1) % queueSize;\r
-               if (nextHead == tail.get()) return;\r
-               head.set(nextHead);\r
-       }\r
-\r
-       /** Returns null or the next queued object in the queue list */\r
-       public T pop () {\r
-               int nextTail = (tail.get() + 1) % queueSize;\r
-               if (head.get() == nextTail) return null;\r
-               T object = queueBuffer.get(nextTail);\r
-               tail.set(nextTail);\r
-               return object;\r
-       }\r
-}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/LongHashMap.java b/gdx/src/com/badlogic/gdx/utils/LongHashMap.java
deleted file mode 100644 (file)
index d0eebac..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.Iterator;\r
-\r
-/**\r
- * An unordered map that uses long keys. Avoids the boxing that occurs with HashMap<Long, T>.\r
- * @author Nathan Sweet\r
- * @author christop widulle\r
- */\r
-public class LongHashMap<T> {\r
-       public int size;\r
-\r
-       Entry[] table;\r
-       private float loadFactor;\r
-       private int mask, capacity, threshold;\r
-       private Entries entries;\r
-       private Values values;\r
-       private Keys keys;\r
-\r
-       public LongHashMap () {\r
-               this(16, 0.75f);\r
-       }\r
-\r
-       public LongHashMap (int initialCapacity) {\r
-               this(initialCapacity, 0.75f);\r
-       }\r
-\r
-       public LongHashMap (int initialCapacity, float loadFactor) {\r
-               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
-               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
-               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
-               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
-               this.loadFactor = loadFactor;\r
-               threshold = (int)(capacity * loadFactor);\r
-               table = new Entry[capacity];\r
-               mask = capacity - 1;\r
-       }\r
-\r
-       public T put (long key, T value) {\r
-               int index = (int)(key & mask);\r
-               for (Entry e = table[index]; e != null; e = e.next) {\r
-                       if (e.key != key) continue;\r
-                       // Key already exists.\r
-                       Object oldValue = e.value;\r
-                       e.value = value;\r
-                       return (T)oldValue;\r
-               }\r
-               table[index] = new Entry(key, value, table[index]);\r
-               if (size++ >= threshold) resize(2 * capacity);\r
-               return null;\r
-       }\r
-\r
-       public T get (long key) {\r
-               int index = (int)(key & mask);\r
-               for (Entry e = table[index]; e != null; e = e.next)\r
-                       if (e.key == key) return (T)e.value;\r
-               return null;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
-        * time this method is called.\r
-        */\r
-       public Iterator entries () {\r
-               if (entries == null)\r
-                       entries = new Entries();\r
-               else\r
-                       entries.reset();\r
-               return entries;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
-        * this method is called.\r
-        */\r
-       public Iterator values () {\r
-               if (values == null)\r
-                       values = new Values();\r
-               else\r
-                       values.reset();\r
-               return values;\r
-       }\r
-\r
-       /**\r
-        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
-        * this method is called.\r
-        */\r
-       public Keys keys () {\r
-               if (keys == null)\r
-                       keys = new Keys();\r
-               else\r
-                       keys.reset();\r
-               return keys;\r
-       }\r
-\r
-       /**\r
-        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
-        * an expensive operation.\r
-        */\r
-       public boolean containsValue (Object value, boolean identity) {\r
-               Entry[] table = this.table;\r
-               if (identity || value == null) {\r
-                       for (int i = table.length; i-- > 0;)\r
-                               for (Entry e = table[i]; e != null; e = e.next)\r
-                                       if (e.value == value) return true;\r
-               } else {\r
-                       for (int i = table.length; i-- > 0;)\r
-                               for (Entry e = table[i]; e != null; e = e.next)\r
-                                       if (value.equals(e.value)) return true;\r
-               }\r
-               return false;\r
-       }\r
-\r
-       public boolean containsKey (long key) {\r
-               int index = (int)(key & mask);\r
-               for (Entry e = table[index]; e != null; e = e.next)\r
-                       if (e.key == key) return true;\r
-               return false;\r
-       }\r
-\r
-       public T remove (long key) {\r
-               int index = (int)(key & mask);\r
-               Entry prev = table[index];\r
-               Entry e = prev;\r
-               while (e != null) {\r
-                       Entry next = e.next;\r
-                       if (e.key == key) {\r
-                               size--;\r
-                               if (prev == e)\r
-                                       table[index] = next;\r
-                               else\r
-                                       prev.next = next;\r
-                               return (T)e.value;\r
-                       }\r
-                       prev = e;\r
-                       e = next;\r
-               }\r
-               return null;\r
-       }\r
-\r
-       public void clear () {\r
-               Entry[] table = this.table;\r
-               for (int index = table.length; --index >= 0;)\r
-                       table[index] = null;\r
-               size = 0;\r
-       }\r
-\r
-       /**\r
-        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
-        * items to avoid multiple backing array resizes.\r
-        */\r
-       public void ensureCapacity (int additionalCapacity) {\r
-               int sizeNeeded = size + additionalCapacity;\r
-               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
-       }\r
-\r
-       private void resize (int newSize) {\r
-               Entry[] newTable = new Entry[newSize];\r
-               Entry[] table = this.table;\r
-               int bucketmask = newSize - 1;\r
-               for (int i = 0; i < table.length; i++) {\r
-                       Entry entry = table[i];\r
-                       if (entry != null) {\r
-                               table[i] = null;\r
-                               do {\r
-                                       Entry next = entry.next;\r
-                                       int index = (int)(entry.key & bucketmask);\r
-                                       entry.next = newTable[index];\r
-                                       newTable[index] = entry;\r
-                                       entry = next;\r
-                               } while (entry != null);\r
-                       }\r
-               }\r
-               this.table = newTable;\r
-               capacity = newSize;\r
-               threshold = (int)(newSize * loadFactor);\r
-               mask = capacity - 1;\r
-       }\r
-\r
-       public String toString () {\r
-               if (size == 0) return "[]";\r
-               StringBuilder buffer = new StringBuilder(32);\r
-               buffer.append('[');\r
-               Entry[] table = this.table;\r
-               int i = table.length;\r
-               while (i-- > 0) {\r
-                       Entry e = table[i];\r
-                       if (e == null) continue;\r
-                       buffer.append(e.key);\r
-                       buffer.append('=');\r
-                       buffer.append(e.value);\r
-                       for (e = e.next; e != null; e = e.next) {\r
-                               buffer.append(", ");\r
-                               buffer.append(e.key);\r
-                               buffer.append('=');\r
-                               buffer.append(e.value);\r
-                       }\r
-                       break;\r
-               }\r
-               while (i-- > 0) {\r
-                       for (Entry e = table[i]; e != null; e = e.next) {\r
-                               buffer.append(", ");\r
-                               buffer.append(e.key);\r
-                               buffer.append('=');\r
-                               buffer.append(e.value);\r
-                       }\r
-               }\r
-               buffer.append(']');\r
-               return buffer.toString();\r
-       }\r
-\r
-       class Entries implements Iterator {\r
-               private int index = -1;\r
-               Entry<T> entry = null;\r
-\r
-               public boolean hasNext () {\r
-                       if (entry != null && entry.next != null) {\r
-                               entry = entry.next;\r
-                               return true;\r
-                       }\r
-                       while (true) {\r
-                               index++;\r
-                               if (index >= table.length) return false;\r
-                               if (table[index] == null) continue;\r
-                               entry = table[index];\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-               public Object next () {\r
-                       return entry;\r
-               }\r
-\r
-               public void remove () {\r
-                       Entry prev = table[index];\r
-                       Entry e = prev;\r
-                       while (e != null) {\r
-                               Entry next = e.next;\r
-                               if (e == entry) {\r
-                                       size--;\r
-                                       if (prev == e)\r
-                                               table[index] = next;\r
-                                       else\r
-                                               prev.next = next;\r
-                                       return;\r
-                               }\r
-                               prev = e;\r
-                               e = next;\r
-                       }\r
-               }\r
-\r
-               void reset () {\r
-                       index = -1;\r
-                       entry = null;\r
-               }\r
-       }\r
-\r
-       class Values extends Entries {\r
-               public T next () {\r
-                       return entry.value;\r
-               }\r
-       }\r
-\r
-       class Keys {\r
-               private int index = -1;\r
-               Entry<T> entry = null;\r
-\r
-               public boolean hasNext () {\r
-                       if (entry != null && entry.next != null) {\r
-                               entry = entry.next;\r
-                               return true;\r
-                       }\r
-                       while (true) {\r
-                               index++;\r
-                               if (index >= table.length) return false;\r
-                               if (table[index] == null) continue;\r
-                               entry = table[index];\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-               public long next () {\r
-                       return entry.key;\r
-               }\r
-\r
-               public void remove () {\r
-                       Entry prev = table[index];\r
-                       Entry e = prev;\r
-                       while (e != null) {\r
-                               Entry next = e.next;\r
-                               if (e == entry) {\r
-                                       size--;\r
-                                       if (prev == e)\r
-                                               table[index] = next;\r
-                                       else\r
-                                               prev.next = next;\r
-                                       return;\r
-                               }\r
-                               prev = e;\r
-                               e = next;\r
-                       }\r
-               }\r
-\r
-               void reset () {\r
-                       index = -1;\r
-                       entry = null;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * An entry in the map. The value may be changed directly.\r
-        */\r
-       static public class Entry<T> {\r
-               public final long key;\r
-               public T value;\r
-               Entry next;\r
-\r
-               Entry (long k, T v, Entry n) {\r
-                       key = k;\r
-                       value = v;\r
-                       next = n;\r
-               }\r
-\r
-               public String toString () {\r
-                       return key + "=" + value;\r
-               }\r
-       }\r
-}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/LongMap.java b/gdx/src/com/badlogic/gdx/utils/LongMap.java
new file mode 100644 (file)
index 0000000..8a6c048
--- /dev/null
@@ -0,0 +1,389 @@
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+\r
+/**\r
+ * An unordered map that uses long keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put. This class also avoids the boxing that occurs with HashMap<Long,\r
+ * T>.<br>\r
+ * <br>\r
+ * Warning: Integer.MIN_VALUE cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class LongMap<V> {\r
+       static private final int EXTRA = 4;\r
+       static private final int EMPTY = Integer.MIN_VALUE;\r
+\r
+       public int size;\r
+\r
+       long[] keyTable;\r
+       V[] valueTable;\r
+       private float loadFactor;\r
+       private int mask, capacity, threshold;\r
+       private Entries entries;\r
+       private Values values;\r
+       private Keys keys;\r
+\r
+       public LongMap () {\r
+               this(16, 0.75f);\r
+       }\r
+\r
+       public LongMap (int initialCapacity) {\r
+               this(initialCapacity, 0.75f);\r
+       }\r
+\r
+       public LongMap (int initialCapacity, float loadFactor) {\r
+               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+               this.loadFactor = loadFactor;\r
+               threshold = (int)(capacity * loadFactor);\r
+               keyTable = new long[capacity + EXTRA];\r
+               for (int i = keyTable.length - 1; i >= 0; i--)\r
+                       keyTable[i] = EMPTY;\r
+               valueTable = (V[])new Object[capacity + EXTRA];\r
+               mask = capacity - 1;\r
+       }\r
+\r
+       public V put (long key, V value) {\r
+               long[] keyTable = this.keyTable;\r
+               int index = (int)(key & mask);\r
+               while (true) {\r
+                       long existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY || existingKey == key) break;\r
+                       index++;\r
+               }\r
+               keyTable[index] = key;\r
+               V oldValue = valueTable[index];\r
+               valueTable[index] = value;\r
+               if (size++ >= threshold || keyTable[keyTable.length - 1] != EMPTY) resize(capacity << 1);\r
+               return oldValue;\r
+       }\r
+\r
+       public void putAll (LongMap<V> map) {\r
+               ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+               for (Entry<V> entry : map.entries())\r
+                       put(entry.key, entry.value);\r
+       }\r
+\r
+       public V get (long key) {\r
+               long[] keyTable = this.keyTable;\r
+               int index = (int)(key & mask);\r
+               while (true) {\r
+                       long existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return null;\r
+                       if (existingKey == key) return valueTable[index];\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+        * an expensive operation.\r
+        */\r
+       public boolean containsValue (Object value, boolean identity) {\r
+               V[] valueTable = this.valueTable;\r
+               if (value == null) {\r
+                       long[] keyTable = this.keyTable;\r
+                       for (int i = keyTable.length; i-- > 0;)\r
+                               if (keyTable[i] != EMPTY && valueTable[i] == null) return true;\r
+               } else if (identity) {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (valueTable[i] == value) return true;\r
+               } else {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (value.equals(valueTable[i])) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       public boolean containsKey (long key) {\r
+               long[] keyTable = this.keyTable;\r
+               int index = (int)(key & mask);\r
+               while (true) {\r
+                       long existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return false;\r
+                       if (existingKey == key) return true;\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public V remove (long key) {\r
+               long[] keyTable = this.keyTable;\r
+               int index = (int)(key & mask);\r
+               while (true) {\r
+                       long existingKey = keyTable[index];\r
+                       if (existingKey == EMPTY) return null;\r
+                       if (existingKey == key) {\r
+                               keyTable[index] = EMPTY;\r
+                               V value = valueTable[index];\r
+                               valueTable[index] = null;\r
+                               return value;\r
+                       }\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public void clear () {\r
+               long[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = keyTable.length; i-- > 0;) {\r
+                       if (keyTable[i] != EMPTY) {\r
+                               keyTable[i] = EMPTY;\r
+                               valueTable[i] = null;\r
+                       }\r
+               }\r
+               size = 0;\r
+       }\r
+\r
+       /**\r
+        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+        * items to avoid multiple backing array resizes.\r
+        */\r
+       public void ensureCapacity (int additionalCapacity) {\r
+               int sizeNeeded = size + additionalCapacity;\r
+               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+       }\r
+\r
+       private void resize (int newSize) {\r
+               int newMask = newSize - 1;\r
+               mask = newMask;\r
+               capacity = newSize;\r
+               threshold = (int)(newSize * loadFactor);\r
+\r
+               newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+               long[] newKeyTable = new long[newSize];\r
+               for (int i = newSize - 1; i >= 0; i--)\r
+                       newKeyTable[i] = EMPTY;\r
+               V[] newValueTable = (V[])new Object[newSize];\r
+\r
+               long[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = 0, n = keyTable.length; i < n; i++) {\r
+                       long key = keyTable[i];\r
+                       if (key != EMPTY) {\r
+                               int index = (int)(key & newMask);\r
+                               while (true) {\r
+                                       if (newKeyTable[index] == EMPTY) break;\r
+                                       index++;\r
+                               }\r
+                               if (index == newSize) {\r
+                                       // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+                                       resize(capacity << 1);\r
+                                       return;\r
+                               }\r
+                               newKeyTable[index] = key;\r
+                               newValueTable[index] = valueTable[i];\r
+                       }\r
+               }\r
+               this.keyTable = newKeyTable;\r
+               this.valueTable = newValueTable;\r
+       }\r
+\r
+       public String toString () {\r
+               if (size == 0) return "[]";\r
+               StringBuilder buffer = new StringBuilder(32);\r
+               buffer.append('[');\r
+\r
+               long[] keyTable = this.keyTable;\r
+               int i = keyTable.length;\r
+               while (i-- > 0) {\r
+                       long key = keyTable[i];\r
+                       if (key == EMPTY) continue;\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+                       break;\r
+               }\r
+               while (i-- > 0) {\r
+                       long key = keyTable[i];\r
+                       if (key == EMPTY) continue;\r
+                       buffer.append(", ");\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+               }\r
+               buffer.append(']');\r
+               return buffer.toString();\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+        * time this method is called.\r
+        */\r
+       public Entries<V> entries () {\r
+               if (entries == null)\r
+                       entries = new Entries(this);\r
+               else\r
+                       entries.reset();\r
+               return entries;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Values<V> values () {\r
+               if (values == null)\r
+                       values = new Values(this);\r
+               else\r
+                       values.reset();\r
+               return values;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Keys keys () {\r
+               if (keys == null)\r
+                       keys = new Keys(this);\r
+               else\r
+                       keys.reset();\r
+               return keys;\r
+       }\r
+\r
+       static public class Entry<V> {\r
+               public long key;\r
+               public V value;\r
+\r
+               public String toString () {\r
+                       return key + "=" + value;\r
+               }\r
+       }\r
+\r
+       static public class Entries<V> implements Iterable<Entry<V>>, Iterator<Entry<V>> {\r
+               Entry<V> entry = new Entry();\r
+               int index = -1;\r
+               private final LongMap map;\r
+\r
+               public Entries (LongMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       long[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public Entry<V> next () {\r
+                       entry.key = map.keyTable[index];\r
+                       entry.value = (V)map.valueTable[index];\r
+                       return entry;\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<Entry<V>> iterator () {\r
+                       return this;\r
+               }\r
+       }\r
+\r
+       static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+               int index = -1;\r
+               private final LongMap map;\r
+\r
+               public Values (LongMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       long[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public V next () {\r
+                       return (V)map.valueTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<V> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<V> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+\r
+       static public class Keys {\r
+               int index = -1;\r
+               private final LongMap map;\r
+\r
+               public Keys (LongMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       long[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != EMPTY) return true;\r
+                       return false;\r
+               }\r
+\r
+               public long next () {\r
+                       return map.keyTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = EMPTY;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public LongArray toArray () {\r
+                       LongArray array = new LongArray(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/ObjectMap.java b/gdx/src/com/badlogic/gdx/utils/ObjectMap.java
new file mode 100644 (file)
index 0000000..08ac7b4
--- /dev/null
@@ -0,0 +1,384 @@
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * An unordered map that uses int keys. Uses open addressing and linear probing, which avoids allocation. In contrast,\r
+ * java.util.HashMap uses chained entries and allocates on put.<br>\r
+ * <br>\r
+ * Warning: null cannot be used as a key.\r
+ * @author Nathan Sweet\r
+ */\r
+public class ObjectMap<K, V> {\r
+       static private final int EXTRA = 4;\r
+\r
+       public int size;\r
+\r
+       K[] keyTable;\r
+       V[] valueTable;\r
+       private float loadFactor;\r
+       private int mask, capacity, threshold;\r
+       private Entries entries;\r
+       private Values values;\r
+       private Keys keys;\r
+\r
+       public ObjectMap () {\r
+               this(16, 0.75f);\r
+       }\r
+\r
+       public ObjectMap (int initialCapacity) {\r
+               this(initialCapacity, 0.75f);\r
+       }\r
+\r
+       public ObjectMap (int initialCapacity, float loadFactor) {\r
+               if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large.");\r
+               if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               if (loadFactor <= 0) throw new IllegalArgumentException("initialCapacity must be greater than zero.");\r
+               capacity = MathUtils.nextPowerOfTwo(initialCapacity);\r
+               this.loadFactor = loadFactor;\r
+               threshold = (int)(capacity * loadFactor);\r
+               keyTable = (K[])new Object[capacity + EXTRA];\r
+               valueTable = (V[])new Object[capacity + EXTRA];\r
+               mask = capacity - 1;\r
+       }\r
+\r
+       public V put (K key, V value) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = key.hashCode() & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null || existingKey.equals(key)) break;\r
+                       index++;\r
+               }\r
+               keyTable[index] = key;\r
+               V oldValue = valueTable[index];\r
+               valueTable[index] = value;\r
+               if (size++ >= threshold || keyTable[keyTable.length - 1] != null) resize(capacity << 1);\r
+               return oldValue;\r
+       }\r
+\r
+       public void putAll (ObjectMap<K, V> map) {\r
+               ensureCapacity(map.size); // Conservative in case map has keys already in this map.\r
+               for (Entry<K, V> entry : map.entries())\r
+                       put(entry.key, entry.value);\r
+       }\r
+\r
+       public V get (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = key.hashCode() & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return null;\r
+                       if (existingKey.equals(key)) return valueTable[index];\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be\r
+        * an expensive operation.\r
+        */\r
+       public boolean containsValue (Object value, boolean identity) {\r
+               V[] valueTable = this.valueTable;\r
+               if (value == null) {\r
+                       K[] keyTable = this.keyTable;\r
+                       for (int i = keyTable.length; i-- > 0;)\r
+                               if (keyTable[i] != null && valueTable[i] == null) return true;\r
+               } else if (identity) {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (value.equals(valueTable[i])) return true;\r
+               } else {\r
+                       for (int i = valueTable.length; i-- > 0;)\r
+                               if (value.equals(valueTable[i])) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       public boolean containsKey (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = key.hashCode() & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return false;\r
+                       if (existingKey.equals(key)) return true;\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public V remove (K key) {\r
+               K[] keyTable = this.keyTable;\r
+               int index = key.hashCode() & mask;\r
+               while (true) {\r
+                       K existingKey = keyTable[index];\r
+                       if (existingKey == null) return null;\r
+                       if (existingKey.equals(key)) {\r
+                               keyTable[index] = null;\r
+                               V value = valueTable[index];\r
+                               valueTable[index] = null;\r
+                               return value;\r
+                       }\r
+                       index++;\r
+               }\r
+       }\r
+\r
+       public void clear () {\r
+               K[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = keyTable.length; i-- > 0;) {\r
+                       if (keyTable[i] != null) {\r
+                               keyTable[i] = null;\r
+                               valueTable[i] = null;\r
+                       }\r
+               }\r
+               size = 0;\r
+       }\r
+\r
+       /**\r
+        * Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many\r
+        * items to avoid multiple backing array resizes.\r
+        */\r
+       public void ensureCapacity (int additionalCapacity) {\r
+               int sizeNeeded = size + additionalCapacity;\r
+               if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo(sizeNeeded));\r
+       }\r
+\r
+       private void resize (int newSize) {\r
+               int newMask = newSize - 1;\r
+               mask = newMask;\r
+               capacity = newSize;\r
+               threshold = (int)(newSize * loadFactor);\r
+\r
+               newSize += EXTRA; // Allow the last hash bucket to have extra room for linear probing.\r
+               K[] newKeyTable = (K[])new Object[newSize];\r
+               V[] newValueTable = (V[])new Object[newSize];\r
+\r
+               K[] keyTable = this.keyTable;\r
+               V[] valueTable = this.valueTable;\r
+               for (int i = 0, n = keyTable.length; i < n; i++) {\r
+                       K key = keyTable[i];\r
+                       if (key != null) {\r
+                               int index = key.hashCode() & newMask;\r
+                               while (true) {\r
+                                       if (newKeyTable[index] == null) break;\r
+                                       index++;\r
+                               }\r
+                               if (index == newSize) {\r
+                                       // Very unlikely, but possible for the last bucket to have more than EXTRA keys hashed to it.\r
+                                       resize(capacity << 1);\r
+                                       return;\r
+                               }\r
+                               newKeyTable[index] = key;\r
+                               newValueTable[index] = valueTable[i];\r
+                       }\r
+               }\r
+               this.keyTable = newKeyTable;\r
+               this.valueTable = newValueTable;\r
+       }\r
+\r
+       public String toString () {\r
+               if (size == 0) return "[]";\r
+               StringBuilder buffer = new StringBuilder(32);\r
+               buffer.append('[');\r
+\r
+               K[] keyTable = this.keyTable;\r
+               int i = keyTable.length;\r
+               while (i-- > 0) {\r
+                       K key = keyTable[i];\r
+                       if (key == null) continue;\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+                       break;\r
+               }\r
+               while (i-- > 0) {\r
+                       K key = keyTable[i];\r
+                       if (key == null) continue;\r
+                       buffer.append(", ");\r
+                       buffer.append(key);\r
+                       buffer.append('=');\r
+                       buffer.append(valueTable[i]);\r
+               }\r
+               buffer.append(']');\r
+               return buffer.toString();\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is reused each\r
+        * time this method is called.\r
+        */\r
+       public Entries<K, V> entries () {\r
+               if (entries == null)\r
+                       entries = new Entries(this);\r
+               else\r
+                       entries.reset();\r
+               return entries;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Values<V> values () {\r
+               if (values == null)\r
+                       values = new Values(this);\r
+               else\r
+                       values.reset();\r
+               return values;\r
+       }\r
+\r
+       /**\r
+        * Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is reused each time\r
+        * this method is called.\r
+        */\r
+       public Keys<K> keys () {\r
+               if (keys == null)\r
+                       keys = new Keys(this);\r
+               else\r
+                       keys.reset();\r
+               return keys;\r
+       }\r
+\r
+       static public class Entry<K, V> {\r
+               public K key;\r
+               public V value;\r
+\r
+               public String toString () {\r
+                       return key + "=" + value;\r
+               }\r
+       }\r
+\r
+       static public class Entries<K, V> implements Iterable<Entry<K, V>>, Iterator<Entry<K, V>> {\r
+               Entry<K, V> entry = new Entry();\r
+               int index = -1;\r
+               private final ObjectMap map;\r
+\r
+               public Entries (ObjectMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public Entry<K, V> next () {\r
+                       entry.key = (K)map.keyTable[index];\r
+                       entry.value = (V)map.valueTable[index];\r
+                       return entry;\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<Entry<K, V>> iterator () {\r
+                       return this;\r
+               }\r
+       }\r
+\r
+       static public class Values<V> implements Iterable<V>, Iterator<V> {\r
+               int index = -1;\r
+               private final ObjectMap map;\r
+\r
+               public Values (ObjectMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public V next () {\r
+                       return (V)map.valueTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<V> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<V> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+\r
+       static public class Keys<K> implements Iterable<K>, Iterator<K> {\r
+               int index = -1;\r
+               private final ObjectMap map;\r
+\r
+               public Keys (ObjectMap map) {\r
+                       this.map = map;\r
+               }\r
+\r
+               public boolean hasNext () {\r
+                       Object[] keyTable = map.keyTable;\r
+                       for (int n = keyTable.length; ++index < n;)\r
+                               if (keyTable[index] != null) return true;\r
+                       return false;\r
+               }\r
+\r
+               public K next () {\r
+                       return (K)map.keyTable[index];\r
+               }\r
+\r
+               public void remove () {\r
+                       map.keyTable[index] = null;\r
+                       map.valueTable[index] = null;\r
+                       map.size--;\r
+                       index--;\r
+               }\r
+\r
+               public void reset () {\r
+                       index = -1;\r
+               }\r
+\r
+               public Iterator<K> iterator () {\r
+                       return this;\r
+               }\r
+\r
+               public Array<K> toArray () {\r
+                       Array array = new Array(map.size);\r
+                       while (hasNext())\r
+                               array.add(next());\r
+                       return array;\r
+               }\r
+       }\r
+}\r
diff --git a/gdx/src/com/badlogic/gdx/utils/Pool.java b/gdx/src/com/badlogic/gdx/utils/Pool.java
deleted file mode 100644 (file)
index 9e14f67..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*\r
- * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
- * License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
- * governing permissions and limitations under the License.\r
- */\r
-\r
-package com.badlogic.gdx.utils;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-/**\r
- * A pool implementation used for object instances that should get reused instead of being collected by the garbage collector.\r
- * Note that you should not hold on to the references of objects from this Pool once they've been marked as free by calling\r
- * {@link #free(Object)}.\r
- * \r
- * @author mzechner\r
- * \r
- * @param <T> the type\r
- */\r
-@SuppressWarnings("unchecked") public class Pool<T> {\r
-       /**\r
-        * Interface for an Object Factory to be used with this Pool\r
-        * \r
-        * @author mzechner\r
-        * \r
-        * @param <T> the type\r
-        */\r
-       public interface PoolObjectFactory<T> {\r
-               public T createObject ();\r
-       }\r
-\r
-       /** the list of free objects **/\r
-       private final List<T> freeObjects = new ArrayList();\r
-       /** the factory **/\r
-       private final PoolObjectFactory<T> factory;\r
-       /** maximum size of pool **/\r
-       private final int maxSize;\r
-\r
-       public Pool (PoolObjectFactory<T> factory, int maxSize) {\r
-               this.factory = factory;\r
-               this.maxSize = maxSize;\r
-       }\r
-\r
-       /**\r
-        * Creates a new object either by taking it from the free object pool or by creating a new one if there are no free objects\r
-        * yet.\r
-        * \r
-        * @return the object\r
-        */\r
-       public T newObject () {\r
-               T object = null;\r
-\r
-               if (freeObjects.size() == 0)\r
-                       object = factory.createObject();\r
-               else\r
-                       object = freeObjects.remove(freeObjects.size() - 1);\r
-\r
-               return object;\r
-       }\r
-\r
-       /**\r
-        * Frees the given object and returns it to the pool.\r
-        * @param object the object\r
-        */\r
-       public void free (T object) {\r
-               if (freeObjects.size() < maxSize) freeObjects.add(object);\r
-       }\r
-}\r
index 7be5870..455e178 100644 (file)
@@ -13,8 +13,6 @@
 \r
 package com.badlogic.gdx.utils;\r
 \r
-import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
-\r
 /**\r
  * A simple linked list that pools its nodes. This is a highly specialized class used in a couple of 2D scene graph classes. I\r
  * wouldn't use it if i was you :)\r
@@ -35,19 +33,18 @@ public class PooledLinkedList<T> {
        private Item<T> curr;\r
        private int size = 0;\r
 \r
-       private final Pool<Item<T>> pool;\r
+       private final BagPool<Item<T>> pool;\r
 \r
        public PooledLinkedList (int maxPoolSize) {\r
-               this.pool = new Pool<PooledLinkedList.Item<T>>(new PoolObjectFactory<PooledLinkedList.Item<T>>() {\r
-\r
-                       @Override public PooledLinkedList.Item<T> createObject () {\r
+               this.pool = new BagPool<PooledLinkedList.Item<T>>(16, maxPoolSize) {\r
+                       protected Item<T> newObject () {\r
                                return new Item<T>();\r
                        }\r
-               }, maxPoolSize);\r
+               };\r
        }\r
 \r
        public void add (T object) {\r
-               Item<T> item = pool.newObject();\r
+               Item<T> item = pool.add();\r
                item.payload = object;\r
                item.next = null;\r
                item.prev = null;\r
@@ -93,7 +90,7 @@ public class PooledLinkedList<T> {
                if (curr == null) return;\r
 \r
                size--;\r
-               pool.free(curr);\r
+               pool.removeValue(curr, true);\r
 \r
                Item<T> c = curr;\r
                Item<T> n = curr.next;\r
diff --git a/gdx/src/com/badlogic/gdx/utils/Sort.java b/gdx/src/com/badlogic/gdx/utils/Sort.java
new file mode 100644 (file)
index 0000000..d3a52fa
--- /dev/null
@@ -0,0 +1,68 @@
+/*\r
+ * Copyright (C) 2008 The Android Open Source Project\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.util.Comparator;\r
+\r
+/**\r
+ * Provides methods to sort arrays or objects. Sorting requires working memory and this class allows that memory to be reused to\r
+ * avoid allocation. The sorting is otherwise identical to the Arrays.sort methods (uses timsort).<br>\r
+ * <br>\r
+ * Note that sorting primitive arrays with the Arrays.sort methods does not allocate memory (unless sorting large arrays of char,\r
+ * short, or byte).\r
+ */\r
+public class Sort {\r
+       private TimSort timSort;\r
+       private ComparableTimSort comparableTimSort;\r
+\r
+       public <T extends Comparable<T>> void sort (Array<T> a) {\r
+               if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+               comparableTimSort.doSort(a.items, 0, a.size);\r
+       }\r
+\r
+       public <T extends Comparable<T>> void sort (ArrayPool<T> a) {\r
+               if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+               comparableTimSort.doSort(a.items, 0, a.size);\r
+       }\r
+\r
+       public <T extends Comparable<T>> void sort (T[] a) {\r
+               if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+               comparableTimSort.doSort(a, 0, a.length);\r
+       }\r
+\r
+       public <T extends Comparable<T>> void sort (T[] a, int fromIndex, int toIndex) {\r
+               if (comparableTimSort == null) comparableTimSort = new ComparableTimSort();\r
+               comparableTimSort.doSort(a, fromIndex, toIndex);\r
+       }\r
+\r
+       public <T> void sort (Array<T> a, Comparator<T> c) {\r
+               if (timSort == null) timSort = new TimSort();\r
+               timSort.doSort(a.items, c, 0, a.size);\r
+       }\r
+\r
+       public <T> void sort (ArrayPool<T> a, Comparator<T> c) {\r
+               if (timSort == null) timSort = new TimSort();\r
+               timSort.doSort(a.items, c, 0, a.size);\r
+       }\r
+\r
+       public <T> void sort (T[] a, Comparator<T> c) {\r
+               if (timSort == null) timSort = new TimSort();\r
+               timSort.doSort(a, c, 0, a.length);\r
+       }\r
+\r
+       public <T> void sort (T[] a, Comparator<T> c, int fromIndex, int toIndex) {\r
+               if (timSort == null) timSort = new TimSort();\r
+               timSort.doSort(a, c, fromIndex, toIndex);\r
+       }\r
+}\r
index e43d2b8..7d0958f 100644 (file)
@@ -34,7 +34,7 @@ public class AtlasIssueTest extends GdxTest {
                batch = new SpriteBatch();\r
                batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0, 0, 855, 480));\r
                atlas = new TextureAtlas(Gdx.files.internal("data/issue_pack"), Gdx.files.internal("data/"));\r
-               sprite  = atlas.getSprite("map");\r
+               sprite  = atlas.createSprite("map");\r
                font = new BitmapFont(Gdx.files.internal("data/font.fnt"), Gdx.files.internal("data/font.png"), false);\r
                Gdx.gl.glClearColor(0, 1, 0, 1);\r
        }\r
index 9a7f045..01412d9 100644 (file)
@@ -44,7 +44,7 @@ public class FilterPerformanceTest extends GdxTest {
        String[] filterNames = { "nearest", "linear", "nearest mipmap nearest", "linear mipmap nearest", "linear mipmap linear" };\r
        \r
        private void setTextureFilter (int filter) {\r
-               atlas.getRegion("map").getTexture().bind();\r
+               atlas.findRegion("map").getTexture().bind();\r
                Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, filters[filter]);\r
                texture.bind();\r
                Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, filters[filter]);\r
@@ -66,7 +66,7 @@ public class FilterPerformanceTest extends GdxTest {
                setTextureFilter(0);\r
                setModeString();\r
 \r
-               sprite = atlas.getSprite("map");\r
+               sprite = atlas.createSprite("map");\r
                sprite2 = new Sprite(texture, 0, 0, 855, 480);\r
                font = new BitmapFont(Gdx.files.internal("data/font.fnt"), Gdx.files.internal("data/font.png"), false); \r
 \r
index ffb6f67..cd4a709 100644 (file)
@@ -33,21 +33,21 @@ public class TextureAtlasTest extends GdxTest {
 \r
                atlas = new TextureAtlas(Gdx.files.internal("data"));\r
 \r
-               badlogic = atlas.getSprite("badlogicslice");\r
+               badlogic = atlas.createSprite("badlogicslice");\r
                badlogic.setPosition(50, 50);\r
 \r
-               badlogicSmall = atlas.getSprite("badlogicsmall");\r
+               badlogicSmall = atlas.createSprite("badlogicsmall");\r
                badlogicSmall.setPosition(10, 10);\r
                badlogicSmall.flip(true, true);\r
 \r
-               AtlasRegion region = atlas.getRegion("badlogicsmall");\r
+               AtlasRegion region = atlas.findRegion("badlogicsmall");\r
                System.out.println("badlogicSmall original size: " + region.originalWidth + ", " + region.originalHeight);\r
                System.out.println("badlogicSmall packed size: " + region.packedWidth + ", " + region.packedHeight);\r
 \r
-               star = atlas.getSprite("particle-star");\r
+               star = atlas.createSprite("particle-star");\r
                star.setPosition(10, 70);\r
 \r
-               font = new BitmapFont(Gdx.files.internal("data/font.fnt"), atlas.getRegion("font"), false);\r
+               font = new BitmapFont(Gdx.files.internal("data/font.fnt"), atlas.findRegion("font"), false);\r
 \r
                Gdx.gl.glClearColor(0, 1, 0, 1);\r
        }\r