10using System.Collections;
11using System.Collections.Generic;
23 public partial class LeapGraphicGroup : ISerializationCallbackReceiver, ILeapInternalGraphicGroup {
25 #region INSPECTOR FIELDS
27 private string _groupName =
default(
string);
30 private RenderingMethodReference _renderingMethod =
new RenderingMethodReference();
33 private FeatureList _features =
new FeatureList();
36 #region PRIVATE VARIABLES
37 [SerializeField, HideInInspector]
38 private LeapGraphicRenderer _renderer;
40 [SerializeField, HideInInspector]
41 private List<LeapGraphic> _graphics =
new List<LeapGraphic>();
43 [SerializeField, HideInInspector]
44 private List<SupportInfo> _supportInfo =
new List<SupportInfo>();
46 [SerializeField, HideInInspector]
47 private bool _addRemoveSupported =
default(
bool);
49 private HashSet<LeapGraphic> _toAttach =
new HashSet<LeapGraphic>();
50 private HashSet<LeapGraphic> _toDetach =
new HashSet<LeapGraphic>();
53 #region PUBLIC RUNTIME API
86 return _renderingMethod.Value;
95 public IList<LeapGraphicFeatureBase>
features {
97 Assert.IsNotNull(_features,
"The feature list of graphic group was null!");
109 Assert.IsNotNull(_graphics,
"The graphic list of graphic group was null!");
121 return _graphics.Count + _toAttach.Count;
131 Assert.IsNotNull(_supportInfo,
"The support info list of graphic group was null!");
132 Assert.AreEqual(_features.Count, _supportInfo.Count,
"The support info list should have the same length as the feature list.");
144 return _addRemoveSupported;
161 Assert.IsNotNull(graphic);
167 if (!addRemoveSupportedOrEditTime()) {
172 if (!Application.isPlaying) {
173 Undo.RecordObject(graphic,
"Added graphic to group");
177 if (_toAttach.Contains(graphic)) {
180 if (_toDetach.Contains(graphic)) {
183 _toDetach.Remove(graphic);
188 if (_graphics.Contains(graphic)) {
193 _graphics.Remove(graphic);
195 Debug.LogWarning(
"Could not add graphic because it was already a part of this group.");
201 if (!Application.isPlaying) {
202 int newIndex = _graphics.Count;
203 _graphics.Add(graphic);
212 if (_renderer.space !=
null) {
213 _renderer.space.RebuildHierarchy();
214 _renderer.space.RecalculateTransformers();
217 _renderer.editor.ScheduleRebuild();
221 if (_toAttach.Contains(graphic)) {
226 _toAttach.Add(graphic);
233 foreach (var graphic
in _graphics) {
235 graphic.OnUpdateAnchor(anchor);
251 Assert.IsNotNull(graphic);
253 if (!addRemoveSupportedOrEditTime()) {
258 if (Application.isPlaying)
261 if (_toDetach.Contains(graphic)) {
264 if (_toAttach.Contains(graphic)) {
267 _toAttach.Remove(graphic);
272 int graphicIndex = _graphics.IndexOf(graphic);
273 if (graphicIndex < 0) {
278 if (!Application.isPlaying) {
279 Undo.RecordObject(graphic,
"Removed graphic from group");
280 Undo.RecordObject(_renderer,
"Removed graphic from group");
283 _graphics.RemoveAt(graphicIndex);
288 if (_renderer.space !=
null) {
289 _renderer.space.RebuildHierarchy();
290 _renderer.space.RecalculateTransformers();
293 _renderer.editor.ScheduleRebuild();
297 if (_toDetach.Contains(graphic)) {
302 _toDetach.Add(graphic);
315 for (
int i = 0; i < _features.Count; i++) {
316 var feature = _features[i];
317 if (!(feature is T))
continue;
318 if (_supportInfo[i].support ==
SupportType.Error)
continue;
328 if (Application.isPlaying)
331 handleRuntimeAddRemove();
334 _renderingMethod.Value.OnUpdateRenderer();
336 foreach (var feature
in _features) {
337 feature.isDirty =
false;
343 foreach (var feature
in _features) {
344 feature.ClearDataObjectReferences();
347 for (
int i = 0; i < _graphics.Count; i++) {
348 var graphic = _graphics[i];
350 EditorUtility.SetDirty(graphic);
351 Undo.RecordObject(graphic,
"modified feature data on graphic.");
354 List<LeapFeatureData> dataList =
new List<LeapFeatureData>();
355 foreach (var feature
in _features) {
356 var dataObj = graphic.featureData.Query().OfType(feature.GetDataObjectType()).FirstOrDefault();
357 if (dataObj !=
null) {
358 graphic.featureData.Remove(dataObj);
360 dataObj = feature.CreateFeatureDataForGraphic(graphic);
362 feature.AddFeatureData(dataObj);
363 dataList.Add(dataObj);
366 graphic.OnAssignFeatureData(dataList);
370 foreach (var feature
in _features) {
371 feature.AssignFeatureReferences();
378 var typeToFeatures =
new Dictionary<Type, List<LeapGraphicFeatureBase>>();
379 foreach (var feature
in _features) {
380 Type featureType = feature.GetType();
381 List<LeapGraphicFeatureBase> list;
382 if (!typeToFeatures.TryGetValue(featureType, out list)) {
383 list =
new List<LeapGraphicFeatureBase>();
384 typeToFeatures[featureType] = list;
390 var featureToInfo =
new Dictionary<LeapGraphicFeatureBase, SupportInfo>();
392 foreach (var pair
in typeToFeatures) {
393 var featureType = pair.Key;
394 var featureList = pair.Value;
397 var castList = Activator.CreateInstance(typeof(List<>).MakeGenericType(featureType)) as IList;
398 foreach (var feature
in featureList) {
399 castList.Add(feature);
403 if (_renderingMethod.Value ==
null)
continue;
406 if (!interfaceType.IsAssignableFrom(_renderingMethod.Value.GetType())) {
407 infoList.FillEach(() =>
SupportInfo.
Error(
"This renderer does not support this feature."));
411 var supportDelegate = interfaceType.GetMethod(
"GetSupportInfo");
413 if (supportDelegate ==
null) {
414 Debug.LogError(
"Could not find support delegate.");
418 supportDelegate.Invoke(_renderingMethod.Value,
new object[] { castList, infoList });
420 for (
int i = 0; i < featureList.Count; i++) {
421 featureToInfo[featureList[i]] = infoList[i];
426 _supportInfo =
new List<SupportInfo>();
427 foreach (var feature
in _features) {
428 _supportInfo.Add(feature.GetSupportInfo(
this).OrWorse(featureToInfo[feature]));
434 #region LIFECYCLE CALLBACKS
440 for (
int i = 0; i < _features.Count; i++) {
441 _features[i].AssignFeatureReferences();
442 _features[i].ClearDataObjectReferences();
443 _features[i].isDirty =
true;
444 foreach (var graphic
in _graphics) {
445 _features[i].AddFeatureData(graphic.featureData[i]);
449 _renderingMethod.Value.OnEnableRenderer();
456 _renderingMethod.Value.OnDisableRenderer();
461 #region PRIVATE IMPLEMENTATION
465 editor =
new EditorApi(
this);
469 private void handleRuntimeAddRemove() {
470 if (_toAttach.Count == 0 && _toDetach.Count == 0) {
475 List<int> dirtyIndexes = Pool<List<int>>.Spawn();
478 var attachEnum = _toAttach.GetEnumerator();
479 var detachEnum = _toDetach.GetEnumerator();
480 bool canAttach = attachEnum.MoveNext();
481 bool canDetach = detachEnum.MoveNext();
485 while (canAttach && canDetach) {
486 int toDetatchIndex = _graphics.IndexOf(detachEnum.Current);
487 _graphics[toDetatchIndex] = attachEnum.Current;
491 detachEnum.Current.OnDetachedFromGroup();
492 attachEnum.Current.OnAttachedToGroup(
this, anchor);
494 dirtyIndexes.Add(toDetatchIndex);
496 canAttach = attachEnum.MoveNext();
497 canDetach = detachEnum.MoveNext();
500 int newGraphicStart = _graphics.Count;
506 _graphics.Add(attachEnum.Current);
507 canAttach = attachEnum.MoveNext();
514 int toDetachIndex = _graphics.IndexOf(detachEnum.Current);
515 dirtyIndexes.Add(toDetachIndex);
517 _graphics[_graphics.Count - 1].isRepresentationDirty =
true;
518 _graphics.RemoveAtUnordered(toDetachIndex);
520 detachEnum.Current.OnDetachedFromGroup();
522 canDetach = detachEnum.MoveNext();
534 for (
int i = newGraphicStart; i < _graphics.Count; i++) {
536 _graphics[i].OnAttachedToGroup(
this, anchor);
539 attachEnum.Dispose();
540 detachEnum.Dispose();
546 for (
int i = dirtyIndexes.Count; i-- != 0;) {
547 if (dirtyIndexes[i] >= _graphics.Count) {
548 dirtyIndexes.RemoveAt(i);
557 foreach (var feature
in _features) {
558 feature.isDirty =
true;
561 (_renderingMethod.Value as ISupportsAddRemove).OnAddRemoveGraphics(dirtyIndexes);
563 dirtyIndexes.Clear();
564 Pool<List<int>>.Recycle(dirtyIndexes);
569 private bool addRemoveSupportedOrEditTime() {
571 if (!Application.isPlaying) {
576 return _addRemoveSupported;
582 if (_renderingMethod.Value ==
null ||
renderer ==
null) {
583 Debug.LogWarning(
"The rendering group did not find the needed data! If you have a variable of type " +
584 "LeapGraphicGroup make sure to annotate it with a [NonSerialized] attribute, or else " +
585 "Unity will automatically create invalid instances of the class.");
588 renderingMethodInternal.
group =
this;
596 LeapRuntimeTintFeature,
597 LeapBlendShapeFeature,
598 CustomFloatChannelFeature,
599 CustomVectorChannelFeature,
600 CustomColorChannelFeature,
601 CustomMatrixChannelFeature> { }
606 LeapTextRenderer> { }
bool addRemoveSupported
Returns whether or not add/remove operations are supported at runtime by this group....
bool TryAddGraphic(LeapGraphic graphic)
Tries to add the given graphic to this group. This can safely be called during runtime or edit time....
void OnEnable()
Specifically called during the OnEnable callback during RUNTIME ONLY
void RebuildFeatureSupportInfo()
List< SupportInfo > supportInfo
Maps 1-to-1 with the feature list, where each element represents the support that feature currently h...
void RefreshGraphicAnchors()
void RebuildFeatureData()
LeapRenderingMethod renderingMethod
Gets the rendering method used for this group. This can only be changed at edit time using either the...
void OnDisable()
Specifically called during the OnDisable callback during RUNTIME ONLY
void OnAfterDeserialize()
int toBeAttachedCount
Returns the total number of graphics that will be part of this group after the next update cycle....
List< LeapGraphic > graphics
Returns the list of graphics attached to this group. This getter returns a regular mutable list for s...
bool TryRemoveGraphic(LeapGraphic graphic)
Tries to remove the given graphic from this group. This can safely be called during runtime or edit t...
LeapGraphicRenderer renderer
Gets the renderer this group is attached to.
bool GetSupportedFeatures< T >(List< T > features)
Fills the argument list with all of the currently supported features of type T. Returns true if there...
IList< LeapGraphicFeatureBase > features
Returns the list of features attached to this group. This can only be changed at edit time using eith...
bool isAttachedToGroup
Returns whether or not this graphic is attached to any group. Can still return false at runtime even ...
bool isRepresentationDirty
An internal flag that returns true if the visual representation of this graphic needs to be updated....
virtual void NotifyWillBeAttached(LeapGraphicGroup toBeAttachedTo)
Called by the system to notify that this graphic will be attached within the next frame....
bool willbeDetached
Returns whether or not this graphic will be detached from a group within the next frame....
virtual void CancelWillBeDetached()
Called by the system to notify that a previous notification that this graphic would be detached has b...
LeapGraphicGroup attachedGroup
Returns the group this graphic is attached to.
virtual void CancelWillBeAttached()
Called by the system to notify that a previous notification that this graphic would be attached has b...
virtual void OnAttachedToGroup(LeapGraphicGroup group, LeapSpaceAnchor anchor)
Called by the system when this graphic is attached to a group. This method is invoked both at runtime...
virtual void OnDetachedFromGroup()
Called by the system when this graphic is detached from a group. This method is invoked both at runti...
virtual void NotifyWillBeDetached(LeapGraphicGroup toBeDetachedFrom)
Called by the system to notify that this graphic will be detached within the next frame....
bool willbeAttached
Returns whether or not this graphic will be attached to a group within the next frame....
LeapSpace space
Returns the leap space that is currently attached to this graphic renderer.
Represents an ordered collection of objects of type BaseType.
Represents a single reference to a value of type BaseType.
static LeapSpaceAnchor GetAnchor(Transform root)
void RecalculateTransformers()
Call to update all transformers in the space. Call this whenever any anchor or parent of an anchor ch...
void RebuildHierarchy()
Call to traverse the entire hierarchy and rebuild the relationship between anchors....
LeapGraphicRenderer renderer
LeapGraphicRenderer renderer
The support info class provides a very basic way to notify that something is fully supported,...
static SupportInfo Error(string message)
Helper getter to return a struct that signifies no support with an error message.
static SupportInfo FullSupport()
Helper getter to return a struct that signifies full support.
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....