Skip to content

Instantly share code, notes, and snippets.

@Frooxius
Last active July 8, 2018 23:02
Show Gist options
  • Save Frooxius/84938b6c233fdec9030192719b7f0014 to your computer and use it in GitHub Desktop.
Save Frooxius/84938b6c233fdec9030192719b7f0014 to your computer and use it in GitHub Desktop.
Value User Override
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FrooxEngine.CommonAvatar
{
[Category("Users/Common Avatar System")]
public class AvatarUserMeshHider : Component, IAvatarObjectComponent
{
public enum HideMethod
{
ShadowOnly,
Deactivate,
}
public readonly Sync<HideMethod> Method;
public readonly SyncRefList<MeshRenderer> Exclude;
public void Dequipped(AvatarObjectSlot slot)
{
foreach (var renderer in Slot.GetComponentsInChildren<MeshRenderer>(r => !Exclude.Contains(r)))
{
switch (Method.Value)
{
case HideMethod.Deactivate:
renderer.EnabledField.ClearUserOverrides();
break;
case HideMethod.ShadowOnly:
renderer.ShadowCastMode.ClearUserOverrides();
break;
}
}
}
public void Equipped(AvatarObjectSlot slot)
{
var user = slot.Slot.GetComponentInParents<UserRoot>().TargetUser.Target;
foreach(var renderer in Slot.GetComponentsInChildren<MeshRenderer>(r=>!Exclude.Contains(r)))
{
switch(Method.Value)
{
case HideMethod.Deactivate:
renderer.EnabledField.OverrideForUser(user, false);
break;
case HideMethod.ShadowOnly:
renderer.ShadowCastMode.OverrideForUser(user, ShadowCastMode.ShadowOnly);
break;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FrooxEngine
{
public class ValueUserOverride<T> : Component
{
class Override : SyncObject
{
public readonly SyncRef<User> User;
public readonly Sync<T> Value;
}
public readonly FieldDrive<T> Target;
public readonly Sync<T> Default;
readonly SyncList<Override> _overrides;
public void SetOverride(User user, T value)
{
var _override = _overrides.FirstOrDefault(o => o.User.Target == user);
if (_override == null)
{
_override = _overrides.Add();
_override.User.Target = user;
}
_override.Value.Value = value;
}
public void RemoveOverride(User user) => _overrides.RemoveAll(o => o.User.Target == user);
protected override void OnAwake()
{
Target.SetupValueSetHook((field, value) =>
{
var _override = _overrides.FirstOrDefault(o => o.User.Target == World.LocalUser);
if (_override == null)
Default.Value = value;
else
_override.Value.Value = value;
});
}
protected override void OnChanges()
{
if (!Target.IsLinkValid)
return;
var _override = _overrides.FirstOrDefault(o => o.User.Target == World.LocalUser);
if (_override == null)
Target.Target.Value = Default.Value;
else
Target.Target.Value = _override.Value.Value;
}
protected override void OnDestroy()
{
// return field to the default value
if (Target.Target != null)
Target.Target.Value = Default;
}
}
public static class ValueUserOverride
{
public static ValueUserOverride<T> GetUserOverride<T>(this IField<T> field, bool addIfDoesntExist = false)
{
var slot = field.FindNearestParent<Slot>();
var valueOverride = slot.GetComponent<ValueUserOverride<T>>(o => o.Target.Target == field);
if(valueOverride == null && addIfDoesntExist)
{
valueOverride = slot.AttachComponent<ValueUserOverride<T>>();
valueOverride.Target.Target = field;
valueOverride.Default.Value = field.Value;
}
return valueOverride;
}
public static ValueUserOverride<T> OverrideForUser<T>(this IField<T> field, User user, T value)
{
var valueOverride = field.GetUserOverride(true);
valueOverride.SetOverride(user, value);
return valueOverride;
}
public static void ClearUserOverrides<T>(this IField<T> field)
{
var valueOverride = field.GetUserOverride();
valueOverride?.Destroy();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment