-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
- Loading branch information
There are no files selected for viewing
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; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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"; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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> | ||
{ | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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> | ||
{ | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.
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; } | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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; | ||
} | ||
} |