Skip to content

Commit

Permalink
Finalized game-UI decoupling:
Browse files Browse the repository at this point in the history
* Cast-spell buttons still access game object directly because at IO time the game is waiting for UI;
* CardIcon addin is re-written so that it accesses an array of counter data from card data.
  • Loading branch information
zeroyao committed Mar 26, 2013
1 parent d2bff80 commit 43c8155
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 110 deletions.
2 changes: 1 addition & 1 deletion trunk/Fountain/Common/StdStructures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace TouhouSpring
{
public interface IIndexable<T> : IEnumerable<T>, IEnumerable
public interface IIndexable<out T> : IEnumerable<T>, IEnumerable
{
T this[int index] { get; }
int Count { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public enum CardLocation
Graveyard
}

public interface ICounterData
{
string Name { get; }
string IconUri { get; }
int Count { get; }
}

public interface ICardData
{
int Guid { get; }
Expand All @@ -36,6 +43,22 @@ public interface ICardData
bool IsAssist { get; }
bool IsAssistActivated { get; }
bool IsInstant { get; }

IIndexable<ICounterData> Counters { get; }
}

private class InternalCounterData : ICounterData
{
public string Name { get; private set; }
public string IconUri { get; private set; }
public int Count { get; private set; }

public InternalCounterData(string name, string iconUri, int count)
{
Name = name;
IconUri = iconUri;
Count = count;
}
}

private class InternalCardData : ICardData
Expand All @@ -56,6 +79,7 @@ private class InternalCardData : ICardData
public bool IsAssist { get; private set; }
public bool IsAssistActivated { get; private set; }
public bool IsInstant { get; private set; }
public IIndexable<ICounterData> Counters { get; private set; }

public InternalCardData(CardInstance card, CardLocation location, int locationIndex)
{
Expand Down Expand Up @@ -83,6 +107,20 @@ public InternalCardData(CardInstance card, CardLocation location, int locationIn
IsAssistActivated = card.IsActivatedAssist;

IsInstant = card.Behaviors.Has<Behaviors.Instant>();

var counters = card.Counters;
var statusEffects = card.Behaviors.OfType<Behaviors.IStatusEffect>();
var counterArray = new InternalCounterData[counters.Count() + statusEffects.Count()];
int i = 0;
foreach (var counter in counters)
{
counterArray[i++] = new InternalCounterData(counter.Text, counter.IconUri, card.GetCounterCount(counter.GetType()));
}
foreach (var statusEffect in statusEffects)
{
counterArray[i++] = new InternalCounterData(statusEffect.Text, statusEffect.IconUri, 0);
}
Counters = counterArray.ToIndexable();
}

public InternalCardData(int ownerPlayerIndex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private void UpdateCardControls(float deltaTime)
cardControl.Addins.Add(new UI.CardControlAddins.Flip(cardControl));
cardControl.Addins.Add(new UI.CardControlAddins.LocationAnimation(cardControl));
cardControl.Addins.Add(new UI.CardControlAddins.ToneAnimation(cardControl));
//cardControl.Addins.Add(new UI.CardControlAddins.CardIcons(cardControl));
cardControl.Addins.Add(new UI.CardControlAddins.CardIcons(cardControl));
m_cardControls.Add(cardControl);

if (cardData.Location == CardDataManager.CardLocation.Hand)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ private void PrepareGameStartupParam()
deck1.Add(cardDb.GetModel("alice_2"));
deck1.Add(cardDb.GetModel("alice_2"));
deck1.Add(cardDb.GetModel("alice_2"));
deck1.Add(cardDb.GetModel("marisa"));
deck1.Add(cardDb.GetModel("marisa"));
deck1.Add(cardDb.GetModel("marisa"));
deck1.Assists.Add(cardDb.GetModel("eirin"));
deck1.Assists.Add(cardDb.GetModel("patchouli"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,19 @@ public void OnCardClicked(UI.CardControl cardControl)
{
m_gameUI.AddContextButton("激活", ContextButton_OnActivate);
}
//if (m_castFromCards.Contains(cardGuid))
//{
// var card = cardControl.Card;
// foreach (var spell in card.Spells.Intersect(m_io.CastSpellCandidates))
// {
// m_gameUI.AddContextButton("施放 " + spell.Model.Name, text =>
// {
// m_io.RespondCast(spell);
// m_gameUI.LeaveState();
// });
// }
//}
if (m_castFromCards.Contains(cardGuid))
{
// its okay to access actual CardInstance here because the game is waiting for UI
var card = m_castFromCards.First(c => c.Guid == cardGuid);
foreach (var spell in card.Spells.Intersect(m_io.CastSpellCandidates))
{
m_gameUI.AddContextButton("施放 " + spell.Model.Name, text =>
{
m_io.RespondCast(spell);
m_gameUI.LeaveState();
});
}
}
if (m_io.SacrificeCandidates.Contains(cardGuid))
{
m_gameUI.AddContextButton("牺牲", ContextButton_OnSacrifice);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@
<Compile Include="UI\CardControl.Binding.cs" />
<Compile Include="UI\CardControl.cs" />
<Compile Include="UI\CardControl.Render.cs" />
<None Include="UI\CardControlAddins\CardIcons.cs" />
<None Include="UI\CardControlAddins\CardIcons.Icon.cs" />
<Compile Include="UI\CardControlAddins\CardIcons.cs" />
<Compile Include="UI\CardControlAddins\CardIcons.Icon.cs" />
<Compile Include="UI\CardControlAddins\InstantRotation.cs" />
<Compile Include="UI\CardControlAddins\DamageIndicator.cs" />
<Compile Include="UI\CardControlAddins\Flip.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ private class Icon : MouseTrackedControl
private Graphics.TexturedQuad m_icon;
private Graphics.TextRenderer.IFormattedText m_counterNumber;

public Behaviors.ICounter Counter;
public Behaviors.IStatusEffect StatusEffect;
public CardInstance Card;
public Services.CardDataManager.ICounterData CounterData;

public Label TextLabel;
public Panel TextPanel;
Expand All @@ -27,8 +25,7 @@ private class Icon : MouseTrackedControl
public void Initialize()
{
Region = new Rectangle(-IconSize / 2, 0, IconSize, IconSize);
string iconUri = Counter != null ? Counter.IconUri : StatusEffect.IconUri;
var texture = GameApp.Service<Services.ResourceManager>().Acquire<Graphics.VirtualTexture>(iconUri);
var texture = GameApp.Service<Services.ResourceManager>().Acquire<Graphics.VirtualTexture>(CounterData.IconUri);
m_icon = new Graphics.TexturedQuad(texture);
}

Expand All @@ -39,10 +36,9 @@ public void ReleaseTexture()

public override void OnMouseEnter(MouseEventArgs e)
{
string text = Counter != null ? Counter.Text : StatusEffect.Text;
if (!String.IsNullOrEmpty(text))
if (!String.IsNullOrEmpty(CounterData.Name))
{
TextLabel.FormattedText = GameApp.Service<Graphics.TextRenderer>().FormatText(text, LabelTextFormatOptions);
TextLabel.FormattedText = GameApp.Service<Graphics.TextRenderer>().FormatText(CounterData.Name, LabelTextFormatOptions);
var world2D = GameApp.Service<Services.GameUI>().InGameUIPage.Style.ChildIds["World2D"].Target;
var transform = TransformNode.GetTransformBetween(this, world2D);
var pt1 = transform.TransformCoord(new Vector3(0, 0, 0));
Expand Down Expand Up @@ -70,21 +66,16 @@ public override void OnMouseLeave(MouseEventArgs e)

public void UpdateCounter()
{
if (Counter == null)
{
return;
}

var number = Card.GetCounterCount(Counter.GetType()).ToString();
if (number == "1")
if (CounterData.Count <= 1)
{
m_counterNumber = null;
}
else
{
if (m_counterNumber == null || m_counterNumber.Text != number)
var numStr = CounterData.Count.ToString();
if (m_counterNumber == null || m_counterNumber.Text != numStr)
{
m_counterNumber = GameApp.Service<Graphics.TextRenderer>().FormatText(number, CounterNumberFormatOptions);
m_counterNumber = GameApp.Service<Graphics.TextRenderer>().FormatText(numStr, CounterNumberFormatOptions);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ partial class CardIcons : CardControl.Addin

private struct IconItem
{
public Behaviors.IStatusEffect m_statusEffect;
public Behaviors.ICounter m_counter;
public Services.CardDataManager.ICounterData m_counterData;
public Icon m_ui;

public bool EqualsTo(Services.CardDataManager.ICounterData counter)
{
return m_counterData != null
&& m_counterData.Name == counter.Name
&& m_counterData.IconUri == counter.IconUri;
}
}

private object m_lastCounterArray; // use this to see whether the data is refreshed
private IconItem[] m_icons = new IconItem[MaxIcons];
private Graphics.TextRenderer.FormatOptions m_counterFmtOptions;
private Graphics.TextRenderer.FormatOptions m_textFmtOptions;
Expand All @@ -39,93 +46,64 @@ public CardIcons(CardControl control)

public override void Update(float deltaTime)
{
var counters = Card.Counters.Take(MaxIcons).ToList();
var statusEffectBhvs = Card.Behaviors.OfType<Behaviors.IStatusEffect>().Take(MaxIcons - counters.Count).ToList();

IconItem[] newArray = new IconItem[MaxIcons];
int newIndex = 0;
for (int i = 0; i < counters.Count; ++i)
if (m_lastCounterArray != CardData.Counters)
{
var counter = counters[i];
int oldIndex = m_icons.FindIndex(item => item.m_counter == counter);
if (oldIndex >= 0)
{
newArray[newIndex] = m_icons[oldIndex];
newArray[newIndex++].m_ui.Dispatcher = null;
m_icons[oldIndex].m_counter = null;
}
else
IconItem[] newArray = new IconItem[MaxIcons];
int newIndex = 0;
for (int i = 0; i < Math.Min(CardData.Counters.Count, MaxIcons); ++i)
{
newArray[newIndex].m_counter = counter;
newArray[newIndex].m_ui = new Icon
var counter = CardData.Counters[i];
int oldIndex = m_icons.FindIndex(item => item.EqualsTo(counter));
if (oldIndex >= 0)
{
Counter = counter,
Card = Card,
TextLabel = m_label,
TextPanel = m_labelPanel,
CounterNumberColor = Color.White,
CounterNumberFormatOptions = m_counterFmtOptions,
LabelTextFormatOptions = m_textFmtOptions
};
newArray[newIndex++].m_ui.Initialize();
}
}
for (int i = 0; i < statusEffectBhvs.Count; ++i)
{
var bhv = statusEffectBhvs[i];
int oldIndex = m_icons.FindIndex(item => item.m_statusEffect == bhv);
if (oldIndex >= 0)
{
newArray[newIndex] = m_icons[oldIndex];
newArray[newIndex++].m_ui.Dispatcher = null;
m_icons[oldIndex].m_statusEffect = null;
}
else
{
newArray[newIndex].m_statusEffect = bhv;
newArray[newIndex].m_ui = new Icon
newArray[newIndex] = m_icons[oldIndex];
newArray[newIndex].m_counterData = counter;
newArray[newIndex].m_ui.CounterData = counter;
newArray[newIndex++].m_ui.Dispatcher = null;
m_icons[oldIndex].m_counterData = null;
}
else
{
StatusEffect = bhv,
Card = (bhv as Behaviors.IBehavior).Host,
TextLabel = m_label,
TextPanel = m_labelPanel,
CounterNumberColor = Color.White,
CounterNumberFormatOptions = m_counterFmtOptions,
LabelTextFormatOptions = m_textFmtOptions
};
newArray[newIndex++].m_ui.Initialize();
newArray[newIndex].m_counterData = counter;
newArray[newIndex].m_ui = new Icon
{
CounterData = counter,
TextLabel = m_label,
TextPanel = m_labelPanel,
CounterNumberColor = Color.White,
CounterNumberFormatOptions = m_counterFmtOptions,
LabelTextFormatOptions = m_textFmtOptions
};
newArray[newIndex++].m_ui.Initialize();
}
}
}

foreach (var oldItem in m_icons)
{
if (oldItem.m_counter != null || oldItem.m_statusEffect != null)

foreach (var oldItem in m_icons)
{
oldItem.m_ui.ReleaseTexture();
oldItem.m_ui.Dispatcher = null;
if (oldItem.m_counterData != null)
{
oldItem.m_ui.ReleaseTexture();
oldItem.m_ui.Dispatcher = null;
}
}
}

var fromY = (Control.Region.Height - (IconSize + Interval) * MaxIcons + Interval) / 2;
for (int i = 0; i < newArray.Length; ++i)
{
var newItem = newArray[i];
if (newItem.m_ui != null)
var fromY = (Control.Region.Height - (IconSize + Interval) * MaxIcons + Interval) / 2;
for (int i = 0; i < newArray.Length; ++i)
{
newItem.m_ui.Transform = MatrixHelper.Translate(0, fromY + i * (IconSize + Interval), 0);
newItem.m_ui.Dispatcher = Control.BodyContainer;
newItem.m_ui.UpdateCounter();
var newItem = newArray[i];
if (newItem.m_ui != null)
{
newItem.m_ui.Transform = MatrixHelper.Translate(0, fromY + i * (IconSize + Interval), 0);
newItem.m_ui.Dispatcher = Control.BodyContainer;
newItem.m_ui.UpdateCounter();
}
}
m_icons = newArray;
m_lastCounterArray = CardData.Counters;
}
m_icons = newArray;

m_label.Dispatcher = null;
m_labelPanel.Dispatcher = null;
if (m_label.FormattedText != null)
{
m_labelPanel.Dispatcher = GameApp.Service<Services.GameUI>().InGameUIPage.Style.ChildIds["World2D"].Target;
m_label.Dispatcher = GameApp.Service<Services.GameUI>().InGameUIPage.Style.ChildIds["World2D"].Target;
}
m_labelPanel.Dispatcher = m_label.FormattedText != null ? GameApp.Service<Services.GameUI>().InGameUIPage.Style.ChildIds["World2D"].Target : null;
m_label.Dispatcher = m_label.FormattedText != null ? GameApp.Service<Services.GameUI>().InGameUIPage.Style.ChildIds["World2D"].Target : null;
}

public override void RenderPostMain(Matrix transform, RenderEventArgs e)
Expand Down

0 comments on commit 43c8155

Please sign in to comment.