Skip to content
This repository has been archived by the owner on Jul 18, 2020. It is now read-only.

Commit

Permalink
#16: Add IBodyPartContainer and UMA implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mysticfall committed Dec 17, 2017
1 parent 908149f commit c33ea8a
Show file tree
Hide file tree
Showing 46 changed files with 479 additions and 160 deletions.
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/CustomizableHumanoid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class CustomizableHumanoid : Humanoid, IMorphable, IClothed
[Inject]
public IMorphSet Morphs { get; }

[Inject]
public IBodyPartContainer BodyParts { get; }

[Inject]
public IClothingContainer Clothings { get; }
}
Expand Down
12 changes: 12 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPart.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Alensia.Core.Common;
using UnityEngine;

namespace Alensia.Core.Character.Morph
{
public abstract class BodyPart : Form, IBodyPart
{
public BodyPartSlot Slot => _slot;

[SerializeField] private BodyPartSlot _slot;
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPart.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Alensia.Core.Collection;
using Alensia.Core.Item;
using Malee;

namespace Alensia.Core.Character.Morph
{
public abstract class BodyPartContainer<TItem, TList> : SlotContainer<BodyPartSlot, IBodyPart, TItem, TList>,
IBodyPartContainer
where TItem : class, IBodyPart
where TList : ReorderableArray<TItem>
{
protected abstract IMorphableRace Race { get; }

public override IDirectory<BodyPartSlot> Slots => Race.BodyPartSlots;
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartContainer.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Alensia.Core.Character.Morph
{
///<summary>
/// Commonly used body part names.
///</summary>
public class BodyPartNames
{
public const string Hair = "Hair";

public const string Skin = "Skin";
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartNames.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartSlot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using Alensia.Core.Common;
using Alensia.Core.Item;
using Malee;

namespace Alensia.Core.Character.Morph
{
[Serializable]
public class BodyPartSlot : Form, ISlot
{
}

[Serializable]
public class BodyPartSlotList : ReorderableArray<BodyPartSlot>
{
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/BodyPartSlot.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IBodyPart.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Alensia.Core.Common;
using Alensia.Core.Item;

namespace Alensia.Core.Character.Morph
{
public interface IBodyPart : IForm, ISlotItem<BodyPartSlot>
{
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IBodyPart.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IBodyPartContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Alensia.Core.Item;

namespace Alensia.Core.Character.Morph
{
public interface IBodyPartContainer : ISlotContainer<BodyPartSlot, IBodyPart>
{
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Assets/Alensia/Core/Character/Morph/IMorphSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Alensia.Core.Character.Morph
{
public interface IMorphSet
{
IRace Race { get; set; }
IMorphableRace Race { get; set; }

Sex Sex { get; set; }

Expand Down
2 changes: 2 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IMorphable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ namespace Alensia.Core.Character.Morph
public interface IMorphable
{
IMorphSet Morphs { get; }

IBodyPartContainer BodyParts { get; }
}
}
9 changes: 9 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IMorphableRace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Alensia.Core.Collection;

namespace Alensia.Core.Character.Morph
{
public interface IMorphableRace : IRace
{
IDirectory<BodyPartSlot> BodyPartSlots { get; }
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/IMorphableRace.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Assets/Alensia/Core/Character/Morph/MorphSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Alensia.Core.Character.Morph
{
public abstract class MorphSet : ManagedMonoBehavior, IMorphSet
{
public IRace Race
public IMorphableRace Race
{
get { return _race.Value; }
set
Expand Down Expand Up @@ -48,7 +48,7 @@ public Sex Sex

private readonly IReactiveProperty<Sex> _sex;

private readonly IReactiveProperty<IRace> _race;
private readonly IReactiveProperty<IMorphableRace> _race;

private readonly IReactiveProperty<IReadOnlyList<IMorph>> _morphs;

Expand All @@ -59,7 +59,7 @@ public Sex Sex
protected MorphSet()
{
_sex = new ReactiveProperty<Sex>();
_race = new ReactiveProperty<IRace>();
_race = new ReactiveProperty<IMorphableRace>();
_morphs = new ReactiveProperty<IReadOnlyList<IMorph>>(
Enumerable.Empty<IMorph>().ToList());

Expand Down Expand Up @@ -103,7 +103,7 @@ protected override void OnDisposed()

protected abstract void ChangeSex(Sex sex);

protected abstract void ChangeRace(IRace race);
protected abstract void ChangeRace(IMorphableRace race);

protected abstract void ApplyMorph(IMorph morph);
}
Expand Down
32 changes: 32 additions & 0 deletions Assets/Alensia/Core/Character/Morph/MorphableRace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using Alensia.Core.Collection;
using Malee;
using UnityEngine;

namespace Alensia.Core.Character.Morph
{
[Serializable]
public class MorphableRace : Race, IMorphableRace
{
public IDirectory<BodyPartSlot> BodyPartSlots
{
get
{
lock (this)
{
if (_bodyPartMap != null) return _bodyPartMap;

_bodyPartMap = new SimpleDirectory<BodyPartSlot>(_bodyPartSlots);

return _bodyPartMap;
}
}
}

[SerializeField, Reorderable] private BodyPartSlotList _bodyPartSlots;

private IDirectory<BodyPartSlot> _bodyPartMap;

private void OnValidate() => _bodyPartMap = null;
}
}
3 changes: 3 additions & 0 deletions Assets/Alensia/Core/Character/Morph/MorphableRace.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 3 additions & 101 deletions Assets/Alensia/Core/Item/ClothingContainer.cs
Original file line number Diff line number Diff line change
@@ -1,114 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Alensia.Core.Character;
using Alensia.Core.Collection;
using Alensia.Core.Common;
using Malee;
using UnityEngine;
using UnityEngine.Assertions;

namespace Alensia.Core.Item
{
public abstract class ClothingContainer<TItem, TList> : ManagedMonoBehavior, IClothingContainer
public abstract class ClothingContainer<TItem, TList> : SlotContainer<ClothingSlot, IClothing, TItem, TList>,
IClothingContainer
where TItem : class, IClothing
where TList : ReorderableArray<TItem>
{
protected abstract IRace Race { get; }

public IDirectory<ClothingSlot> Slots => Race.ClothingSlots;

private IDictionary<string, TItem> _mappings;

[SerializeField, Reorderable] private TList _clothings;

protected override void OnInitialized()
{
base.OnInitialized();

// ReSharper disable once InconsistentlySynchronizedField
_mappings = _clothings
.Where(c => Slots.Contains(c.Slot.Name))
.ToDictionary(i => i.Name);
}

public bool Contains(string key) => _mappings.ContainsKey(key);

public IClothing this[string key]
{
get
{
TItem value;

return _mappings.TryGetValue(key, out value) ? value : null;
}
}

public void Set(IClothing item)
{
Assert.IsNotNull(item, "item != null");

var slot = CheckSlot(item.Slot.Name);
var cloth = CheckItem(item);

lock (_mappings)
{
ApplyClothing(cloth);

_mappings.Add(slot, cloth);
_clothings.Add(cloth);
}
}

public void Remove(string key)
{
Assert.IsNotNull(key, "key != null");

var slot = CheckSlot(key);
var item = this[slot];

if (item == null) return;

lock (_mappings)
{
var cloth = CheckItem(item);

RemoveClothing(cloth);

_mappings.Remove(slot);

var items = _clothings.Where(c => c.Slot.Name == slot).ToList();

items.Reverse();
items.ForEach(i => _clothings.Remove(i));
}
}

protected abstract void ApplyClothing(TItem item);

protected abstract void RemoveClothing(TItem item);

private string CheckSlot(string key)
{
if (!Slots.Contains(key))
{
throw new ArgumentException($"Invalid slot name: '{key}'.");
}

return key;
}

private TItem CheckItem(IClothing item)
{
var cloth = item as TItem;

if (cloth == null)
{
throw new ArgumentException(
$"'{nameof(item)}' is not a valid clothing type.'");
}

return cloth;
}
public override IDirectory<ClothingSlot> Slots => Race.ClothingSlots;
}
}
Loading

0 comments on commit c33ea8a

Please sign in to comment.