public virtual void SetUpSheet() { Infos = new SpriteData(); Infos.List = new List <List <List <SpriteInfo> > >(); for (int i = 0; i < spriteList.Count; i++) { Infos.List.Add(new List <List <SpriteInfo> >()); var path = AssetDatabase.GetAssetPath(spriteList[i]) .Substring(17); //Substring(17) To remove the "Assets/Resources/" Sprite[] spriteSheetSprites = Resources.LoadAll <Sprite>(path.Remove(path.Length - 4)); if (spriteSheetSprites.Length > 1) { var p = AssetDatabase.GetAssetPath(spriteList[i]); int extensionIndex = p.LastIndexOf("."); p = p.Substring(0, extensionIndex) + ".json"; string json = System.IO.File.ReadAllText(p); Logger.Log(json.ToString()); spriteJson = JsonConvert.DeserializeObject <SpriteJson>(json); int c = 0; int cone = 0; for (int J = 0; J < spriteJson.Number_Of_Variants; J++) { Infos.List[i].Add(new List <SpriteInfo>()); } foreach (var SP in spriteSheetSprites) { var info = new SpriteInfo(); info.sprite = SP; if (spriteJson.Delays.Count > 0) { info.waitTime = spriteJson.Delays[c][cone]; } Infos.List[i][c].Add(info); if (c >= (spriteJson.Number_Of_Variants - 1)) { c = 0; cone++; } else { c++; } } } else { var info = new SpriteInfo() { sprite = spriteSheetSprites[0], waitTime = 0 }; Infos.List[i].Add(new List <SpriteInfo>()); Infos.List[i][0].Add(info); } } Infos.SerializeT(); var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); Logger.Log("Setup Complete", Category.SpriteHandler); } }
static void DrawSkeletons(SceneView sceneview) { var gizmoColor = Gizmos.color; pyramidMeshRenderer.Clear(); boxMeshRenderer.Clear(); for (var i = 0; i < s_BoneRendererComponents.Count; i++) { var boneRenderer = s_BoneRendererComponents[i]; if (boneRenderer.bones == null) { continue; } PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { StageHandle stageHandle = prefabStage.stageHandle; if (stageHandle.IsValid() && !stageHandle.Contains(boneRenderer.gameObject)) { continue; } } if (boneRenderer.drawBones) { var size = boneRenderer.boneSize * 0.025f; var shape = boneRenderer.boneShape; var color = boneRenderer.boneColor; var nubColor = new Color(color.r, color.g, color.b, color.a); var selectionColor = Color.white; for (var j = 0; j < boneRenderer.bones.Length; j++) { var bone = boneRenderer.bones[j]; if (bone.first == null || bone.second == null) { continue; } DoBoneRender(bone.first, bone.second, shape, color, size); } for (var k = 0; k < boneRenderer.tips.Length; k++) { var tip = boneRenderer.tips[k]; if (tip == null) { continue; } DoBoneRender(tip, null, shape, color, size); } } if (boneRenderer.drawTripods) { var size = boneRenderer.tripodSize * 0.025f; for (var j = 0; j < boneRenderer.transforms.Length; j++) { var tripodSize = 1f; var transform = boneRenderer.transforms[j]; if (transform == null) { continue; } var position = transform.position; var xAxis = position + transform.rotation * Vector3.right * size * tripodSize; var yAxis = position + transform.rotation * Vector3.up * size * tripodSize; var zAxis = position + transform.rotation * Vector3.forward * size * tripodSize; Handles.color = Color.red; Handles.DrawLine(position, xAxis); Handles.color = Color.green; Handles.DrawLine(position, yAxis); Handles.color = Color.blue; Handles.DrawLine(position, zAxis); } } } pyramidMeshRenderer.Render(); boxMeshRenderer.Render(); Gizmos.color = gizmoColor; }
private void DoPrefabButtons() { if (!m_IsPrefabInstanceAnyRoot || m_IsAsset) { return; } using (new EditorGUI.DisabledScope(m_PlayModeObjects)) { EditorGUILayout.BeginHorizontal(Styles.prefabButtonsHorizontalLayout); // Prefab information PrefabAssetType singlePrefabType = PrefabUtility.GetPrefabAssetType(target); PrefabInstanceStatus singleInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(target); GUIContent prefixLabel; if (targets.Length > 1) { prefixLabel = Styles.goTypeLabelMultiple; } else { prefixLabel = Styles.goTypeLabel[(int)singlePrefabType, (int)singleInstanceStatus]; } if (prefixLabel != null) { EditorGUILayout.BeginHorizontal(GUILayout.Width(kIconSize + Styles.tagFieldWidth)); GUILayout.FlexibleSpace(); if (m_IsDisconnected || m_IsMissing) { GUI.contentColor = GUI.skin.GetStyle("CN StatusWarn").normal.textColor; GUILayout.Label(prefixLabel, EditorStyles.whiteLabel, GUILayout.ExpandWidth(false)); GUI.contentColor = Color.white; } else { GUILayout.Label(prefixLabel, GUILayout.ExpandWidth(false)); } EditorGUILayout.EndHorizontal(); } if (!m_IsMissing) { using (new EditorGUI.DisabledScope(targets.Length > 1)) { if (singlePrefabType == PrefabAssetType.Model) { // Open Model Prefab if (GUILayout.Button(Styles.openString, EditorStyles.miniButtonLeft)) { GameObject asset = PrefabUtility.GetOriginalSourceOrVariantRoot(target); AssetDatabase.OpenAsset(asset); GUIUtility.ExitGUI(); } } else { // Open non-Model Prefab using (new EditorGUI.DisabledScope(m_ImmutableSourceAsset)) { if (GUILayout.Button(Styles.openString, EditorStyles.miniButtonLeft)) { GameObject asset = PrefabUtility.GetOriginalSourceOrVariantRoot(target); PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(asset), (GameObject)target, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceInspectorOpenButton); GUIUtility.ExitGUI(); } } } } // Select prefab if (GUILayout.Button(Styles.selectString, EditorStyles.miniButtonRight)) { HashSet <GameObject> selectedAssets = new HashSet <GameObject>(); for (int i = 0; i < targets.Length; i++) { GameObject prefabGo = PrefabUtility.GetOriginalSourceOrVariantRoot(targets[i]); // Because of legacy prefab references we have to have this extra step // to make sure we ping the prefab asset correctly. // Reason is that scene files created prior to making prefabs CopyAssets // will reference prefabs as if they are serialized assets. Those references // works fine but we are not able to ping objects loaded directly from the asset // file, so we have to make sure we ping the metadata version of the prefab. var assetPath = AssetDatabase.GetAssetPath(prefabGo); selectedAssets.Add((GameObject)AssetDatabase.LoadMainAssetAtPath(assetPath)); } Selection.objects = selectedAssets.ToArray(); if (Selection.gameObjects.Length == 1) { EditorGUIUtility.PingObject(Selection.activeObject); } } // Should be EditorGUILayout.Space, except it does not have ExpandWidth set to false. // Maybe we can change that? GUILayoutUtility.GetRect(6, 6, GUILayout.ExpandWidth(false)); // Reserve space regardless of whether the button is there or not to avoid jumps in button sizes. Rect rect = GUILayoutUtility.GetRect(Styles.overridesContent, Styles.overridesDropdown); if (m_IsPrefabInstanceOutermostRoot) { if (EditorGUI.DropdownButton(rect, Styles.overridesContent, FocusType.Passive)) { if (targets.Length > 1) { PopupWindow.Show(rect, new PrefabOverridesWindow(targets.Select(e => (GameObject)e).ToArray())); } else { PopupWindow.Show(rect, new PrefabOverridesWindow((GameObject)target)); } GUIUtility.ExitGUI(); } } } EditorGUILayout.EndHorizontal(); } }
protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) { var objectReferences = DragAndDrop.objectReferences; if (objectReferences == null || objectReferences.Length == 0) { return(DragAndDropVisualMode.Rejected); } var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); var validItems = new List <Object>(objectReferences.Length); foreach (var reference in objectReferences) { // reject any objects from assets if (AssetDatabase.Contains(reference)) { continue; } var validObject = false; var component = reference as Component; var gameObject = reference as GameObject; if (component != null) { gameObject = component.gameObject; } else if (gameObject == null) { continue; } if (gameObject != null) { if (prefabStage != null && PrefabStageUtility.GetPrefabStage(gameObject) == prefabStage) { validObject = true; } else if (gameObject.scene.IsValid()) { validObject = true; } } if (validObject) { validItems.Add(reference); } } if (validItems.Count == 0) { return(DragAndDropVisualMode.Rejected); } if (Event.current.type == EventType.DragPerform) { var alt = Event.current.alt; EditorApplication.delayCall += () => { ReferencesFinder.FindObjectsReferencesInHierarchy(validItems.ToArray(), !alt); }; DragAndDrop.AcceptDrag(); } return(DragAndDropVisualMode.Generic); }
/// <summary> /// Get every basic prefab-related info about this node. /// </summary> public static Properties GetPrefabProperties(GameObject gameObject) { if (gameObject == null) { return(null); } Properties p = new Properties(gameObject); #if false // Does not required anymore, also generate warning in Editor // Wappen hack: From https://forum.unity.com/threads/problem-with-prefab-api-upgrade.537074/ // Check if it is nesting prefab //bool isPartOfPrefabInstance = PrefabUtility.IsPartOfPrefabInstance(gameObject); #endif // First group of check is to test everything about "Prefab Asset" { // First is to determine isPartOfPrefabAsset p.isPartOfPrefabAsset = PrefabUtility.IsPartOfPrefabAsset(gameObject); // Second alternate test, using direct AssetDatabase if (!p.isPartOfPrefabAsset) { p.isPartOfPrefabAsset = !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(gameObject)); } // If it is under prefab asset, determine its root // Use gameObject.transform.root.gameObject to test for prefab asset root. if (p.isPartOfPrefabAsset) { p.prefabAssetRoot = gameObject.transform.root.gameObject; p.isPrefabAssetRoot = (gameObject == p.prefabAssetRoot); p.prefabAssetType = PrefabUtility.GetPrefabAssetType(gameObject); } } // Second group of check is to test everything about "Prefab Instance" // This is when you instance an prefab asset into scene or nested under other prefab. // First check is obvious, it should not and cannot be prefab asset root in the first place. if (!p.isPrefabAssetRoot) { // Use PrefabUtility.GetNearestPrefabInstanceRoot to test for prefab instance root. /* Basic visualization * The node with its [Name] inside bracket is blue gameobject node. * See image in https://docs.unity3d.com/ScriptReference/PrefabUtility.GetNearestPrefabInstanceRoot.html * For possible prefab configuration * * - [OUTERMOST] * - CHILD 1 * - CHILD 2 * - [prefab instance head] < If we are running on this node, isPrefabInstanceRoot = true * - child 1 * - child 2 < If we are running on this node, isPrefabInstanceRoot = false, but we still have nearestInstanceRoot points to 'prefab instance head' */ // Note: "PrefabUtility.GetNearestPrefabInstanceRoot" Causes following warning message on editor: // SendMessage cannot be called during Awake, CheckConsistency, or OnValidate // If this API is called in such timing, it is unavoidable, live with it // https://forum.unity.com/threads/sendmessage-cannot-be-called-during-awake-checkconsistency-or-onvalidate-can-we-suppress.537265/ p.nearestInstanceRoot = PrefabUtility.GetNearestPrefabInstanceRoot(gameObject); p.isPartOfPrefabInstance = (p.nearestInstanceRoot != null); p.isPrefabInstanceRoot = gameObject == p.nearestInstanceRoot; // Equivalent to PrefabUtility.IsAnyPrefabInstanceRoot, see UnityReferenceSource } // Third test is testing everything about Prefab stage property // needed to be checked separately as it is very special rule var editorPrefabStage = PrefabStageUtility.GetCurrentPrefabStage( ); if (editorPrefabStage != null) { // We are in prefab stage, but is selected gameobject really an object from prefab stage? // There is no 100% direct API to determine this, plus there is following observed obstacle when in prefab stage: // - root object editing in prefab stage wont have connection to its original prefab (it becomes gray gameobject icon), so we cannot test it with any prefab API. (bad) // - Also cannot test for 'editorPrefabStage.prefabContentsRoot == gameObject.transform.root.gameObject' directly, both seems to always be different object instance. // but we could derive from the following fact: // If it was NOT under prefab asset (from above test) // we can almost sure that it is in prefab stage if (p.isPartOfPrefabAsset == false) { p.isPartOfPrefabStage = true; } // Editor prefab stage root object wont have transform.parent // That's how we determine if it is isPrefabStageRoot if (p.isPartOfPrefabStage && gameObject.transform.parent == null) { p.isPrefabStageRoot = true; } } // AssetPath determination // PrefabHelper will try its best to detect most accurate prefab path for this prefab // Has to be done separately based on API priority if (p.isRootOfAnyPrefab) { if (p.isPrefabStageRoot) { p.prefabAssetPath = editorPrefabStage.prefabAssetPath; } else if (p.isPrefabInstanceRoot) // It is nested prefab instance inside another prefab { // Note: GetPrefabAssetPathOfNearestInstanceRoot is the only way to obtain real asset path of this nested prefab instance // internally it uses PrefabUtility.GetOriginalSourceOrVariantRoot which is internal function to Unity, see UnityReferenceSource // FYI: Calling GetAssetPath will get the "top/outermost" one. Not this nested one. (dont want that) p.prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(p.nearestInstanceRoot); } else if (p.isPrefabAssetRoot) { // Ordinary prefab asset root p.prefabAssetPath = AssetDatabase.GetAssetPath(gameObject); } } else { // This object is not root of any prefab, but could still be part of some prefab, find that nearest asset path if (p.isPartOfPrefabStage) { p.prefabAssetPath = editorPrefabStage.prefabAssetPath; } else if (p.isPartOfPrefabInstance) { p.prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(p.nearestInstanceRoot); } else if (p.isPartOfPrefabAsset) { p.prefabAssetPath = AssetDatabase.GetAssetPath(gameObject.transform.root.gameObject); } } return(p); }
public bool IsEditingAPrefabAsset() { var stage = PrefabStageUtility.GetCurrentPrefabStage(); return(stage != null && editSequence.director != null && stage.IsPartOfPrefabContents(editSequence.director.gameObject)); }
public static string GetHierarchyPath(GameObject gameObject, bool includeScene = true) { if (gameObject == null) return String.Empty; StringBuilder sb; if (_SbPool.Count > 0) { sb = _SbPool.Pop(); sb.Clear(); } else { sb = new StringBuilder(200); } try { if (includeScene) { var sceneName = gameObject.scene.name; if (sceneName == string.Empty) { #if UNITY_2018_3_OR_NEWER var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject); if (prefabStage != null) { sceneName = "Prefab Stage"; } else #endif { sceneName = "Unsaved Scene"; } } sb.Append("<b>" + sceneName + "</b>"); } sb.Append(GetTransformPath(gameObject.transform)); #if false bool isPrefab; #if UNITY_2018_3_OR_NEWER isPrefab = PrefabUtility.GetPrefabAssetType(gameObject.gameObject) != PrefabAssetType.NotAPrefab; #else isPrefab = UnityEditor.PrefabUtility.GetPrefabType(o) == UnityEditor.PrefabType.Prefab; #endif var assetPath = string.Empty; if (isPrefab) { #if UNITY_2018_3_OR_NEWER assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject); #else assetPath = AssetDatabase.GetAssetPath(gameObject); #endif sb.Append(" (" + System.IO.Path.GetFileName(assetPath) + ")"); } #endif var path = sb.ToString(); sb.Clear(); return path; } finally { _SbPool.Push(sb); } }
private static void Reference(Transform root, GameObject gameObject, Object value, bool stackReferencer, GameObject prefab) { var holder = default(GameObject); var existingReferencer = root.GetComponentInChildren <IReferencer>() as Component; if (existingReferencer != null) { holder = existingReferencer.gameObject; } else { holder = new GameObject("Referencer"); GameObjectUtility.SetParentAndAlign(holder, root.gameObject); holder.transform.SetAsFirstSibling(); Undo.RegisterCreatedObjectUndo(holder, "Create " + holder.name); } Object referencer = stackReferencer ? (Object)holder.AddComponent <StackReferencer>() : holder.AddComponent <Referencer>(); var serializedObject = new SerializedObject(referencer); var valueProperty = serializedObject.FindProperty("value"); valueProperty.objectReferenceInstanceIDValue = value.GetInstanceID(); var rootPath = "Assets/Objects"; if (!Directory.Exists(rootPath)) { Directory.CreateDirectory(rootPath); } var componentIndex = Array.IndexOf(gameObject.GetComponents <Component>(), value); var type = componentIndex == -1 ? value.GetType().Name : $"[{componentIndex}]{value.GetType().Name}"; var tokenPath = string.Empty; var isPrefab = false; if (prefab != null) { var prefabPath = $"{rootPath}/Prefabs"; if (!Directory.Exists(prefabPath)) { Directory.CreateDirectory(prefabPath); } tokenPath = $"{prefabPath}/{prefab.name}-{type}-{value.name}Token.asset"; isPrefab = true; } else { var scenePath = $"{rootPath}/Scenes"; if (!Directory.Exists(scenePath)) { Directory.CreateDirectory(scenePath); } var activeScene = SceneManager.GetActiveScene(); var currentScenePath = $"{scenePath}/{activeScene.name}"; if (!Directory.Exists(currentScenePath)) { Directory.CreateDirectory(currentScenePath); } var number = activeScene.buildIndex.ToString().Remove(0, 1); var index = activeScene.buildIndex < 10 ? $"0{number}" : number; var prefix = string.Concat(activeScene.name.Where(c => c >= 'A' && c <= 'Z')) + index; tokenPath = $"{currentScenePath}/{prefix}-{type}-{value.name}Token.asset"; } var token = ScriptableObject.CreateInstance <Token>(); AssetDatabase.CreateAsset(token, tokenPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); var tokenProperty = serializedObject.FindProperty("token"); tokenProperty.objectReferenceInstanceIDValue = token.GetInstanceID(); serializedObject.ApplyModifiedProperties(); if (isPrefab && PrefabStageUtility.GetCurrentPrefabStage() == null) { PrefabUtility.ApplyPrefabInstance(prefab, InteractionMode.UserAction); } Selection.activeObject = referencer; EditorGUIUtility.PingObject(referencer); }
public override void OnInspectorGUI() { EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); // Allow opening prefab even if file is not open for edit. // For things with explicit save operations (scenes, prefabs) we allow editing // and handle the potential version control conflict at the time when the user saves. bool wasEnabled = GUI.enabled; GUI.enabled = true; using (new EditorGUI.DisabledScope(assetTargets.Length > 1)) { GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button(Styles.openContent, Styles.openButtonStyle)) { // We only support opening one prefab at a time (so do not use 'targets') PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(assetTarget), null, StageNavigationManager.Analytics.ChangeType.EnterViaAssetInspectorOpenButton); GUIUtility.ExitGUI(); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); GUILayout.Space(5); if (!hasMissingScripts && !m_SavingHasFailed) { EditorGUILayout.HelpBox(Styles.openHelpText.text, MessageType.Info, true); } } GUI.enabled = wasEnabled; if (hasMissingScripts) { if (assetTargets.Length > 1) { // List all assets that have missing scripts (but only if we have a multi-selection) GUILayout.Space(5); EditorGUILayout.HelpBox(Styles.multiSelectionMissingScriptsHelpText.text, MessageType.Warning, true); using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(10); using (new EditorGUILayout.VerticalScope()) { foreach (var prefabAssetPath in m_PrefabsWithMissingScript) { if (GUILayout.Button(prefabAssetPath, EditorStyles.label)) { PrefabStageUtility.OpenPrefab(prefabAssetPath); } } } } } else { EditorGUILayout.HelpBox(Styles.missingScriptsHelpText.text, MessageType.Warning, true); } } else if (m_SavingHasFailed) { EditorGUILayout.HelpBox(Styles.savingFailedHelpText.text, MessageType.Warning, true); } EditorGUILayout.EndVertical(); }
private void LateUpdate() { #if UNITY_EDITOR // We don't run in "prefab scenes", i.e. when editing a prefab. Bail out if prefab scene is detected. if (PrefabStageUtility.GetCurrentPrefabStage() != null) { return; } #endif if (OceanRenderer.Instance == null || !ShowEffect()) { _rend.enabled = false; return; } // Pass true in last arg for a crap reason - in edit mode LateUpdate can be called very frequently, and the height sampler mistakenly thinks // this is erroneous and complains. _sampleWaterHeight.Init(transform.position, 0f, true); _sampleWaterHeight.Sample(out var waterHeight); float heightOffset = transform.position.y - waterHeight; // Disable skirt when camera not close to water. In the first few frames collision may not be avail, in that case no choice // but to assume enabled. In the future this could detect if camera is far enough under water, render a simple quad to avoid // finding the intersection line. _rend.enabled = heightOffset < _maxHeightAboveWater; if (_rend.enabled) { if (_copyParamsEachFrame) { _rend.sharedMaterial.CopyPropertiesFromMaterial(OceanRenderer.Instance.OceanMaterial); } // Assign lod0 shape - trivial but bound every frame because lod transform comes from here if (_mpb == null) { _mpb = new PropertyWrapperMPB(); } _rend.GetPropertyBlock(_mpb.materialPropertyBlock); // Underwater rendering uses displacements for intersecting the waves with the near plane, and ocean depth/shadows for ScatterColour() _mpb.SetInt(LodDataMgr.sp_LD_SliceIndex, 0); OceanRenderer.Instance._lodDataAnimWaves.BindResultData(_mpb); if (OceanRenderer.Instance._lodDataSeaDepths != null) { OceanRenderer.Instance._lodDataSeaDepths.BindResultData(_mpb); } else { LodDataMgrSeaFloorDepth.BindNull(_mpb); } if (OceanRenderer.Instance._lodDataShadow != null) { OceanRenderer.Instance._lodDataShadow.BindResultData(_mpb); } else { LodDataMgrShadow.BindNull(_mpb); } _mpb.SetFloat(sp_HeightOffset, heightOffset); _mpb.SetVector(OceanChunkRenderer.sp_InstanceData, new Vector3(OceanRenderer.Instance.ViewerAltitudeLevelAlpha, 0f, 0f)); _rend.SetPropertyBlock(_mpb.materialPropertyBlock); } }
private void OnGUI() { // Find max label width. var maxLabelWidth = 110.0f; for (int i = 0; i < lxfml.groups.Length; i++) { var size = EditorStyles.boldLabel.CalcSize(new GUIContent(lxfml.groups[i].name)); maxLabelWidth = Mathf.Max(maxLabelWidth, size.x); } minSize = new Vector2(leftMargin + maxLabelWidth + 360, 226); maxSize = new Vector2(leftMargin + maxLabelWidth + 360, 2000); scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false); GUI.Box(new Rect(20, 20, 100, 100), logoTexture); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 20.0f, 100.0f), "Colliders", "Add colliders to bricks."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 50.0f, 100.0f), "Connectivity", "Add connectivity to bricks. Connectivity requires colliders."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 100.0f, 100.0f), "Static", "Make bricks static."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 130.0f, 100.0f), "Lightmapped", "Add lightmap UVs to bricks. Bricks must be static to be lightmapped."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 180.0f, 100.0f), "Randomize Rotation", "Slightly rotate bricks to improve realism."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 230.0f, 100.0f), "Prefer Legacy", "Prefer legacy geometry over new geometry."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 280.0f, 100.0f), "LOD", "LOD 0 includes chamfered edges.\nLOD 1 does not.\nLOD 2 simplifies knobs."); // Reserve the space for the GUILayout scroll view. GUILayout.Space(135.0f); var nextY = 135.0f; var showAllBoolsUI = model == null && group == null && lxfml.groups.Length > 1; // When importing a new model, just check if there is more than one lxfml group. showAllBoolsUI |= model != null && importSettings.Count > 1; // When reimporting an entire model, check if the existing model has more than one group. if (showAllBoolsUI) { CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 15.0f, nextY), importSettings, "colliders", "connectivity", null); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 45.0f, nextY), importSettings, "connectivity", null, "colliders"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 95.0f, nextY), importSettings, "isStatic", "lightmapped", null); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 125.0f, nextY), importSettings, "lightmapped", null, "isStatic"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 175.0f, nextY), importSettings, "randomizeRotation"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 225.0f, nextY), importSettings, "preferLegacy"); CreateAllLODsUI(new Vector2(leftMargin + maxLabelWidth + 275.0f, nextY), importSettings); // Reserve the space for the GUILayout scroll view. GUILayout.Space(25.0f); nextY += 25.0f; } var collidersOrConnectivityWhilePreferringLegacy = false; for (int i = 0; i < lxfml.groups.Length; i++) { var showGroup = group == null && model == null; // When importing a new model, show all groups. showGroup |= model != null && importSettings.ContainsKey(i); // When reimporting an entire model, only show groups already in the existing model. showGroup |= group != null && i == group.number; // When reimporting a model group, only show that group. if (showGroup) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth, 20.0f), lxfml.groups[i].name); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 15.0f, nextY), importSettings, "colliders", i, "connectivity", null); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 45.0f, nextY), importSettings, "connectivity", i, null, "colliders"); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 95.0f, nextY), importSettings, "isStatic", i, "lightmapped", null); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 125.0f, nextY), importSettings, "lightmapped", i, null, "isStatic"); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 175.0f, nextY), importSettings, "randomizeRotation", i); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 225.0f, nextY), importSettings, "preferLegacy", i); CreateLODUI(new Vector2(leftMargin + maxLabelWidth + 275.0f, nextY), importSettings, i); if ((importSettings[i].colliders || importSettings[i].connectivity) && importSettings[i].preferLegacy) { collidersOrConnectivityWhilePreferringLegacy = true; } // Reserve the space for the GUILayout scroll view. GUILayout.Space(20.0f); nextY += 20.0f; } } if (collidersOrConnectivityWhilePreferringLegacy) { EditorGUI.HelpBox(new Rect(leftMargin, nextY, position.width - leftMargin - 20.0f, 38.0f), "Legacy parts might not contain colliders or connectivity information.", MessageType.Warning); // Reserve the space for the GUILayout scroll view. GUILayout.Space(42.0f); nextY += 42.0f; } // Reserve the space for the GUILayout scroll view. GUILayout.Space(5.0f); nextY += 5.0f; // Only show pivot option when not reimporting group. if (group == null) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth, 20.0f), "Pivot"); pivot = (Model.Pivot)EditorGUI.EnumPopup(new Rect(leftMargin + maxLabelWidth + 15.0f, nextY, 126.0f, 16.0f), pivot); // Reserve the space for the GUILayout scroll view. GUILayout.Space(25.0f); nextY += 25.0f; } // Create the right import/reimport button and handle the import/reimport based on the three cases: // - Reimport model // - Reimport model group // - Import model bool importPressed; if (model) { // ---------------------- // Reimport entire model. // ---------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Reimport Model"); if (importPressed) { // Register undo. Undo.RegisterFullObjectHierarchyUndo(model.gameObject, "Reimport"); var oldPivot = model.pivot; model.pivot = pivot; // Update the path if it is new. if (filePath != null) { model.absoluteFilePath = filePath; model.relativeFilePath = PathUtils.GetRelativePath(Directory.GetCurrentDirectory(), filePath); } ModelImporter.ReimportModel(lxfml, model, oldPivot, importSettings); var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } SceneBrickBuilder.MarkSceneDirty(); } } else if (group) { // --------------------- // Reimport model group. // --------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Reimport Model Group"); if (importPressed) { // Register undo. Undo.RegisterFullObjectHierarchyUndo(group.gameObject, "Reimport"); ModelImporter.ReimportModelGroup(lxfml, group, importSettings[group.number], true); var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } SceneBrickBuilder.MarkSceneDirty(); } } else { // ---------------------- // Import model. // ---------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Import Model"); if (importPressed) { // Check for connectivity updates. ConnectivityVersionChecker.CheckForUpdates(); model = ModelImporter.InstantiateModel(lxfml, filePath, pivot, importSettings).GetComponent <Model>(); var camera = SceneView.lastActiveSceneView.camera; if (camera) { var cameraRay = new Ray(camera.transform.position, camera.transform.forward); var bricksInModel = model.GetComponentsInChildren <Brick>(); var bricks = new HashSet <Brick>(bricksInModel); var sourceBrick = bricks.First(); BrickBuildingUtility.AlignBricks(sourceBrick, bricks, BrickBuildingUtility.ComputeBounds(bricks), sourceBrick.transform.position, Vector3.zero, cameraRay, new Plane(Vector3.up, Vector3.zero), 100.0f, out Vector3 offset, out Vector3 alignedOffset, out _, out _); var offsetPosition = model.transform.position + alignedOffset; model.transform.position = offsetPosition; Selection.activeGameObject = model.gameObject; Physics.SyncTransforms(); } SceneBrickBuilder.SyncAndUpdateBrickCollision(true); } } // Reserve the space for the GUILayout scroll view. GUILayout.Space(36.0f); nextY += 36.0f; // List tracked errors. foreach (var trackedError in trackedErrors) { EditorGUI.HelpBox(new Rect(leftMargin, nextY, maxLabelWidth + 340.0f, 38.0f), trackedError.Key, MessageType.Warning); // Reserve the space for the GUILayout scroll view. GUILayout.Space(42.0f); nextY += 42.0f; foreach (var id in trackedError.Value) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth + 340.0f, 16.0f), id); // Reserve the space for the GUILayout scroll view. GUILayout.Space(20.0f); nextY += 20.0f; } } GUILayout.EndScrollView(); if (importPressed) { this.Close(); } }
/// <summary> /// 在场景中搜索任务目标 /// </summary> private static void SearchTaskTarget(TaskGameObjects taskGameObjects, int index) { if (taskGameObjects.GUIDs[index] == "<None>") { return; } if (taskGameObjects._gameObjects[index] != null) { return; } PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { taskGameObjects._gameObjects[index] = prefabStage.prefabContentsRoot.FindChildren(taskGameObjects.Paths[index]); if (taskGameObjects._gameObjects[index] == null) { TaskTarget[] targets = prefabStage.prefabContentsRoot.GetComponentsInChildren <TaskTarget>(true); foreach (TaskTarget target in targets) { if (taskGameObjects.GUIDs[index] == target.GUID) { taskGameObjects._gameObjects[index] = target.gameObject; taskGameObjects.Paths[index] = target.transform.FullName(); taskGameObjects.Paths[index] = taskGameObjects.Paths[index].Substring(taskGameObjects.Paths[index].IndexOf("/") + 1); break; } } } } else { taskGameObjects._gameObjects[index] = GameObject.Find(taskGameObjects.Paths[index]); if (taskGameObjects._gameObjects[index] == null) { TaskTarget[] targets = UnityEngine.Object.FindObjectsOfType <TaskTarget>(); foreach (TaskTarget target in targets) { if (taskGameObjects.GUIDs[index] == target.GUID) { taskGameObjects._gameObjects[index] = target.gameObject; taskGameObjects.Paths[index] = target.transform.FullName(); break; } } } } if (taskGameObjects._gameObjects[index] != null) { TaskTarget target = taskGameObjects._gameObjects[index].GetComponent <TaskTarget>(); if (!target) { target = taskGameObjects._gameObjects[index].AddComponent <TaskTarget>(); target.GUID = taskGameObjects.GUIDs[index]; EditorUtility.SetDirty(taskGameObjects._gameObjects[index]); } } }
private static void HierarchyWindowListElementOnGUI(int instanceID, Rect selectionRect) { if (EditorApplication.isPlayingOrWillChangePlaymode || !VCSettings.HierarchyIcons || !VCCommands.Active) { return; } var obj = EditorUtility.InstanceIDToObject(instanceID); if (obj == null) { string sceneAssetPath = SceneManagerUtilities.GetSceneAssetPathFromHandle(instanceID); if (!string.IsNullOrEmpty(sceneAssetPath)) { VCUtility.RequestStatus(sceneAssetPath, VCSettings.HierarchyReflectionMode); DrawIcon(selectionRect, IconUtils.rubyIcon, sceneAssetPath, null, -20f); } } else { var currentPrefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (currentPrefabStage != null) { var go = obj as GameObject; if (go) { if (PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot == go) { DrawIcon(selectionRect, IconUtils.squareIcon, PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath, PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot, 0f); } } } } }
public static bool IsPrefabModeRoot(GameObject test) { PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); return(prefabStage != null && prefabStage.prefabContentsRoot == test); }
internal static void UpdateAllMockups() { //When building, the scene may open-close multiple times and brought back the mockup canvas, //which combined with bugs mentioned at https://github.com/5argon/NotchSolution/issues/11, //will fail the build. This `if` prevents mockup refresh while building. if (BuildPipeline.isBuildingPlayer) { return; } EnsureCanvasAndEventSetup(); //Make the editing environment contains an another copy of mockup canvas. var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EnsureCanvasAndEventSetup(prefabStage: prefabStage); } var settings = Settings.Instance; bool enableSimulation = settings.EnableSimulation; var selectedDevice = SimulationDatabase.ByIndex(Settings.Instance.ActiveConfiguration.DeviceIndex); if (enableSimulation && selectedDevice != null) { var name = selectedDevice.Meta.overlay; Sprite mockupSprite = null; if (!string.IsNullOrEmpty(name)) { var filePath = Path.Combine(NotchSimulatorUtility.DevicesFolder, name); mockupSprite = AssetDatabase.LoadAssetAtPath <Sprite>(filePath); if (mockupSprite == null) { if (System.IO.File.Exists(filePath)) { Texture2D tex = new Texture2D(1, 1); tex.LoadImage(System.IO.File.ReadAllBytes(filePath)); mockupSprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100.0f); } else { Debug.LogWarning($"No mockup image named {name} in {NotchSimulatorUtility.DevicesFolder} folder!"); } } } foreach (var mockup in AllMockupCanvases) { mockup.UpdateMockupSprite( sprite: mockupSprite, orientation: NotchSimulatorUtility.GetGameViewOrientation(), simulate: enableSimulation, flipped: settings.FlipOrientation, prefabModeOverlayColor: Settings.Instance.PrefabModeOverlayColor ); } } else { DestroyHiddenCanvas(); } }
private static bool CreateMixedRealityToolkitGameObjectValidation() { return(PrefabStageUtility.GetCurrentPrefabStage() == null); }
public float PrefabModeButton(GameObjectTreeViewItem item, Rect selectionRect) { float contentRectRight = selectionRect.xMax; if (item.showPrefabModeButton) { float yOffset = (selectionRect.height - GameObjectStyles.rightArrow.fixedWidth) / 2; Rect buttonRect = new Rect( selectionRect.xMax - GameObjectStyles.rightArrow.fixedWidth - GameObjectStyles.rightArrow.margin.right, selectionRect.y + yOffset, GameObjectStyles.rightArrow.fixedWidth, GameObjectStyles.rightArrow.fixedHeight); int instanceID = item.id; GUIContent content = buttonRect.Contains(Event.current.mousePosition) ? PrefabStageUtility.GetPrefabButtonContent(instanceID) : GUIContent.none; if (GUI.Button(buttonRect, content, GameObjectStyles.rightArrow)) { GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go); Object originalSource = AssetDatabase.LoadMainAssetAtPath(assetPath); if (originalSource != null) { var prefabStageMode = PrefabStageUtility.GetPrefabStageModeFromModifierKeys(); PrefabStageUtility.OpenPrefab(assetPath, go, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyRightArrow); } } contentRectRight = buttonRect.xMin; } return(contentRectRight); }
public static bool IsPrefabStage(this GameObject gameObject) { return(PrefabStageUtility.GetCurrentPrefabStage() != null); }
protected override void OnEnable() { base.OnEnable(); configurationProfile = target as MixedRealityToolkitConfigurationProfile; var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); // Create The MR Manager if none exists. if (!MixedRealityToolkit.IsInitialized && prefabStage == null) { // TODO Check base scene for service locator existence? // Search for all instances, in case we've just hot reloaded the assembly. var managerSearch = FindObjectsOfType <MixedRealityToolkit>(); if (managerSearch.Length == 0) { if (EditorUtility.DisplayDialog( "Attention!", "There is no active Mixed Reality Toolkit in your scene!\n\nWould you like to create one now?", "Yes", "Later")) { if (MixedRealityToolkit.CameraSystem != null) { var playspace = MixedRealityToolkit.CameraSystem.CameraRig.PlayspaceTransform; Debug.Assert(playspace != null); } MixedRealityToolkit.Instance.ActiveProfile = configurationProfile; } else { Debug.LogWarning("No Mixed Reality Toolkit in your scene."); } } } // Camera configuration enableCameraSystem = serializedObject.FindProperty("enableCameraSystem"); cameraSystemType = serializedObject.FindProperty("cameraSystemType"); cameraProfile = serializedObject.FindProperty("cameraProfile"); // Input system configuration enableInputSystem = serializedObject.FindProperty("enableInputSystem"); inputSystemType = serializedObject.FindProperty("inputSystemType"); inputSystemProfile = serializedObject.FindProperty("inputSystemProfile"); // Boundary system configuration enableBoundarySystem = serializedObject.FindProperty("enableBoundarySystem"); boundarySystemType = serializedObject.FindProperty("boundarySystemType"); boundaryVisualizationProfile = serializedObject.FindProperty("boundaryVisualizationProfile"); // Teleport system configuration enableTeleportSystem = serializedObject.FindProperty("enableTeleportSystem"); teleportSystemType = serializedObject.FindProperty("teleportSystemType"); // Spatial Awareness system configuration enableSpatialAwarenessSystem = serializedObject.FindProperty("enableSpatialAwarenessSystem"); spatialAwarenessSystemType = serializedObject.FindProperty("spatialAwarenessSystemType"); spatialAwarenessProfile = serializedObject.FindProperty("spatialAwarenessProfile"); // Networking system configuration enableNetworkingSystem = serializedObject.FindProperty("enableNetworkingSystem"); networkingSystemType = serializedObject.FindProperty("networkingSystemType"); networkingSystemProfile = serializedObject.FindProperty("networkingSystemProfile"); // Diagnostics system configuration enableDiagnosticsSystem = serializedObject.FindProperty("enableDiagnosticsSystem"); diagnosticsSystemType = serializedObject.FindProperty("diagnosticsSystemType"); diagnosticsSystemProfile = serializedObject.FindProperty("diagnosticsSystemProfile"); // Additional registered components configuration registeredServiceProvidersProfile = serializedObject.FindProperty("registeredServiceProvidersProfile"); }
public static bool IsRootPrefabStage(this GameObject gameObject) { // return PrefabStageUtility.GetCurrentPrefabStage() != null && !PrefabUtility.IsPartOfPrefabInstance(gameObject); return(PrefabStageUtility.GetCurrentPrefabStage() != null && !PrefabUtility.IsPartOfAnyPrefab(gameObject)); }
/// <summary> /// Draws the contents of a scriptable inline inside a foldout. Depending on if there's an actual scriptable /// linked, the values will be greyed out or editable in case the scriptable is created inside the serialized object. /// </summary> static public bool DrawScriptableFoldout <T>(SerializedProperty scriptable, string description, bool isExpanded) where T : ScriptableObject { isExpanded = EditorGUILayout.Foldout(isExpanded, description, true, MixedRealityStylesUtility.BoldFoldoutStyle); if (isExpanded) { using (new EditorGUI.IndentLevelScope()) { if (scriptable.objectReferenceValue == null) { // If there's no scriptable linked we're creating a local instance that allows to store a // local version of the scriptable in the serialized object owning the scriptable property. scriptable.objectReferenceValue = ScriptableObject.CreateInstance <T>(); } // We have currently 5 different states to display to the user: // 1. the scriptable is local to the object instance // 2. the scriptable is a linked nested scriptable inside of the currently displayed prefab // 3. the scriptable is a linked nested scriptable inside of another prefab // 4. the scriptable is a shared standalone asset // 5. the scriptable slot is empty but inside of a prefab asset which needs special handling as // prefabs can only display linked or nested scriptables. // Depending on the type of link we show the user the scriptable configuration either: // case 1 &2: editable inlined // case 3 & 4: greyed out readonly // case 5: only show the link // case 5 -> can't create and/or store the local scriptable above - show link bool isStoredAsset = (scriptable.objectReferenceValue == null) ? false : AssetDatabase.Contains(scriptable.objectReferenceValue); bool isEmptyInStagedPrefab = !isStoredAsset && ((Component)scriptable.serializedObject.targetObject).gameObject.scene.path == ""; if (scriptable.objectReferenceValue == null || isEmptyInStagedPrefab) { EditorGUILayout.HelpBox("No scriptable " + scriptable.displayName + " linked to this prefab. Prefabs can't store " + "local versions of scriptables and need to be linked to a scriptable asset.", MessageType.Warning); EditorGUILayout.PropertyField(scriptable, new GUIContent(scriptable.displayName + " (Empty): ")); } else { bool isNestedInCurrentPrefab = false; var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { var instancePath = AssetDatabase.GetAssetPath(scriptable.objectReferenceValue); isNestedInCurrentPrefab = instancePath != "" && #if UNITY_2020_1_OR_NEWER instancePath == prefabStage.assetPath #else instancePath == prefabStage.prefabAssetPath #endif ; } if (isStoredAsset && !isNestedInCurrentPrefab) { // case 3 & 4 - greyed out drawer bool isMainAsset = AssetDatabase.IsMainAsset(scriptable.objectReferenceValue); var sharedAssetPath = AssetDatabase.GetAssetPath(scriptable.objectReferenceValue); if (isMainAsset) { EditorGUILayout.HelpBox("Editing a shared " + scriptable.displayName + ", located at " + sharedAssetPath, MessageType.Warning); } else { EditorGUILayout.HelpBox("Editing a nested " + scriptable.displayName + ", located inside of " + sharedAssetPath, MessageType.Warning); } EditorGUILayout.PropertyField(scriptable, new GUIContent(scriptable.displayName + " (Shared asset): ")); // In case there's a shared scriptable linked we're disabling the inlined scriptable properties // (this will render them grayed out) so users won't accidentally modify the shared scriptable. GUI.enabled = false; DrawScriptableSubEditor(scriptable); GUI.enabled = true; } else { // case 1 & 2 - inline editable drawer if (isNestedInCurrentPrefab) { EditorGUILayout.HelpBox("Editing a nested version of " + scriptable.displayName + ".", MessageType.Info); } else { EditorGUILayout.HelpBox("Editing a local version of " + scriptable.displayName + ".", MessageType.Info); } EditorGUILayout.PropertyField(scriptable, new GUIContent(scriptable.displayName + " (local): ")); DrawScriptableSubEditor(scriptable); } } } } return(isExpanded); }
public void Draw(Rect r, Rect visibleArea) { var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); m_IsNotInPrefabContextModeWithOverrides = prefabStage == null || prefabStage.mode != PrefabStage.Mode.InContext || !PrefabStage.s_PatchAllOverriddenProperties || Selection.objects.All(obj => PrefabUtility.IsPartOfAnyPrefab(obj) && !AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(obj)).Equals(AssetDatabase.AssetPathToGUID(prefabStage.assetPath))); m_ReorderableList.draggable = m_Reorderable && m_IsNotInPrefabContextModeWithOverrides; Rect headerRect = new Rect(r.x, r.y, r.width, m_HeaderHeight); Rect sizeRect = new Rect(headerRect.xMax - Constants.kArraySizeWidth, headerRect.y, Constants.kArraySizeWidth, m_HeaderHeight); EventType prevType = Event.current.type; if (Event.current.type == EventType.MouseUp && sizeRect.Contains(Event.current.mousePosition)) { Event.current.type = EventType.Used; } EditorGUI.BeginChangeCheck(); m_Foldout = EditorGUI.BeginFoldoutHeaderGroup(headerRect, m_Foldout, m_Header); EditorGUI.EndFoldoutHeaderGroup(); if (EditorGUI.EndChangeCheck()) { m_ReorderableList.ClearCacheRecursive(); } if (Event.current.type == EventType.Used && sizeRect.Contains(Event.current.mousePosition)) { Event.current.type = prevType; } EditorGUI.DefaultPropertyField(sizeRect, m_ArraySize, GUIContent.none); EditorGUI.LabelField(sizeRect, new GUIContent("", "Array Size")); if (headerRect.Contains(Event.current.mousePosition)) { if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) { Object[] objReferences = DragAndDrop.objectReferences; foreach (var o in objReferences) { if (EditorGUI.ValidateObjectFieldAssignment(new[] { o }, typeof(Object), m_ReorderableList.serializedProperty, EditorGUI.ObjectFieldValidatorOptions.None) != null) { DragAndDrop.visualMode = DragAndDropVisualMode.Generic; } else { continue; } if (Event.current.type == EventType.DragPerform) { ReorderableList.defaultBehaviours.DoAddButton(m_ReorderableList, o); } } DragAndDrop.AcceptDrag(); Event.current.Use(); } } if (Event.current.type == EventType.DragExited) { DragAndDrop.visualMode = DragAndDropVisualMode.None; Event.current.Use(); } if (m_Foldout) { r.y += m_HeaderHeight + Constants.kHeaderPadding; r.height -= m_HeaderHeight + Constants.kHeaderPadding; visibleArea.y -= r.y; m_ReorderableList.DoList(r, visibleArea); } }
protected static GameObject getSourcePrefab42019(GameObject gameObject, out bool isSceneObject, out GameObject sourceRoot, out string childPath) { GameObject source; PrefabAssetType assetType = PrefabUtility.GetPrefabAssetType(gameObject); PrefabInstanceStatus status = PrefabUtility.GetPrefabInstanceStatus(gameObject); PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage(); if (stage != null && stage.IsPartOfPrefabContents(gameObject)) { //编辑场景 isSceneObject = false; childPath = stage.prefabContentsRoot.transform.getChildPath(gameObject.transform); sourceRoot = AssetDatabase.LoadAssetAtPath <GameObject>(stage.prefabAssetPath); Transform sourceTransform = sourceRoot.transform.Find(childPath); if (sourceTransform != null) { source = sourceTransform.gameObject; } else { sourceRoot = null; childPath = string.Empty; return(null); } } else if (string.IsNullOrEmpty(gameObject.scene.path)) { //Assets isSceneObject = false; source = gameObject; sourceRoot = source.transform.root.gameObject; childPath = sourceRoot.transform.getChildPath(source.transform); //switch (assetType) //{ // case PrefabAssetType.Regular: // case PrefabAssetType.Variant: // case PrefabAssetType.Model: // case PrefabAssetType.MissingAsset: // case PrefabAssetType.NotAPrefab: // default: // break; //} } else { //场景物体 switch (status) { case PrefabInstanceStatus.Connected: switch (assetType) { case PrefabAssetType.Regular: case PrefabAssetType.Model: isSceneObject = false; source = PrefabUtility.GetCorrespondingObjectFromSource(gameObject); sourceRoot = source.transform.root.gameObject; childPath = sourceRoot.transform.getChildPath(source.transform); break; case PrefabAssetType.Variant: isSceneObject = false; source = PrefabUtility.GetCorrespondingObjectFromSource(gameObject); sourceRoot = source.transform.root.gameObject; childPath = sourceRoot.transform.getChildPath(source.transform); break; case PrefabAssetType.MissingAsset: case PrefabAssetType.NotAPrefab: default: isSceneObject = true; source = gameObject; sourceRoot = null; childPath = null; break; } break; case PrefabInstanceStatus.NotAPrefab: case PrefabInstanceStatus.MissingAsset: case PrefabInstanceStatus.Disconnected: default: isSceneObject = true; source = gameObject; sourceRoot = null; childPath = null; break; } } return(source); }
public void LogStageInformation() { #if UNITY_EDITOR // First check if input GameObject is persistent before checking what stage the GameObject is in if (EditorUtility.IsPersistent(gameObject)) { if (!PrefabUtility.IsPartOfPrefabAsset(gameObject)) { LogConsole("The GameObject is a temporary object created during import. OnValidate() is called two times with a temporary object during import: First time is when saving cloned objects to .prefab file. Second event is when reading .prefab file objects during import"); } else { LogConsole("GameObject is part of an imported Prefab Asset (from the Library folder)"); } return; } // If the GameObject is not persistent let's determine which stage we are in first because getting Prefab info depends on it var mainStage = StageUtility.GetMainStageHandle(); var currentStage = StageUtility.GetStageHandle(gameObject); if (currentStage == mainStage) { if (PrefabUtility.IsPartOfPrefabInstance(gameObject)) { var type = PrefabUtility.GetPrefabAssetType(gameObject); var path = AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(gameObject)); LogConsole(string.Format("GameObject is part of a Prefab Instance in the MainStage and is of type: {0}. It comes from the prefab asset: {1}", type, path)); } else { LogConsole("GameObject is a plain GameObject in the MainStage"); } } else { var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject); if (prefabStage != null) { if (PrefabUtility.IsPartOfPrefabInstance(gameObject)) { var type = PrefabUtility.GetPrefabAssetType(gameObject); var nestedPrefabPath = AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(gameObject)); LogConsole(string.Format("GameObject is in a PrefabStage. The GameObject is part of a nested Prefab Instance and is of type: {0}. The opened Prefab asset is: {1} and the nested Prefab asset is: {2}", type, prefabStage.prefabAssetPath, nestedPrefabPath)); } else { var prefabAssetRoot = AssetDatabase.LoadAssetAtPath <GameObject>(prefabStage.prefabAssetPath); var type = PrefabUtility.GetPrefabAssetType(prefabAssetRoot); LogConsole(string.Format("GameObject is in a PrefabStage. The opened Prefab is of type: {0}. The GameObject comes from the prefab asset: {1}", type, prefabStage.prefabAssetPath)); } } else if (EditorSceneManager.IsPreviewSceneObject(gameObject)) { LogConsole("GameObject is not in the MainStage, nor in a PrefabStage. But it is in a PreviewScene so could be used for Preview rendering or other utilities."); } else { LogConsole("Unknown GameObject Info"); } } #endif }
public static bool IsPartOfPrefabStage(GameObject gameObject, out PrefabStage pfs) { pfs = PrefabStageUtility.GetPrefabStage(gameObject); return(pfs != null); }
public void LogPrefabInformation() { #if UNITY_EDITOR StringBuilder stringBuilder = new StringBuilder(); // First check if input GameObject is persistent before checking what stage the GameObject is in if (EditorUtility.IsPersistent(gameObject)) { if (!PrefabUtility.IsPartOfPrefabAsset(gameObject)) { stringBuilder.Append("The GameObject is a temporary object created during import. OnValidate() is called two times with a temporary object during import: First time is when saving cloned objects to .prefab file. Second event is when reading .prefab file objects during import"); } else { stringBuilder.Append("GameObject is part of an imported Prefab Asset (from the Library folder).\n"); stringBuilder.AppendLine("Prefab Asset: " + GetPrefabInfoString(gameObject)); } Debug.Log(stringBuilder.ToString()); return; } PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(gameObject); if (prefabStage != null) { GameObject openPrefabThatContentsIsPartOf = AssetDatabase.LoadAssetAtPath <GameObject>(prefabStage.prefabAssetPath); stringBuilder.AppendFormat( "The GameObject is part of the Prefab contents of the Prefab Asset:\n{0}\n\n", GetPrefabInfoString(openPrefabThatContentsIsPartOf)); } if (!PrefabUtility.IsPartOfPrefabInstance(gameObject)) { stringBuilder.Append("The GameObject is a plain GameObject (not part of a Prefab instance).\n"); } else { // This is the Prefab Asset that can be applied to via the Overrides dropdown. GameObject outermostPrefabAssetObject = PrefabUtility.GetCorrespondingObjectFromSource(gameObject); // This is the Prefab Asset that determines the icon that is shown in the Hierarchy for the nearest root. GameObject nearestRootPrefabAssetObject = AssetDatabase.LoadAssetAtPath <GameObject>(PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject)); // This is the Prefab Asset where the original version of the object comes from. GameObject originalPrefabAssetObject = PrefabUtility.GetCorrespondingObjectFromOriginalSource(gameObject); stringBuilder.AppendFormat( @"Prefab Asset of the outermost Prefab instance the input GameObject is part of is: {0} Prefab Asset of the nearest Prefab instance root the input GameObject is part of is: {1} Prefab Asset of the innermost Prefab instance the input GameObject is part of is: {2} Complete nesting chain from outermost to original: ", GetPrefabInfoString(outermostPrefabAssetObject), GetPrefabInfoString(nearestRootPrefabAssetObject), GetPrefabInfoString(originalPrefabAssetObject)); GameObject current = outermostPrefabAssetObject; while (current != null) { stringBuilder.AppendLine(GetPrefabInfoString(current)); current = PrefabUtility.GetCorrespondingObjectFromSource(current); } } stringBuilder.AppendLine(""); Debug.Log(stringBuilder.ToString()); #endif }
/// <summary> /// Recompute the model and model group hierarchy. /// Some rules: /// 1. A brick will always be in a model group, which will always be in a model. /// 2. Empty models and model groups are destroyed. /// 3. Bricks can not contain bricks, model groups can not contain model groups and models can not contain models. So they are flattened. /// </summary> /// <param name="bricks">The bricks that we need to check the hierarchy for</param> /// <param name="alignRotation">Whether or not we also align rotation when we recompute pivot</param> /// <param name="undoBehavior">Whether or not to register undo for the recomputation of hierarchy</param> public static void RecomputeHierarchy(IEnumerable <Brick> bricks, bool alignRotation = true, UndoBehavior undoBehavior = UndoBehavior.withUndo) { // Group numbers are numbers in parentheses // So group 1 with three bricks is shown as (1, 1, 1) // In case the group is part of a prefab it is suffixed with a p like (1p, 1p) // In case one of the bricks in a group is an override it is noted with a + as in (1p, 1p+) // Cases for splitting: // (1, 1) -> (1) (1) // (1, 1) (2) -> (1) (1, 2) -> (1) (2, 2) // Cases for unpacking: // (1p) (2p) -> (1, 2p) -> (2p+, 2p) // (1p, 1p+) (2p) -> (1, 1, 2p) -> (2p+, 2p+, 2p) // (1p, 1p) -> (1p) (1p) -> (1) (1) // Only set parent: // (1) (2) -> (1, 2) -> (2, 2) // (1p, 1p+) (2p) -> (1p) (1p+, 2p) -> (1p) (2p+, 2p) // (1p, 1p+) (2) -> (1p) (1p+, 2) -> (1p) (2, 2) if (PrefabStageUtility.GetCurrentPrefabStage() != null) { var rootObject = PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot; var brick = rootObject.GetComponent <Brick>(); if (brick) { return; } } // First we flatten models var modelsToCheck = new HashSet <Model>(); var groupsToCheck = new HashSet <ModelGroup>(); var bricksToCheck = new HashSet <Brick>(); foreach (var brick in bricks) { var bricksInParent = brick.GetComponentsInParent <Brick>(true); if (bricksInParent.Length > 1) { bricksToCheck.Add(brick); } var modelsInParent = brick.GetComponentsInParent <Model>(true); if (modelsInParent.Length > 1) { modelsToCheck.UnionWith(modelsInParent); } var groupsInParent = brick.GetComponentsInParent <ModelGroup>(true); if (groupsInParent.Length > 1) { groupsToCheck.UnionWith(groupsInParent); } } foreach (var model in modelsToCheck) { var modelsInModel = model.GetComponentsInChildren <Model>(true); foreach (var inModel in modelsInModel) { if (inModel == model) { continue; } var groupsInModel = inModel.GetComponentsInChildren <ModelGroup>(true); foreach (var group in groupsInModel) { SetParent(group.transform, model.transform, undoBehavior); } } } // Now flatten groups foreach (var group in groupsToCheck) { var groupsInGroup = group.GetComponentsInChildren <ModelGroup>(true); foreach (var inGroup in groupsInGroup) { if (inGroup == group) { continue; } var bricksInGroup = inGroup.GetComponentsInChildren <Brick>(true); foreach (var brick in bricksInGroup) { SetParent(brick.transform, group.transform, undoBehavior); } } } // Now flatten bricks foreach (var brick in bricksToCheck) { var group = GetGroupInParent(brick.transform); if (group) { SetParent(brick.transform, group.transform, undoBehavior); } } var connectedClusters = new List <HashSet <Brick> >(); // Collect all connected brick lists foreach (var brick in bricks) { if (connectedClusters.Any(x => x.Contains(brick))) { continue; } if (!brick.HasConnectivity()) { var group = GetGroupInParent(brick.transform); if (!group) { connectedClusters.Add(new HashSet <Brick> { brick }); } else { var model = GetModelInParent(brick.transform); if (!model) { var bricksInGroup = group.GetComponentsInChildren <Brick>(true); var connected = new HashSet <Brick>(); connected.Add(brick); connectedClusters.Add(connected); } } } else { var connected = brick.GetConnectedBricks(); connected.Add(brick); connectedClusters.Add(connected); } } // Now find all groups for each cluster var groupsPerCluster = new List <(HashSet <Brick>, HashSet <ModelGroup>, HashSet <Brick>)>(); foreach (var cluster in connectedClusters) { if (cluster.Count == 0) { continue; } var bricksNotInGroup = new HashSet <Brick>(); var groups = new HashSet <ModelGroup>(); foreach (var brick in cluster) { var group = GetGroupInParent(brick.transform); if (group) { groups.Add(group); } else { bricksNotInGroup.Add(brick); } } groupsPerCluster.Add((cluster, groups, bricksNotInGroup)); } // Sorting makes sure we merge before we split. Merging will make it easier to see what we need to split later. groupsPerCluster = groupsPerCluster.OrderByDescending(x => x.Item2.Count).ToList(); // Check through each of these groups in the cluster foreach (var groupPerCluster in groupsPerCluster) { var cluster = groupPerCluster.Item1; var groups = groupPerCluster.Item2; var notInGroup = groupPerCluster.Item3; // If the cluster has more than one group, we need to merge them if (groups.Count > 1) { // Merge some groups ModelGroup largestGroup = null; int largestGroupSize = 0; foreach (var group in groups) { var bricksInGroup = group.GetComponentsInChildren <Brick>(true); var bricksInCluster = bricksInGroup.Count(x => cluster.Contains(x)); if (bricksInCluster >= largestGroupSize) { largestGroup = group; largestGroupSize = bricksInCluster; } } foreach (var brick in cluster) { if (brick.transform.parent == largestGroup.transform) { continue; } if (IsPartOfPrefab(brick)) { UnpackPrefab(brick, undoBehavior); } SetParent(brick.transform, largestGroup.transform, undoBehavior); } RecomputePivot(largestGroup, alignRotation, undoBehavior); var modelGO = largestGroup.transform.parent; var model = modelGO.GetComponent <Model>(); if (model) { RecomputePivot(model, alignRotation, undoBehavior); } } else if (groups.Count == 1) // In case the cluster only has one group, we need to check if the group contains bricks not in this cluster { var group = groups.FirstOrDefault(); if (!group) { continue; } var bricksInGroup = group.GetComponentsInChildren <Brick>(true); var clustersForGroup = new HashSet <HashSet <Brick> >(); // If this group contains more than one cluster, split foreach (var brick in bricksInGroup) { if (!clustersForGroup.Any(x => x.Contains(brick))) { if (brick.HasConnectivity()) { var connected = brick.GetConnectedBricks(); connected.Add(brick); clustersForGroup.Add(connected); } } } // Only split if we found multiple clusters in group if (clustersForGroup.Count > 1) { // Get the model for the group var model = GetModelInParent(group.transform); // Find all prefabs we need to unpack by looking through the clusters in the group foreach (var clusterInGroup in clustersForGroup) { // Look through each brick in the cluster foreach (var brick in clusterInGroup) { // First check if there is a brick in this cluster that is part of a prefab and not an override // If there is, then check if there is another cluster containing a prefab that is not an override // In that case, we have to unpack, because we are changing the parents of gameobjects in a prefab if (IsPartOfPrefab(brick)) { if (clustersForGroup.Any(clust => clust != clusterInGroup && clust.Any(obj => !PrefabUtility.IsAddedGameObjectOverride(obj.gameObject)))) { UnpackPrefab(brick, undoBehavior); break; } } } } // Optimization: Check for largest group containing only a single cluster and keep that group intact HashSet <Brick> largestGroupBricks = null; ModelGroup largestGroup = null; int largestGroupSize = 0; var sharedParentClusters = new HashSet <ModelGroup>(); foreach (var clusterInGroup in clustersForGroup) { var parent = clusterInGroup.First().transform.parent; var modelGroup = parent.GetComponent <ModelGroup>(); if (!modelGroup) { continue; } var skip = false; foreach (var brick in clusterInGroup) { if (brick.transform.parent != parent) { skip = true; break; } } if (skip) { continue; } if (largestGroupSize < clusterInGroup.Count()) { largestGroupSize = clusterInGroup.Count(); largestGroupBricks = clusterInGroup; largestGroup = modelGroup; } } if (largestGroupBricks != null) { clustersForGroup.Remove(largestGroupBricks); } foreach (var clusterInGroup in clustersForGroup) { var newObject = new GameObject(); var newGroup = newObject.AddComponent <ModelGroup>(); // Add LEGOModelGroupAsset component. newObject.AddComponent <LEGOModelGroupAsset>(); if (undoBehavior == UndoBehavior.withUndo) { Undo.RegisterCreatedObjectUndo(newObject, "Created new group"); } newGroup.transform.position = group.transform.position; if (model) { SetParent(newGroup.transform, model.transform, undoBehavior); } newGroup.name = group.groupName; newGroup.groupName = group.groupName; newGroup.parentName = group.parentName; newGroup.optimizations = group.optimizations; newGroup.randomizeNormals = group.randomizeNormals; foreach (var view in group.views) { newGroup.views.Add(new CullingCameraConfig() { name = view.name, perspective = view.perspective, position = view.position, rotation = view.rotation, fov = view.fov, size = view.size, minRange = view.minRange, maxRange = view.maxRange, aspect = view.aspect }); } newGroup.autoGenerated = true; foreach (var brick in clusterInGroup) { SetParent(brick.transform, newGroup.transform, undoBehavior); } RecomputePivot(newGroup, alignRotation, undoBehavior); } if (model) { RecomputePivot(model, alignRotation, undoBehavior); } } else if (notInGroup.Count > 0) { foreach (var brick in notInGroup) { if (IsPartOfPrefab(brick)) { UnpackPrefab(brick, undoBehavior); } SetParent(brick.transform, group.transform, undoBehavior); } } else { RecomputePivot(group, alignRotation, undoBehavior); var modelGO = group.transform.parent; Model model = null; bool createNewModel = (PrefabStageUtility.GetCurrentPrefabStage() != null && modelGO && !modelGO.GetComponent <Model>()) || (PrefabStageUtility.GetCurrentPrefabStage() == null && (!modelGO || !modelGO.GetComponent <Model>())); if (createNewModel) { model = CreateNewDefaultModel(group.name, undoBehavior); if (modelGO != null) { if (PrefabStageUtility.GetCurrentPrefabStage() == null && PrefabUtility.IsPartOfAnyPrefab(modelGO)) { UnpackPrefab(modelGO.gameObject, undoBehavior); } SetParent(model.transform, modelGO.transform, undoBehavior); } SetParent(group.transform, model.transform, undoBehavior); EditorGUIUtility.PingObject(group.gameObject); } else { model = modelGO.GetComponent <Model>(); } if (model) { RecomputePivot(model, alignRotation, undoBehavior); } } } else // No groups. { var name = cluster.FirstOrDefault()?.name; Model model = null; if (PrefabStageUtility.GetCurrentPrefabStage() != null) { var rootObject = PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot; model = rootObject.GetComponent <Model>(); if (!model) { model = CreateNewDefaultModel(name); SetParent(model.transform, rootObject.transform, undoBehavior); } } else { model = CreateNewDefaultModel(name); } ModelGroup newGroup = CreateNewDefaultModelGroup(name); SetParent(newGroup.transform, model.transform, undoBehavior); var bounds = BrickBuildingUtility.ComputeBounds(cluster, Matrix4x4.identity); model.transform.position = new Vector3(bounds.center.x, bounds.min.y, bounds.center.z); Transform originalParent = null; foreach (var brick in cluster) { if (!originalParent) { originalParent = brick.transform.parent; } if (brick.transform.parent != originalParent) { originalParent = null; break; } } if (originalParent) { SetParent(model.transform, originalParent, undoBehavior); } foreach (var brick in cluster) { SetParent(brick.transform, newGroup.transform, undoBehavior); EditorGUIUtility.PingObject(brick.gameObject); } } } var modelsInScene = StageUtility.GetCurrentStageHandle().FindComponentsOfType <Model>(); foreach (var model in modelsInScene) { var children = model.GetComponentsInChildren <Brick>(true); if (children.Length == 0) { if (undoBehavior == UndoBehavior.withUndo) { Undo.DestroyObjectImmediate(model.gameObject); } else { Object.DestroyImmediate(model.gameObject); } } } var groupsInScene = StageUtility.GetCurrentStageHandle().FindComponentsOfType <ModelGroup>(); foreach (var group in groupsInScene) { var children = group.GetComponentsInChildren <Brick>(true); if (children.Length == 0) { if (undoBehavior == UndoBehavior.withUndo) { Undo.DestroyObjectImmediate(group.gameObject); } else { Object.DestroyImmediate(group.gameObject); } } } }
// Drive state from OnEnable and OnDisable? OnEnable on RegisterLodDataInput seems to get called on script reload void OnEnable() { // We don't run in "prefab scenes", i.e. when editing a prefab. Bail out if prefab scene is detected. #if UNITY_EDITOR if (PrefabStageUtility.GetCurrentPrefabStage() != null) { return; } #endif if (!_primaryLight && _searchForPrimaryLightOnStartup) { _primaryLight = RenderSettings.sun; } if (!VerifyRequirements()) { enabled = false; return; } #if UNITY_EDITOR if (EditorApplication.isPlaying && !Validate(this, ValidatedHelper.DebugLog)) { enabled = false; return; } #endif _isFirstUpdate = true; Instance = this; Scale = Mathf.Clamp(Scale, _minScale, _maxScale); _lodTransform = new LodTransform(); _lodTransform.InitLODData(_lodCount); // Resolution is 4 tiles across. var baseMeshDensity = _lodDataResolution * 0.25f / _geometryDownSampleFactor; // 0.4f is the "best" value when base mesh density is 8. Scaling down from there produces results similar to // hand crafted values which looked good when the ocean is flat. _lodAlphaBlackPointFade = 0.4f / (baseMeshDensity / 8f); // We could calculate this in the shader, but we can save two subtractions this way. _lodAlphaBlackPointWhitePointFade = 1f - _lodAlphaBlackPointFade - _lodAlphaBlackPointFade; Root = OceanBuilder.GenerateMesh(this, _oceanChunkRenderers, _lodDataResolution, _geometryDownSampleFactor, _lodCount); CreateDestroySubSystems(); _commandbufferBuilder = new BuildCommandBuffer(); InitViewpoint(); if (_attachDebugGUI && GetComponent <OceanDebugGUI>() == null) { gameObject.AddComponent <OceanDebugGUI>().hideFlags = HideFlags.DontSave; } #if UNITY_EDITOR EditorApplication.update -= EditorUpdate; EditorApplication.update += EditorUpdate; #endif foreach (var lodData in _lodDatas) { lodData.OnEnable(); } _canSkipCulling = false; }
public static void Button(UnityEngine.Object target, MethodInfo methodInfo) { bool visible = ButtonUtility.IsVisible(target, methodInfo); if (!visible) { return; } if (methodInfo.GetParameters().All(p => p.IsOptional)) { ButtonAttribute buttonAttribute = (ButtonAttribute)methodInfo.GetCustomAttributes(typeof(ButtonAttribute), true)[0]; string buttonText = string.IsNullOrEmpty(buttonAttribute.Text) ? ObjectNames.NicifyVariableName(methodInfo.Name) : buttonAttribute.Text; bool buttonEnabled = ButtonUtility.IsEnabled(target, methodInfo); EButtonEnableMode mode = buttonAttribute.SelectedEnableMode; buttonEnabled &= mode == EButtonEnableMode.Always || mode == EButtonEnableMode.Editor && !Application.isPlaying || mode == EButtonEnableMode.Playmode && Application.isPlaying; bool methodIsCoroutine = methodInfo.ReturnType == typeof(IEnumerator); if (methodIsCoroutine) { buttonEnabled &= (Application.isPlaying ? true : false); } EditorGUI.BeginDisabledGroup(!buttonEnabled); if (GUILayout.Button(buttonText)) { object[] defaultParams = methodInfo.GetParameters().Select(p => p.DefaultValue).ToArray(); IEnumerator methodResult = methodInfo.Invoke(target, defaultParams) as IEnumerator; if (!Application.isPlaying) { // Set target object and scene dirty to serialize changes to disk EditorUtility.SetDirty(target); PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage(); if (stage != null) { // Prefab mode EditorSceneManager.MarkSceneDirty(stage.scene); } else { // Normal scene EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } } else if (methodResult != null && target is MonoBehaviour behaviour) { behaviour.StartCoroutine(methodResult); } } EditorGUI.EndDisabledGroup(); } else { string warning = typeof(ButtonAttribute).Name + " works only on methods with no parameters"; HelpBox_Layout(warning, MessageType.Warning, context: target, logToConsole: true); } }
private void Rebuild(bool regenMesh) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(terrain.gameObject); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } MeshFilter filter = terrain.GetComponent <MeshFilter>(); Mesh mesh = filter.sharedMesh; if (mesh == null) { mesh = new Mesh(); AssetDatabase.CreateAsset(mesh, "Assets/Resources/TacticsMaps/Meshes/" + terrain.gameObject.name + ".asset"); filter.sharedMesh = mesh; } quads = new Dictionary <Vector3, Dictionary <Vector3, TerrainQuad> >(); vertices = new List <Vector3>(); uvs = new List <Vector2>(); tris = new List <int>(); for (int z = 0; z < terrain.size.y; z += 1) { for (int x = 0; x < terrain.size.x; x += 1) { // top vertices float height = terrain.HeightAt(x, z); AddQuad(new Vector3(x, height, z), new Vector3(x + 1, height, z + 1), terrain.TileAt(x, z), new Vector3(x, height, z), new Vector3(0, 1, 0)); // side vertices foreach (OrthoDir dir in Enum.GetValues(typeof(OrthoDir))) { float currentHeight = terrain.HeightAt(x, z); float neighborHeight = terrain.HeightAt(x + dir.Px3DX(), z + dir.Px3DZ()); if (currentHeight > neighborHeight) { Vector2 off1 = Vector2.zero, off2 = Vector2.zero; switch (dir) { case OrthoDir.South: off1 = new Vector2(0, 0); off2 = new Vector2(1, 0); break; case OrthoDir.East: off1 = new Vector2(1, 1); off2 = new Vector2(1, 0); break; case OrthoDir.North: off1 = new Vector2(1, 1); off2 = new Vector2(0, 1); break; case OrthoDir.West: off1 = new Vector2(0, 0); off2 = new Vector2(0, 1); break; } for (float y = neighborHeight; y < currentHeight; y += 0.5f) { AddQuad(new Vector3(x + off1.x, y, z + off1.y), new Vector3(x + off2.x, y + 0.5f, z + off2.y), terrain.TileAt(x, z, y, dir), new Vector3(x, y + 0.5f, z), dir.Px3D()); } } } } } if (regenMesh) { selectedQuads.Clear(); mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.triangles = tris.ToArray(); mesh.uv = uvs.ToArray(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); } }