]> www.infradead.org Git - users/mchehab/andors-trail.git/commitdiff
WIP display duration & magnitude on condition icons.
authorOskar Wiksten <oskar.wiksten@gmail.com>
Sat, 28 Jul 2012 19:51:35 +0000 (21:51 +0200)
committerOskar Wiksten <oskar.wiksten@gmail.com>
Sun, 7 Oct 2012 14:25:36 +0000 (16:25 +0200)
13 files changed:
AndorsTrail/res/anim/scalebeat.xml [new file with mode: 0644]
AndorsTrail/res/anim/scaledown.xml [new file with mode: 0644]
AndorsTrail/res/anim/scaleup.xml [new file with mode: 0644]
AndorsTrail/res/layout/main.xml
AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorCondition.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Actor.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListener.java [new file with mode: 0644]
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java [new file with mode: 0644]
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java [new file with mode: 0644]
AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java [new file with mode: 0644]
AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/StatusView.java

diff --git a/AndorsTrail/res/anim/scalebeat.xml b/AndorsTrail/res/anim/scalebeat.xml
new file mode 100644 (file)
index 0000000..3471f26
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<set
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       >
+
+       <scale
+               android:fromXScale="1.0"
+               android:fromYScale="1.0"
+               android:toXScale="1.1"
+               android:toYScale="1.1" 
+               android:duration="100"
+               android:pivotX="50%"
+               android:pivotY="50%"
+               android:interpolator="@android:anim/decelerate_interpolator"
+               />
+       <scale
+               android:fromXScale="1.1"
+               android:fromYScale="1.1"
+               android:toXScale="1.0"
+               android:toYScale="1.0" 
+               android:duration="100"
+               android:startOffset="100"
+               android:pivotX="50%"
+               android:pivotY="50%"
+               android:interpolator="@android:anim/accelerate_interpolator"
+               />
+</set>
diff --git a/AndorsTrail/res/anim/scaledown.xml b/AndorsTrail/res/anim/scaledown.xml
new file mode 100644 (file)
index 0000000..0c15c5a
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scale
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:interpolator="@android:anim/accelerate_interpolator"
+       android:fromXScale="1.0"
+       android:fromYScale="1.0"
+       android:toXScale="0.0"
+       android:toYScale="0.0" 
+       android:duration="300"
+       android:pivotX="50%"
+       android:pivotY="50%"
+       />
diff --git a/AndorsTrail/res/anim/scaleup.xml b/AndorsTrail/res/anim/scaleup.xml
new file mode 100644 (file)
index 0000000..138d2a3
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<scale
+       xmlns:android="http://schemas.android.com/apk/res/android"
+       android:interpolator="@android:anim/overshoot_interpolator"
+       android:fromXScale="0.0"
+       android:fromYScale="0.0"
+       android:toXScale="1.0"
+       android:toYScale="1.0" 
+       android:duration="200"
+       android:pivotX="50%"
+       android:pivotY="50%"
+       />
index fb98625f932a505b4eaff1b9896752cea2bf7151..9be5d0193f8831cbcc0ad34153d891871cdd67da 100644 (file)
                android:shadowColor="#000"      
                />
        
-       <LinearLayout 
+       <RelativeLayout 
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_above="@id/main_statusview"
                android:layout_margin="5dp"
                android:id="@+id/statusview_activeconditions"
-               android:orientation="horizontal"
                android:gravity="right"
                />
 
index badc06f6a2f1ec0a1e606cec311c55488cbebed2..5e0384a1c3094bb653e0c312a3353a6718774015 100644 (file)
@@ -16,6 +16,7 @@ import com.gpl.rpg.AndorsTrail.model.actor.Player;
 import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry;
 import com.gpl.rpg.AndorsTrail.util.Coord;
 import com.gpl.rpg.AndorsTrail.view.CombatView;
+import com.gpl.rpg.AndorsTrail.view.DisplayActiveActorConditionIcons;
 import com.gpl.rpg.AndorsTrail.view.MainView;
 import com.gpl.rpg.AndorsTrail.view.VirtualDpadView;
 import com.gpl.rpg.AndorsTrail.view.QuickButton.QuickButtonContextMenuInfo;
@@ -33,7 +34,7 @@ import android.view.View;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem.OnMenuItemClickListener;
 import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -59,7 +60,7 @@ public final class MainActivity extends Activity {
     public StatusView statusview;
     public CombatView combatview;
     public QuickitemView quickitemview;
-    private LinearLayout activeConditions;
+    private DisplayActiveActorConditionIcons activeConditions;
     private VirtualDpadView dpad;
        
        private static final int NUM_MESSAGES = 3;
@@ -84,7 +85,7 @@ public final class MainActivity extends Activity {
         statusview = (StatusView) findViewById(R.id.main_statusview);
         combatview = (CombatView) findViewById(R.id.main_combatview);
         quickitemview = (QuickitemView) findViewById(R.id.main_quickitemview);
-        activeConditions = (LinearLayout) findViewById(R.id.statusview_activeconditions);
+        activeConditions = new DisplayActiveActorConditionIcons(world.tileManager, this, (RelativeLayout) findViewById(R.id.statusview_activeconditions));
         dpad = (VirtualDpadView) findViewById(R.id.main_virtual_dpad);
         
                statusText = (TextView) findViewById(R.id.statusview_statustext);
@@ -165,6 +166,8 @@ public final class MainActivity extends Activity {
         view.gameRoundController.pause();
         view.movementController.stopMovement();
         
+        activeConditions.unsubscribe(world);
+        
         save(Savegames.SLOT_QUICKSAVE);
     }
     
@@ -173,6 +176,8 @@ public final class MainActivity extends Activity {
         super.onResume();
         if (!AndorsTrailApplication.getApplicationFromActivity(this).setup.isSceneReady) return;
 
+        activeConditions.subscribe(world);
+        
         view.gameRoundController.resume();
         
                if (world.model.uiSelections.isInCombat) {
@@ -257,7 +262,6 @@ public final class MainActivity extends Activity {
        
        public void updateStatus() {
                statusview.updateStatus();
-               statusview.updateActiveConditions(this, activeConditions);
                quickitemview.refreshQuickitems();
                combatview.updateStatus();
        }
index 0d53eab0efb9e5fc32e9b5ec1d0d2be695c12625..8937faaafa3dbbfc22ecc2d8fc94bd6b93e4be4c 100644 (file)
@@ -59,10 +59,12 @@ public class ActorStatsController {
                        if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
                        if (c.duration != duration) continue;
                        
-                       actor.conditions.remove(i);
-                       magnitude = c.magnitude - magnitude;
-                       if (magnitude > 0) {
-                               actor.conditions.add(new ActorCondition(type, magnitude, duration));
+                       if (c.magnitude > magnitude) {
+                               c.magnitude -= magnitude;
+                               actor.conditionListener.onActorConditionMagnitudeChanged(actor, c);
+                       } else {
+                               actor.conditions.remove(i);
+                               actor.conditionListener.onActorConditionRemoved(actor, c);
                        }
                        break;
                }
@@ -109,12 +111,14 @@ public class ActorStatsController {
                        if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
                        if (c.duration == duration) {
                                // If the actor already has a condition of this type and the same duration, just increase the magnitude instead.
-                               actor.conditions.remove(i);
-                               magnitude += c.magnitude;
-                               break;
+                               c.magnitude += magnitude;
+                               actor.conditionListener.onActorConditionMagnitudeChanged(actor, c);
+                               return;
                        }
                }
-               actor.conditions.add(new ActorCondition(type, magnitude, duration));
+               ActorCondition c = new ActorCondition(type, magnitude, duration);
+               actor.conditions.add(c);
+               actor.conditionListener.onActorConditionAdded(actor, c);
        }
        private static void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) {
                final ActorConditionType type = e.conditionType;
@@ -123,24 +127,34 @@ public class ActorStatsController {
                        ActorCondition c = actor.conditions.get(i);
                        if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
                        if (c.magnitude > e.magnitude) return;
+                       else if (c.magnitude == e.magnitude) {
+                               if (c.duration >= duration) return;
+                       }
                        // If the actor already has this condition, but of a lower magnitude, we remove the old one and add this higher magnitude.
                        actor.conditions.remove(i);
+                       actor.conditionListener.onActorConditionRemoved(actor, c);
                }
-               actor.conditions.add(e.createCondition(duration));
+               
+               ActorCondition c = e.createCondition(duration);
+               actor.conditions.add(c);
+               actor.conditionListener.onActorConditionAdded(actor, c);
        }
 
        public static void removeAllTemporaryConditions(final Actor actor) {
                for(int i = actor.conditions.size() - 1; i >= 0; --i) {
-                       if (!actor.conditions.get(i).isTemporaryEffect()) continue;
+                       ActorCondition c = actor.conditions.get(i);
+                       if (!c.isTemporaryEffect()) continue;
                        actor.conditions.remove(i);
+                       actor.conditionListener.onActorConditionRemoved(actor, c);
                }
        }
        
        private static void removeAllConditionsOfType(final Actor actor, final String conditionTypeID) {
                for(int i = actor.conditions.size() - 1; i >= 0; --i) {
-                       if (actor.conditions.get(i).conditionType.conditionTypeID.equals(conditionTypeID)) {
-                               actor.conditions.remove(i);
-                       }
+                       ActorCondition c = actor.conditions.get(i);
+                       if (!c.conditionType.conditionTypeID.equals(conditionTypeID)) continue;
+                       actor.conditions.remove(i);
+                       actor.conditionListener.onActorConditionRemoved(actor, c);
                }
        }
        
@@ -210,10 +224,13 @@ public class ActorStatsController {
                if (SkillController.rollForSkillChance(player, SkillCollection.SKILL_REJUVENATION, SkillCollection.PER_SKILLPOINT_INCREASE_REJUVENATION_CHANCE)) {
                        int i = getRandomConditionForRejuvenate(player);
                        if (i >= 0) {
-                               ActorCondition c = player.conditions.remove(i);
+                               ActorCondition c = player.conditions.get(i);
                                if (c.magnitude > 1) {
-                                       int magnitude = c.magnitude - 1;
-                                       player.conditions.add(i, new ActorCondition(c.conditionType, magnitude, c.duration));
+                                       c.magnitude -= 1;
+                                       player.conditionListener.onActorConditionMagnitudeChanged(player, c);
+                               } else {
+                                       player.conditions.remove(i);
+                                       player.conditionListener.onActorConditionRemoved(player, c);
                                }
                                recalculateActorCombatTraits(player);
                        }
@@ -258,6 +275,7 @@ public class ActorStatsController {
                for (ActorCondition c : actor.conditions) {
                        StatsModifierTraits effect = isFullRound ? c.conditionType.statsEffect_everyFullRound : c.conditionType.statsEffect_everyRound;
                        effectToStart = applyStatsModifierEffect(actor, effect, c.magnitude, effectToStart);
+                       if (effect != null) actor.conditionListener.onActorConditionRoundEffectApplied(actor, c);
                }
                startVisualEffect(actor, effectToStart);
        }
@@ -267,10 +285,13 @@ public class ActorStatsController {
                for(int i = actor.conditions.size() - 1; i >= 0; --i) {
                        ActorCondition c = actor.conditions.get(i);
                        if (!c.isTemporaryEffect()) continue;
-                       c.duration -= 1;
-                       if (c.duration <= 0) {
+                       if (c.duration <= 1) {
                                actor.conditions.remove(i);
+                               actor.conditionListener.onActorConditionRemoved(actor, c);
                                removedAnyConditions = true;
+                       } else {
+                               c.duration -= 1;
+                               actor.conditionListener.onActorConditionDurationChanged(actor, c);
                        }
                }
                if (removedAnyConditions) {
index 772a48f4bcfe849554b38f0f9a6377b7f46ad2cf..bb0848e6f96fa6499b31c8b28d9d7f6542b587de 100644 (file)
@@ -11,7 +11,7 @@ public class ActorCondition {
        public static final int DURATION_FOREVER = 999;
        
        public final ActorConditionType conditionType;
-       public final int magnitude;
+       public int magnitude;
        public int duration;
        
        public ActorCondition(ActorConditionType conditionType, int magnitude, int duration) {
index bec0b10359a6aeb0b4d438a1650ab776cf79a343..20efe74904b6b075ce4466bbe2d96901f28a2f21 100644 (file)
@@ -8,6 +8,7 @@ import java.util.ArrayList;
 import com.gpl.rpg.AndorsTrail.context.WorldContext;
 import com.gpl.rpg.AndorsTrail.model.CombatTraits;
 import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
+import com.gpl.rpg.AndorsTrail.model.listeners.ActorConditionListeners;
 import com.gpl.rpg.AndorsTrail.util.Coord;
 import com.gpl.rpg.AndorsTrail.util.CoordRect;
 import com.gpl.rpg.AndorsTrail.util.Range;
@@ -20,6 +21,7 @@ public class Actor {
        public final Coord position;
        public final CoordRect rectPosition;
        public final ArrayList<ActorCondition> conditions = new ArrayList<ActorCondition>();
+       public final ActorConditionListeners conditionListener = new ActorConditionListeners();
        public final boolean isPlayer;
        public final boolean isImmuneToCriticalHits;
        
diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListener.java
new file mode 100644 (file)
index 0000000..6db1770
--- /dev/null
@@ -0,0 +1,12 @@
+package com.gpl.rpg.AndorsTrail.model.listeners;
+
+import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
+import com.gpl.rpg.AndorsTrail.model.actor.Actor;
+
+public interface ActorConditionListener {
+       public void onActorConditionAdded(Actor actor, ActorCondition condition);
+       public void onActorConditionRemoved(Actor actor, ActorCondition condition);
+       public void onActorConditionDurationChanged(Actor actor, ActorCondition condition);
+       public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition);
+       public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition);
+}
diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java
new file mode 100644 (file)
index 0000000..3ea9271
--- /dev/null
@@ -0,0 +1,48 @@
+package com.gpl.rpg.AndorsTrail.model.listeners;
+
+import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
+import com.gpl.rpg.AndorsTrail.model.actor.Actor;
+
+public class ActorConditionListeners extends ListOfListeners<ActorConditionListener> implements ActorConditionListener {
+
+       private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionAdded = new Function2<ActorConditionListener, Actor, ActorCondition>() {
+               @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionAdded(actor, condition); }
+       };
+       private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionRemoved = new Function2<ActorConditionListener, Actor, ActorCondition>() {
+               @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionRemoved(actor, condition); }
+       };
+       private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionDurationChanged = new Function2<ActorConditionListener, Actor, ActorCondition>() {
+               @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionDurationChanged(actor, condition); }
+       };
+       private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionMagnitudeChanged = new Function2<ActorConditionListener, Actor, ActorCondition>() {
+               @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionMagnitudeChanged(actor, condition); }
+       };
+       private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionRoundEffectApplied = new Function2<ActorConditionListener, Actor, ActorCondition>() {
+               @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionRoundEffectApplied(actor, condition); }
+       };
+       
+       @Override
+       public void onActorConditionAdded(Actor actor, ActorCondition condition) {
+               callAllListeners(this.onActorConditionAdded, actor, condition);
+       }
+
+       @Override
+       public void onActorConditionRemoved(Actor actor, ActorCondition condition) {
+               callAllListeners(this.onActorConditionRemoved, actor, condition);
+       }
+
+       @Override
+       public void onActorConditionDurationChanged(Actor actor, ActorCondition condition) {
+               callAllListeners(this.onActorConditionDurationChanged, actor, condition);
+       }
+
+       @Override
+       public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition) {
+               callAllListeners(this.onActorConditionMagnitudeChanged, actor, condition);
+       }
+
+       @Override
+       public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition) {
+               callAllListeners(this.onActorConditionRoundEffectApplied, actor, condition);
+       }
+}
diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java
new file mode 100644 (file)
index 0000000..c51c05f
--- /dev/null
@@ -0,0 +1,52 @@
+package com.gpl.rpg.AndorsTrail.model.listeners;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+public class ListOfListeners<T> {
+       private final ArrayList<WeakReference<T>> listeners = new ArrayList<WeakReference<T>>();
+       
+       public void add(T listener) {
+               listeners.add(new WeakReference<T>(listener));
+       }
+       public void remove(T listenerToRemove) {
+               for (int i = listeners.size()-1; i >= 0; --i) {
+                       T listener = listeners.get(i).get();
+                       if (listener == null || listener == listenerToRemove) {
+                               listeners.remove(i);
+                       }
+               }
+       }
+       
+       protected void callAllListeners(Function<T> e) {
+               for (int i = listeners.size()-1; i >= 0; --i) {
+                       T listener = listeners.get(i).get();
+                       if (listener == null) listeners.remove(i);
+                       else e.call(listener);
+               }
+       }
+       protected <Arg1> void callAllListeners(Function1<T, Arg1> e, Arg1 arg) {
+               for (int i = listeners.size()-1; i >= 0; --i) {
+                       T listener = listeners.get(i).get();
+                       if (listener == null) listeners.remove(i);
+                       else e.call(listener, arg);
+               }
+       }
+       protected <Arg1, Arg2> void callAllListeners(Function2<T, Arg1, Arg2> e, Arg1 arg1, Arg2 arg2) {
+               for (int i = listeners.size()-1; i >= 0; --i) {
+                       T listener = listeners.get(i).get();
+                       if (listener == null) listeners.remove(i);
+                       else e.call(listener, arg1, arg2);
+               }
+       }
+       
+       protected static interface Function<Listener> {
+               public void call(Listener listener);
+       }
+       protected static interface Function1<Listener, Arg1> {
+               public void call(Listener listener, Arg1 arg1);
+       }
+       protected static interface Function2<Listener, Arg1, Arg2> {
+               public void call(Listener listener, Arg1 arg1, Arg2 arg2);
+       }
+}
\ No newline at end of file
diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java
new file mode 100644 (file)
index 0000000..37a30ad
--- /dev/null
@@ -0,0 +1,260 @@
+package com.gpl.rpg.AndorsTrail.view;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.RelativeLayout.LayoutParams;
+
+import com.gpl.rpg.AndorsTrail.R;
+import com.gpl.rpg.AndorsTrail.context.WorldContext;
+import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
+import com.gpl.rpg.AndorsTrail.model.actor.Actor;
+import com.gpl.rpg.AndorsTrail.model.listeners.ActorConditionListener;
+import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
+
+public class DisplayActiveActorConditionIcons implements ActorConditionListener {
+       
+       private final TileManager tileManager;
+       private final RelativeLayout activeConditions;
+       private final ArrayList<ActiveConditionIcon> currentConditionIcons = new ArrayList<ActiveConditionIcon>();
+       private final WeakReference<Context> androidContext;
+       
+       public DisplayActiveActorConditionIcons(final TileManager tileManager, Context androidContext, RelativeLayout activeConditions) {
+               this.tileManager = tileManager;
+               this.androidContext = new WeakReference<Context>(androidContext);
+               this.activeConditions = activeConditions;
+       }
+       
+       private ActiveConditionIcon getIconFor(ActorCondition condition) {
+               for (ActiveConditionIcon icon : currentConditionIcons) {
+                       if (icon.condition == condition) return icon;
+               }
+               return null;
+       }
+       private ActiveConditionIcon getFirstFreeIcon() {
+               for (ActiveConditionIcon icon : currentConditionIcons) {
+                       if (!icon.isVisible()) return icon;
+               }
+               return addNewActiveConditionIcon();
+       }
+       
+       private RelativeLayout.LayoutParams getLayoutParamsForIconIndex(int index) {
+               RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+               layout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+               if (index == 0) {
+                       layout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+               } else {
+                       layout.addRule(RelativeLayout.LEFT_OF, currentConditionIcons.get(index-1).id);
+               }
+               return layout;
+       }
+
+       private ActiveConditionIcon addNewActiveConditionIcon() {
+               int index = currentConditionIcons.size();
+                               
+               ActiveConditionIcon icon = new ActiveConditionIcon(androidContext.get(), index+1);
+               
+               activeConditions.addView(icon.image, getLayoutParamsForIconIndex(index));
+               
+               RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+               layout.addRule(RelativeLayout.ALIGN_RIGHT, icon.id);
+               layout.addRule(RelativeLayout.ALIGN_BOTTOM, icon.id);
+               activeConditions.addView(icon.text, layout);
+               
+               /*
+               layout = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+               layout.addRule(RelativeLayout.ALIGN_RIGHT, icon.image.getId());
+               layout.addRule(RelativeLayout.ALIGN_BOTTOM, icon.image.getId());
+               activeConditions.addView(icon.duration, layout);
+               */
+               
+               currentConditionIcons.add(icon);
+               
+               return icon;
+       }
+
+       private final class ActiveConditionIcon implements AnimationListener {
+               public final int id;
+               public ActorCondition condition;
+               public final ImageView image;
+               public final TextView text;
+               //public final TextView duration;
+               private final Animation onNewIconAnimation;
+               private final Animation onRemovedIconAnimation;
+               private final Animation onAppliedEffectAnimation;
+               
+               public ActiveConditionIcon(Context context, int id) {
+                       this.id = id;
+                       this.image = new ImageView(context);
+                       this.image.setId(id);
+                       this.text = new TextView(context);
+                       this.onNewIconAnimation = AnimationUtils.loadAnimation(context, R.anim.scaleup);
+                       this.onRemovedIconAnimation = AnimationUtils.loadAnimation(context, R.anim.scaledown);
+                       this.onAppliedEffectAnimation = AnimationUtils.loadAnimation(context, R.anim.scalebeat);
+                       this.onRemovedIconAnimation.setAnimationListener(this);
+                       //duration = new TextView(context);
+                       
+                       final Resources res = context.getResources();
+                       
+                       //float textSize = ;
+                       //magnitude.setTextSize(res.getDimension(R.dimen.smalltext));
+                       /*
+                       duration.setTextSize(res.getDimension(R.dimen.smalltext));
+                       
+                       int textColor = res.getColor(android.R.color.white);
+                       int shadowColor = res.getColor(android.R.color.black);
+                       magnitude.setTextColor(textColor);
+                       duration.setTextColor(textColor);
+                       
+                       magnitude.setShadowLayer(1, 1, 1, shadowColor);
+                       duration.setShadowLayer(2, 1, 1, shadowColor);
+                       */
+                       
+                       text.setTextColor(res.getColor(android.R.color.white));
+                       text.setShadowLayer(1, 1, 1, res.getColor(android.R.color.black));
+               }
+               
+               private void setActiveCondition(ActorCondition condition) {
+                       this.condition = condition;
+                       tileManager.setImageViewTile(image, condition.conditionType);
+                       image.setVisibility(View.VISIBLE);
+                       setIconText();
+               }
+
+               public void setIconText() {
+                       boolean showMagnitude = (condition.magnitude != 1);
+                       boolean showDuration = condition.isTemporaryEffect();
+                       if (showMagnitude/* || showDuration*/) {
+                               /*if (showMagnitude && showDuration) {
+                                       icon.text.setText(condition.duration + "x" + condition.magnitude);
+                               } else if (showDuration) {
+                                       icon.text.setText(condition.duration);
+                               } else if (showMagnitude) {
+                                       icon.text.setText("x" + condition.magnitude);
+                               }*/
+                               text.setText(Integer.toString(condition.magnitude));
+                               text.setVisibility(View.VISIBLE);
+                       } else {
+                               text.setVisibility(View.GONE);
+                       }
+                       /*
+                       if (condition.magnitude != 1) {
+                               icon.magnitude.setText(Integer.toString(condition.magnitude));
+                               icon.magnitude.setVisibility(View.VISIBLE);
+                       } else {
+                               icon.magnitude.setVisibility(View.GONE);
+                       }
+                       if (condition.isTemporaryEffect()) {
+                               icon.duration.setText(Integer.toString(condition.duration));
+                               icon.duration.setVisibility(View.VISIBLE);
+                       } else {
+                               icon.duration.setVisibility(View.GONE);
+                       }
+                       */
+               }
+               
+               public void hide(boolean useAnimation) {
+                       if (useAnimation) {
+                               image.startAnimation(onRemovedIconAnimation);
+                       } else {
+                               image.setVisibility(View.GONE);
+                               condition = null;
+                       }
+                       text.setVisibility(View.GONE);
+               }
+               public void show() {
+                       image.startAnimation(onNewIconAnimation);
+                       if (text.getVisibility() == View.VISIBLE) text.startAnimation(onNewIconAnimation);
+               }
+               
+               public void pulseAnimate() {
+                       image.startAnimation(onAppliedEffectAnimation);
+               }
+               
+               public boolean isVisible() {
+                       return condition != null;
+               }
+               
+               @Override
+               public void onAnimationEnd(Animation animation) { 
+                       if (animation == this.onRemovedIconAnimation) {
+                               hide(false);
+                               rearrangeIconsLeftOf(this);
+                       }
+               }
+               
+               @Override public void onAnimationRepeat(Animation animation) { }
+               @Override public void onAnimationStart(Animation animation) { }
+       }
+       
+       protected void rearrangeIconsLeftOf(ActiveConditionIcon icon) {
+               int i = currentConditionIcons.indexOf(icon);
+               currentConditionIcons.remove(i);
+               currentConditionIcons.add(icon);
+               for(; i < currentConditionIcons.size(); ++i) {
+                       ActiveConditionIcon aci = currentConditionIcons.get(i);
+                       aci.image.setLayoutParams(getLayoutParamsForIconIndex(i));
+               }
+       }
+
+       @Override
+       public void onActorConditionAdded(Actor actor, ActorCondition condition) {
+               ActiveConditionIcon icon = getFirstFreeIcon();
+               icon.setActiveCondition(condition);
+               icon.show();
+       }
+
+       @Override
+       public void onActorConditionRemoved(Actor actor, ActorCondition condition) {
+               ActiveConditionIcon icon = getIconFor(condition);
+               if (icon == null) return;
+               icon.hide(true);
+       }
+
+       @Override
+       public void onActorConditionDurationChanged(Actor actor, ActorCondition condition) {
+               ActiveConditionIcon icon = getIconFor(condition);
+               if (icon == null) return;
+               icon.setIconText();
+       }
+
+       @Override
+       public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition) {
+               ActiveConditionIcon icon = getIconFor(condition);
+               if (icon == null) return;
+               icon.setIconText();
+       }
+
+       @Override
+       public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition) {
+               ActiveConditionIcon icon = getIconFor(condition);
+               if (icon == null) return;
+               icon.pulseAnimate();
+       }
+
+       public void unsubscribe(final WorldContext world) {
+               world.model.player.conditionListener.remove(this);
+               hideAllIcons();
+       }
+
+       public void subscribe(final WorldContext world) {
+               hideAllIcons();
+               for (ActorCondition condition : world.model.player.conditions) {
+                       getFirstFreeIcon().setActiveCondition(condition);
+               }
+               world.model.player.conditionListener.add(this);
+       }
+       
+       private void hideAllIcons() {
+               for (ActiveConditionIcon icon : currentConditionIcons) icon.hide(false);
+       }
+}
index c6d0a36a8ca5b1896a0da391aaef013b0f21f93d..f2897c781ab7662ba389a3885ad0e26af747b186 100644 (file)
@@ -6,7 +6,6 @@ import com.gpl.rpg.AndorsTrail.activity.MainActivity;
 import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity;
 import com.gpl.rpg.AndorsTrail.context.ViewContext;
 import com.gpl.rpg.AndorsTrail.context.WorldContext;
-import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
 import com.gpl.rpg.AndorsTrail.model.actor.Player;
 import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
 
@@ -17,8 +16,6 @@ import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.util.AttributeSet;
 import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.ImageButton;
 
@@ -97,15 +94,6 @@ public final class StatusView extends RelativeLayout {
                        world.tileManager.setImageViewTile(heroImage, player);                  
                }
        }
