Created
August 17, 2020 09:07
-
-
Save retasretas/9bc7368e5d814088baa1728e80882e4e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
namespace Sirenix.OdinInspector.Demos.RPGEditor | |
{ | |
public class ConsumableItem : Item | |
{ | |
[SuffixLabel("seconds ", true)] | |
[BoxGroup(STATS_BOX_GROUP)] | |
public float Cooldown; | |
[HorizontalGroup(STATS_BOX_GROUP + "/Dur")] | |
public bool ConsumeOverTime; | |
[HideLabel] | |
[HorizontalGroup(STATS_BOX_GROUP + "/Dur")] | |
[SuffixLabel("seconds ", true), EnableIf("ConsumeOverTime")] | |
[LabelWidth(20)] | |
public float Duration; | |
[VerticalGroup(LEFT_VERTICAL_GROUP)] | |
public StatList Modifiers; // <<--------------- ここで使われる | |
public override ItemTypes[] SupportedItemTypes | |
{ | |
get | |
{ | |
return new ItemTypes[] | |
{ | |
ItemTypes.Consumable, | |
ItemTypes.Flask | |
}; | |
} | |
} | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
namespace Sirenix.OdinInspector.Demos.RPGEditor | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using Sirenix.OdinInspector.Editor; | |
using Sirenix.Utilities; | |
using System.Collections; | |
#endif | |
// | |
// The StatList is a dictionary-like list of StatValues, which holds a StatType and a value. | |
// This could be used by many things throughout the system. In this case, StatLists are used | |
// by the Character and items to define requirements and modifiers. But one could imagine | |
// that many things in a game could have StatLists. | |
// | |
// The reason for it being a list instead of a dictioanry is, that most often StatLists doesn't | |
// contain very many stats. For instance, a shield might add some defences, and a few other random bonuses, | |
// and iterating over a dozen values, is actually faster than making a dictionary lookup if optimized. | |
// | |
// The StatList is then customized with the ValueDropdown attribute, where we override how elements | |
// are added and provide the user with a list of types to choose from using OdinSelectors. | |
// Checkout the CustomAddStatsButton at the bottom of this script. | |
// | |
[Serializable] | |
public class StatList | |
{ | |
[SerializeField] | |
[ValueDropdown("CustomAddStatsButton", IsUniqueList = true, DrawDropdownForListElements = false, DropdownTitle = "Modify Stats")] | |
[ListDrawerSettings(DraggableItems = false, Expanded = true)] | |
private List<StatValue> stats = new List<StatValue>(); | |
public StatValue this[int index] | |
{ | |
get { return this.stats[index]; } | |
set { this.stats[index] = value; } | |
} | |
public int Count | |
{ | |
get { return this.stats.Count; } | |
} | |
public float this[StatType type] | |
{ | |
get | |
{ | |
for (int i = 0; i < this.stats.Count; i++) | |
{ | |
if (this.stats[i].Type == type) | |
{ | |
return this.stats[i].Value; | |
} | |
} | |
return 0; | |
} | |
set | |
{ | |
for (int i = 0; i < this.stats.Count; i++) | |
{ | |
if (this.stats[i].Type == type) | |
{ | |
var val = this.stats[i]; | |
val.Value = value; | |
this.stats[i] = val; | |
return; | |
} | |
} | |
this.stats.Add(new StatValue(type, value)); | |
} | |
} | |
#if UNITY_EDITOR | |
// Finds all available stat-types and excludes the types that the statList already contains, so we don't get multiple entries of the same type. | |
private IEnumerable CustomAddStatsButton() | |
{ | |
return Enum.GetValues(typeof(StatType)).Cast<StatType>() | |
.Except(this.stats.Select(x => x.Type)) | |
.Select(x => new StatValue(x)) | |
.AppendWith(this.stats) | |
.Select(x => new ValueDropdownItem(x.Type.ToString(), x)); | |
} | |
#endif | |
} | |
#if UNITY_EDITOR | |
// | |
// Since the StatList is just a class that contains a list, all StatLists would contain an extra | |
// label with a foldout in the inspector, which we don't want. | |
// | |
// So with this drawer, we simply take the label of the member that holds the StatsList, and render the | |
// actual list using that label. | |
// | |
// So instead of the "private List<StatValue> stats" field getting a label named "Stats" | |
// It now gets the label of whatever member holds the actual StatsList | |
// | |
// If this confuses you, try out commenting the drawer below, and take a look at an item in the RPGEditor to see | |
// the difference. | |
// | |
internal class StatListValueDrawer : OdinValueDrawer<StatList> | |
{ | |
protected override void DrawPropertyLayout(GUIContent label) | |
{ | |
// This would be the "private List<StatValue> stats" field. | |
this.Property.Children[0].Draw(label); | |
} | |
} | |
#endif | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
namespace Sirenix.OdinInspector.Demos.RPGEditor | |
{ | |
public enum StatType | |
{ | |
Shooting, | |
Melee, | |
Social, | |
Animals, | |
Medicine, | |
Cooking, | |
Mining, | |
Crafting | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
namespace Sirenix.OdinInspector.Demos.RPGEditor | |
{ | |
using System; | |
using UnityEngine; | |
// | |
// These StatValues are used by StatLists, and are setup so the StatType cannot be changed after it has been added to the list. | |
// This is done by giving the Type a HideInInspector attribute, and we then rename the Value label to be the name of the type, | |
// and set the LabelWidth to make it a bit more compact. | |
// | |
[Serializable] | |
public struct StatValue : IEquatable<StatValue> | |
{ | |
[HideInInspector] | |
public StatType Type; | |
[Range(-100, 100)] | |
[LabelWidth(70)] | |
[LabelText("$Type")] | |
public float Value; | |
public StatValue(StatType type, float value) | |
{ | |
this.Type = type; | |
this.Value = value; | |
} | |
public StatValue(StatType type) | |
{ | |
this.Type = type; | |
this.Value = 0; | |
} | |
public bool Equals(StatValue other) | |
{ | |
return this.Type == other.Type && this.Value == other.Value; | |
} | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment