private object GetPropertyValue(object inObj, string fieldName) { System.Type t = inObj.GetType(); //GameObject hack // Due to GameObject.active is obsolete and ativeSelf is read only // Use a hack function to override GameObject's active status. if (t == typeof(GameObject) && fieldName == "m_IsActive") { return(((GameObject)inObj).activeSelf); } object ret = null; // Try search Field first than try property System.Reflection.FieldInfo fieldInfo = t.GetField(fieldName, bindingFlags); if (fieldInfo != null) { ret = fieldInfo.GetValue(inObj); return(ret); } if (t.ToString().Contains("UnityEngine.")) { fieldName = ViewSystemUtilitys.ParseUnityEngineProperty(fieldName); } System.Reflection.PropertyInfo info = t.GetProperty(fieldName, bindingFlags); if (info != null) { ret = info.GetValue(inObj); } //ViewSystemLog.Log($"GetProperty on [{gameObject.name}] Target Object {((UnityEngine.Object)inObj).name} [{t.ToString()}] on [{fieldName}] Value [{ret}]"); return(ret); }
public void SetPropertyValue(object inObj, string fieldName, object newValue) { System.Type t = inObj.GetType(); //GameObject hack // Due to GameObject.active is obsolete and ativeSelf is read only // Use a hack function to override GameObject's active status. if (t == typeof(GameObject) && fieldName == "m_IsActive") { ((GameObject)inObj).SetActive((bool)newValue); return; } // Try search Field first than try property System.Reflection.FieldInfo fieldInfo = t.GetField(fieldName, bindingFlags); if (fieldInfo != null) { fieldInfo.SetValue(inObj, newValue); return; } if (t.ToString().Contains("UnityEngine.")) { fieldName = ViewSystemUtilitys.ParseUnityEngineProperty(fieldName); } System.Reflection.PropertyInfo info = t.GetProperty(fieldName, bindingFlags); if (info != null) { info.SetValue(inObj, newValue); } }
public (string Id, UnityEngine.Object Component) GetCachedComponent(Transform targetTansform, string targetTransformPath, string targetComponentType) { UnityEngine.Object c = null; var id = targetTransformPath + "#" + targetComponentType; if (!cachedComponent.TryGetValue(id, out c)) { if (targetComponentType.Contains("UnityEngine.GameObject")) { c = targetTansform.gameObject; } else { c = ViewSystemUtilitys.GetComponent(targetTansform, targetComponentType); } if (c == null) { ViewSystemLog.LogError($"Target Component cannot be found [{targetComponentType}] on GameObject [{transform.name } / {targetTransformPath}]"); } cachedComponent.Add(id, c); } return(id, c); }
internal void SetEvent(IEnumerable <ViewElementEventData> eventDatas) { currentEventDatas = eventDatas.ToArray(); //Group by Component transform_component_property var groupedEventData = eventDatas.GroupBy(item => item.targetTransformPath + ";" + item.targetComponentType + ";" + item.targetPropertyName); foreach (var item in groupedEventData) { string[] p = item.Key.Split(';'); //p[0] is targetTransformPath Transform targetTansform = GetTransform(p[0]); if (targetTansform == null) { ViewSystemLog.LogError($"Target GameObject cannot be found [{transform.name} / {p[0]}]"); continue; } EventRuntimeDatas eventRuntimeDatas; // Get UnityEvent property instance if (!cachedUnityEvent.TryGetValue(item.Key, out eventRuntimeDatas)) { //p[1] is targetComponentType var result = GetCachedComponent(targetTansform, p[0], p[1]); //p[2] is targetPropertyPath string property = p[2]; if (p[1].Contains("UnityEngine.")) { property = ViewSystemUtilitys.ParseUnityEngineProperty(p[2]); } var unityEvent = (UnityEventBase)GetPropertyValue(result.Component, property); eventRuntimeDatas = new EventRuntimeDatas(unityEvent, (Component)result.Component); cachedUnityEvent.Add(item.Key, eventRuntimeDatas); if (eventRuntimeDatas.unityEvent is UnityEvent events) { events.AddListener(EventHandler); } } currentComponent = eventRuntimeDatas.component; // Usually there is only one event on one Selectable // But the system allow mutil event on one Selectable foreach (var item2 in item) { var id_delegate = item2.scriptName + ";" + item2.methodName; //Try to get the cached openDelegate object first //Or create a new openDelegate if (!cachedDelegate.TryGetValue(id_delegate, out EventDelegate <Component> openDelegate)) { // Get Method Type type = Utility.GetType(item2.scriptName); //MethodInfo method = type.GetMethod(item2.methodName); //The method impletmented Object Component scriptInstance = (Component)FindObjectOfType(type); if (scriptInstance == null) { scriptInstance = GenerateScriptInstance(type); } //Create Open Delegate try { openDelegate = CreateOpenDelegate(item2.methodName, scriptInstance); } catch (Exception ex) { ViewSystemLog.LogError($"Create event delegate faild, make sure the method or the instance is exinst. Exception:{ex.ToString()}", this); } cachedDelegate.Add(id_delegate, openDelegate); } currentEventDelegates.Add(openDelegate); } } }
private void CacheComponent() { if (m_ComponentTreeViewState == null) { m_ComponentTreeViewState = new TreeViewState(); } componentTreeView = new ComponentTreeView( currentSelectGameObject, target, m_ComponentTreeViewState, currentSelectGameObject == target, (a, b) => { return(false); }, () => { }); componentTreeView.OnItemClick += (sp) => { Component c; try { c = (Component)sp.serializedObject.targetObject; } catch { c = ((GameObject)sp.serializedObject.targetObject).transform; } if (sp.propertyType == SerializedPropertyType.Generic) { System.Type parentType = sp.serializedObject.targetObject.GetType(); System.Reflection.FieldInfo fi = parentType.GetField(sp.propertyPath); System.Type propertyType = null; if (fi != null) { propertyType = fi.FieldType; } string propertyName = sp.propertyPath; if (parentType.ToString().Contains("UnityEngine.")) { if (propertyName == "m_Navigation") { var content = new GUIContent("UnityEngine.UI.Navigation is not supported with ViewSystem OverrideSystem"); #if UNITY_2019_1_OR_NEWER editorWindow.ShowNotification(content, toastMessageFadeOutTimt); #else editorWindow.ShowNotification(content); #endif return; } propertyName = ViewSystemUtilitys.ParseUnityEngineProperty(sp.propertyPath); } System.Reflection.PropertyInfo pi = parentType.GetProperty(propertyName); if (pi != null && fi == null) { propertyType = pi.PropertyType; } } else { data.targetTransformPath = AnimationUtility.CalculateTransformPath(c.transform, target.transform); data.targetPropertyName = sp.name; data.targetComponentType = sp.serializedObject.targetObject.GetType().ToString(); data.Value.SetValue(sp); editorWindow.Close(); } sp.serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(currentSelectGameObject); }; }
void OnDestroy() { ViewSystemUtilitys.ClearRectTransformCache(); }
public override IEnumerator LeaveOverlayViewPageBase(ViewSystemUtilitys.OverlayPageStatus overlayPageState, float tweenTimeIfNeed, Action OnComplete, bool ignoreTransition = false, bool ignoreTimeScale = false, bool waitForShowFinish = false) { if (waitForShowFinish && overlayPageState.transition == ViewSystemUtilitys.OverlayPageStatus.Transition.Show) { ViewSystemLog.Log("Leave Overlay Page wait for pervious page"); yield return(new WaitUntil(() => !overlayPageState.IsTransition)); } var currentVe = currentViewPage.viewPageItems.Select(m => m.runtimeViewElement); var currentVs = currentViewState.viewPageItems.Select(m => m.runtimeViewElement); var finishTime = ViewSystemUtilitys.CalculateOnLeaveDuration(overlayPageState.viewPage.viewPageItems.Select(m => m.runtimeViewElement)); overlayPageState.transition = ViewSystemUtilitys.OverlayPageStatus.Transition.Leave; List <ViewPageItem> viewPageItems = new List <ViewPageItem>(); viewPageItems.AddRange(overlayPageState.viewPage.viewPageItems); if (overlayPageState.viewState != null) { viewPageItems.AddRange(overlayPageState.viewState.viewPageItems); } foreach (var item in viewPageItems) { if (item.runtimeViewElement == null) { ViewSystemLog.LogWarning($"ViewElement : {item.viewElement.name} is null in runtime."); continue; } // Unique 的 ViewElement 另外處理借用問題 // 暫時不處理 多個 overlay 之間借用的問題!!! if (item.runtimeViewElement.IsUnique == true && IsPageTransition == false) { if (currentVe.Contains(item.runtimeViewElement)) { //準備自動離場的 ViewElement 目前的頁面正在使用中 所以不要對他操作 try { var vpi = currentViewPage.viewPageItems.FirstOrDefault(m => ReferenceEquals(m.runtimeViewElement, item.runtimeViewElement)); var transformData = vpi.GetCurrentViewElementTransform(breakPointsStatus); if (!string.IsNullOrEmpty(transformData.parentPath)) { vpi.runtimeParent = transformCache.Find(transformData.parentPath); } else { vpi.runtimeParent = currentViewPage.runtimePageRoot; } item.runtimeViewElement.ChangePage(true, vpi.runtimeParent, transformData, item.sortingOrder, tweenTimeIfNeed, 0); ViewSystemLog.LogWarning("ViewElement : " + item.viewElement.name + "Try to back to origin Transfrom parent : " + vpi.runtimeParent.name); } catch { } continue; } if (currentVs.Contains(item.runtimeViewElement)) { //準備自動離場的 ViewElement 目前的頁面正在使用中 所以不要對他操作 try { var vpi = currentViewState.viewPageItems.FirstOrDefault(m => ReferenceEquals(m.runtimeViewElement, item.runtimeViewElement)); var transformData = vpi.GetCurrentViewElementTransform(breakPointsStatus); if (!string.IsNullOrEmpty(transformData.parentPath)) { vpi.runtimeParent = transformCache.Find(transformData.parentPath); } else { vpi.runtimeParent = currentViewPage.runtimePageRoot; } item.runtimeViewElement.ChangePage(true, vpi.runtimeParent, transformData, item.sortingOrder, tweenTimeIfNeed, 0); ViewSystemLog.LogWarning("ViewElement : " + item.runtimeViewElement.name + "Try to back to origin Transfrom parent : " + vpi.runtimeParent.name); } catch { } continue; } } // lastOverlayPageItemDelayOutTimes.TryGetValue(item.runtimeViewElement.name, out float delayOut); item.runtimeViewElement.ChangePage(false, null, null, item.sortingOrder, 0, 0, ignoreTransition); } yield return(runtimePool.RecoveryQueuedViewElement()); //Get Back the Navigation to CurrentPage SetNavigationTarget(currentViewPage); InvokeOnOverlayPageLeave(this, new ViewPageEventArgs(overlayPageState.viewPage, null)); if (ignoreTimeScale) { yield return(Yielders.GetWaitForSecondsRealtime(finishTime)); } else { yield return(Yielders.GetWaitForSeconds(finishTime)); } overlayPageState.IsTransition = false; string OverlayPageStateKey = GetOverlayStateKey(overlayPageState.viewPage); overlayPageStatusDict.Remove(OverlayPageStateKey); OnComplete?.Invoke(); }
public override IEnumerator ShowOverlayViewPageBase(ViewPage vp, bool RePlayOnShowWhileSamePage, Action OnStart, Action OnChanged, Action OnComplete, bool ignoreTimeScale) { // Debug.Log("ShowOverlayViewPageBase " + vp.name); if (vp == null) { ViewSystemLog.Log("ViewPage is null"); yield break; } if (vp.viewPageType != ViewPage.ViewPageType.Overlay) { ViewSystemLog.LogError("ViewPage " + vp.name + " is not an Overlay page"); yield break; } //Prepare runtime page root string viewPageRootName = ViewSystemUtilitys.GetPageRootName(vp); var pageWrapper = ViewSystemUtilitys.CreatePageTransform(viewPageRootName, rootCanvasTransform, vp.canvasSortOrder); if (vp.runtimePageRoot == null) { vp.runtimePageRoot = pageWrapper.rectTransform; } pageWrapper.safePadding.SetPaddingValue(vp.edgeValues); ViewState viewState = null; viewStates.TryGetValue(vp.viewState, out viewState); List <ViewElement> viewElementDoesExitsInNextPage = new List <ViewElement>(); IEnumerable <ViewPageItem> viewItemNextPage = null; IEnumerable <ViewPageItem> viewItemNextState = null; List <ViewPageItem> viewItemForNextPage = new List <ViewPageItem>(); string OverlayPageStateKey = GetOverlayStateKey(vp); bool samePage = false; //檢查是否有同 State 的 Overlay 頁面在場上 if (overlayPageStatusDict.TryGetValue(OverlayPageStateKey, out ViewSystemUtilitys.OverlayPageStatus overlayPageStatus)) { viewItemNextPage = PrepareRuntimeReference(GetAllViewPageItemInViewPage(vp)); //同 OverlayState 的頁面已經在場上,移除不同的部分,然後顯示新加入的部分 if (!string.IsNullOrEmpty(vp.viewState)) { if (overlayPageStatus.viewPage.name != vp.name) { // 同 State 不同 Page 的情況,找到差異的部分 foreach (var item in overlayPageStatus.viewPage.viewPageItems) { if (!vp.viewPageItems.Select(m => m.runtimeViewElement).Contains(item.runtimeViewElement)) { viewElementDoesExitsInNextPage.Add(item.runtimeViewElement); } } overlayPageStatus.viewPage = vp; } } else { //只有 ViewPage 卻還是進來這裡的話代表頁面還在場上 // RePlayOnShowWhileSamePage == false 那就更新數值 所以停掉舊的 Coroutine if (overlayPageStatus.pageChangeCoroutine != null) { StopCoroutine(overlayPageStatus.pageChangeCoroutine); } samePage = true; overlayPageStatus.transition = ViewSystemUtilitys.OverlayPageStatus.Transition.Show; } } else { //同 OverlayState 的頁面還不在場上 新建一個 Status overlayPageStatus = new ViewSystemUtilitys.OverlayPageStatus(); overlayPageStatus.viewPage = vp; overlayPageStatus.viewState = viewState; overlayPageStatus.transition = ViewSystemUtilitys.OverlayPageStatus.Transition.Show; viewItemNextPage = PrepareRuntimeReference(GetAllViewPageItemInViewPage(vp)); // 沒有 viewState 的 Page 不需要處理 viewState 的 runtimeViewElement if (!string.IsNullOrEmpty(vp.viewState)) { // nextViewState = viewStates.SingleOrDefault(m => m.name == vp.viewState); if (viewStates.TryGetValue(vp.viewState, out nextViewState)) { viewItemNextState = GetAllViewPageItemInViewState(nextViewState); viewItemNextState = PrepareRuntimeReference(viewItemNextState); } } overlayPageStatusDict.Add(OverlayPageStateKey, overlayPageStatus); } OnStart?.Invoke(); float onShowTime = ViewSystemUtilitys.CalculateOnShowDuration(viewItemNextPage.Select(m => m.runtimeViewElement)); float onShowDelay = ViewSystemUtilitys.CalculateDelayInTime(viewItemNextPage); //對離場的呼叫改變狀態 foreach (var item in viewElementDoesExitsInNextPage) { Debug.LogWarning($"{item.name} not exsit in next page"); item.ChangePage(false, null, null, 0, 0, 0); } viewItemForNextPage.AddRange(viewItemNextPage); if (viewItemNextState != null) { viewItemForNextPage.AddRange(viewItemNextState); } //對進場的呼叫改變狀態 foreach (var item in viewItemNextPage) { if (RePlayOnShowWhileSamePage && samePage) { item.runtimeViewElement.OnShow(); continue; } //套用複寫值 item.runtimeViewElement.ApplyOverrides(item.overrideDatas); item.runtimeViewElement.ApplyEvent(item.eventDatas); var transformData = item.GetCurrentViewElementTransform(breakPointsStatus); if (!string.IsNullOrEmpty(transformData.parentPath)) { item.runtimeParent = transformCache.Find(transformData.parentPath); } else { item.runtimeParent = vp.runtimePageRoot; } item.runtimeViewElement.ChangePage(true, item.runtimeParent, transformData, item.sortingOrder, item.TweenTime, item.delayIn, reshowIfSamePage: RePlayOnShowWhileSamePage); } SetNavigationTarget(vp); yield return(runtimePool.RecoveryQueuedViewElement()); //Fire the event OnChanged?.Invoke(); InvokeOnOverlayPageShow(this, new ViewPageEventArgs(vp, null)); //當所有表演都結束時 if (ignoreTimeScale) { yield return(Yielders.GetWaitForSecondsRealtime(onShowTime + onShowDelay)); } else { yield return(Yielders.GetWaitForSeconds(onShowTime + onShowDelay)); } overlayPageStatus.IsTransition = false; OnComplete?.Invoke(); }
public override IEnumerator ChangePageBase(string viewPageName, Action OnStart, Action OnChanged, Action OnComplete, bool ignoreTimeScale) { //取得 ViewPage 物件 // ViewPage nextViewPage; //沒有找到 if (!viewPages.TryGetValue(viewPageName, out nextViewPage)) { ViewSystemLog.LogError("No view page match " + viewPageName + " Found"); ChangePageToCoroutine = null; yield break; } if (nextViewPage.viewPageType == ViewPage.ViewPageType.Overlay) { ViewSystemLog.LogWarning("To shown Page is an Overlay ViewPage use ShowOverlayViewPage() instead method \n current version will redirect to this method automatically, but this behaviour may be changed in future release."); ShowOverlayViewPageBase(nextViewPage, true, OnStart, OnChanged, OnComplete, ignoreTimeScale); ChangePageToCoroutine = null; yield break; } //Prepare runtime page root string viewPageRootName = ViewSystemUtilitys.GetPageRootName(nextViewPage); var pageWrapper = ViewSystemUtilitys.CreatePageTransform(viewPageRootName, rootCanvasTransform, nextViewPage.canvasSortOrder); if (nextViewPage.runtimePageRoot == null) { nextViewPage.runtimePageRoot = pageWrapper.rectTransform; } pageWrapper.safePadding.SetPaddingValue(nextViewPage.edgeValues); //所有檢查都通過開始換頁 //IsPageTransition = true; nextViewState = null; viewStates.TryGetValue(nextViewPage.viewState, out nextViewState); IEnumerable <ViewPageItem> viewItemNextPage = PrepareRuntimeReference(GetAllViewPageItemInViewPage(nextViewPage)); IEnumerable <ViewPageItem> viewItemNextState = GetAllViewPageItemInViewState(nextViewState); List <ViewPageItem> viewItemForNextPage = new List <ViewPageItem>(); // 如果兩個頁面之間的 ViewState 不同的話 才需要更新 ViewState 部分的 RuntimeViewElement if (nextViewState != currentViewState) { viewItemNextState = PrepareRuntimeReference(viewItemNextState); } // All reference preparing is done start do the stuff for change page InvokeOnViewPageChangeStart(this, new ViewPageTrisitionEventArgs(currentViewPage, nextViewPage)); OnStart?.Invoke(); List <ViewElement> viewElementDoesExitsInNextPage = new List <ViewElement>(); var allViewElementForNextPageInViewPage = viewItemNextPage.Select(m => m.runtimeViewElement).ToList(); var allViewElementForNextPageInViewState = viewItemNextState.Select(m => m.runtimeViewElement).ToList(); foreach (var item in currentLiveElementsInViewPage) { //不存在的話就讓他加入應該移除的列表 if (allViewElementForNextPageInViewPage.Contains(item) == false && allViewElementForNextPageInViewState.Contains(item) == false) { //加入該移除的列表 viewElementDoesExitsInNextPage.Add(item); } } currentLiveElementsInViewPage.Clear(); currentLiveElementsInViewPage = allViewElementForNextPageInViewPage; if (nextViewState != currentViewState) { foreach (var item in currentLiveElementsInViewState) { //不存在的話就讓他加入應該移除的列表 if (allViewElementForNextPageInViewState.Contains(item) == false && allViewElementForNextPageInViewPage.Contains(item) == false) { //加入該移除的列表 viewElementDoesExitsInNextPage.Add(item); } } currentLiveElementsInViewState.Clear(); currentLiveElementsInViewState = allViewElementForNextPageInViewState; } //對離場的呼叫改變狀態 foreach (var item in viewElementDoesExitsInNextPage) { item.ChangePage(false, null, null, 0, 0); } float TimeForPerviousPageOnLeave = 0; switch (nextViewPage.viewPageTransitionTimingType) { case ViewPage.ViewPageTransitionTimingType.AfterPervious: //TimeForPerviousPageOnLeave = ViewSystemUtilitys.CalculateOnLeaveDuration(viewItemNextPage.Select(m => m.viewElement), maxClampTime); TimeForPerviousPageOnLeave = nextViewPageWaitTime; break; case ViewPage.ViewPageTransitionTimingType.WithPervious: TimeForPerviousPageOnLeave = 0; break; case ViewPage.ViewPageTransitionTimingType.Custom: TimeForPerviousPageOnLeave = nextViewPage.customPageTransitionWaitTime; break; } // nextViewPageWaitTime = ViewSystemUtilitys.CalculateDelayOutTime(viewItemNextPage); nextViewPageWaitTime = ViewSystemUtilitys.CalculateOnLeaveDuration(viewItemNextPage.Select(m => m.viewElement), maxClampTime); //等上一個頁面的 OnLeave 結束,注意,如果頁面中有大量的 Animator 這裡只能算出預估的結果 並且會限制最長時間為一秒鐘 if (ignoreTimeScale) { yield return(Yielders.GetWaitForSecondsRealtime(TimeForPerviousPageOnLeave)); } else { yield return(Yielders.GetWaitForSeconds(TimeForPerviousPageOnLeave)); } viewItemForNextPage.AddRange(viewItemNextPage); if (viewItemNextState != null) { viewItemForNextPage.AddRange(viewItemNextState); } //對進場的呼叫改變狀態(ViewPage) foreach (var item in viewItemForNextPage.OrderBy(m => m.sortingOrder)) { if (item.runtimeViewElement == null) { ViewSystemLog.LogError($"The runtimeViewElement is null for some reason, ignore this item."); continue; } //套用複寫值 item.runtimeViewElement.ApplyOverrides(item.overrideDatas); item.runtimeViewElement.ApplyEvent(item.eventDatas); var transformData = item.GetCurrentViewElementTransform(breakPointsStatus); if (!string.IsNullOrEmpty(transformData.parentPath)) { item.runtimeParent = transformCache.Find(transformData.parentPath); } else { item.runtimeParent = nextViewPage.runtimePageRoot; } item.runtimeViewElement.ChangePage(true, item.runtimeParent, transformData, item.sortingOrder, item.TweenTime, item.delayIn); } foreach (var item in currentLiveElements.OrderBy(m => m.sortingOrder)) { item.rectTransform.SetAsLastSibling(); } float OnShowAnimationFinish = ViewSystemUtilitys.CalculateOnShowDuration(viewItemNextPage.Select(m => m.runtimeViewElement), maxClampTime); //更新狀態 UpdateCurrentViewStateAndNotifyEvent(nextViewPage); foreach (var item in currentLiveElements) { item.OnChangedPage(); } yield return(runtimePool.RecoveryQueuedViewElement()); OnChanged?.Invoke(); if (ignoreTimeScale) { yield return(Yielders.GetWaitForSecondsRealtime(OnShowAnimationFinish)); } else { //通知事件 yield return(Yielders.GetWaitForSeconds(OnShowAnimationFinish)); } ChangePageToCoroutine = null; //Callback InvokeOnViewPageChangeEnd(this, new ViewPageEventArgs(currentViewPage, lastViewPage)); nextViewPage = null; nextViewState = null; //2019.12.18 due to there may be new Callback be add, change the OnComplete to all is done. OnComplete?.Invoke(); }