-
-       public void updateActiveConditions(Context androidContext, LinearLayout activeConditions) {
-               GreedyImageViewAppender t = new GreedyImageViewAppender(androidContext, activeConditions);
-               for (ActorCondition condition : player.conditions) {
-                       ImageView iv = t.getNextImage();
-                       world.tileManager.setImageViewTile(iv, condition.conditionType);
-               }
-               t.removeOtherImages();
-       }
        
        public void updateQuickItemImage(boolean visible){
                if(visible){
@@ -114,41 +102,4 @@ public final class StatusView extends RelativeLayout {
                        world.tileManager.setImageViewTileForUIIcon(quickToggle, TileManager.iconID_boxclosed);
                }
        }
-       
-       private static class GreedyImageViewAppender {
-               private final LinearLayout container;
-               private final Context context;
-               private int currentChildIndex = 0;
-               private final int previousChildCount;
-               private final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-               
-               public GreedyImageViewAppender(Context context, LinearLayout container) {
-                       this.container = container;
-                       this.context = context;
-                       this.previousChildCount = container.getChildCount();
-               }
-               public ImageView getNextImage() {
-                       // Since this is called a lot, we do not want to recreate the view objects every time.
-                       // Therefore, we reuse existing ImageView:s if they are present, but just change the image on them.
-                       ImageView iv;
-                       if (currentChildIndex < previousChildCount) {
-                               // There already is a create dimage on this position, reuse it.
-                               iv = (ImageView) container.getChildAt(currentChildIndex);
-                               iv.setVisibility(View.VISIBLE);
-                       } else {
-                               // The player has never had this many conditions, create a new ImageView to hold the condition image.
-                               iv = new ImageView(context);
-                               container.addView(iv, layoutParams);
-                       }
-                       ++currentChildIndex;
-                       return iv;
-               }
-               public void removeOtherImages() {
-                       for(int i = previousChildCount - 1; i >= currentChildIndex; --i) {
-                               //container.removeViewAt(i);
-                               // Don't actually remove them, just hide them (so we won't have to recreate them next time the player get a condition)
-                               container.getChildAt(i).setVisibility(View.GONE);
-                       }
-               }
-       }
 }