public void Init(AutoFenceCreator inAFB) { afb = inAFB; tempPostColliderMode = afb.postColliderMode; tempRailColliderMode = afb.railColliderMode; tempExtraColliderMode = afb.extraColliderMode; tempAllowGaps = afb.allowGaps; tempShowDebugLines = afb.showDebugGapLine; parent = inAFB.finishedFoldersParent; }
public void Init(AutoFenceCreator inAFB, string inModeString, Transform inParentFolder) { afb = inAFB; modeString = inModeString; parentFolder = inParentFolder; if (modeString == "FinishAndStartNew") { fenceName = "Finished Fence"; } else if (modeString == "FinishAndDuplicate") { fenceName = "Finished Duplicated Fence"; } }
void OnEnable() { script = (AutoFenceCreator)target; gs = serializedObject.FindProperty("gs"); scaleInterpolationAlso = serializedObject.FindProperty("scaleInterpolationAlso"); railGaps = serializedObject.FindProperty("railGaps"); numRails = serializedObject.FindProperty("numRails"); railPositionOffset = serializedObject.FindProperty("railPositionOffset"); railSize = serializedObject.FindProperty("railSize"); railRotation = serializedObject.FindProperty("railRotation"); autoHideBuriedRails = serializedObject.FindProperty("autoHideBuriedRails"); fenceHeight = serializedObject.FindProperty("fenceHeight"); postHeightOffset = serializedObject.FindProperty("postHeightOffset"); postSize = serializedObject.FindProperty("postSize"); postRotation = serializedObject.FindProperty("postRotation"); randomness = serializedObject.FindProperty("randomness"); smooth = serializedObject.FindProperty("smooth"); roundingDistance = serializedObject.FindProperty("roundingDistance"); interpolate = serializedObject.FindProperty("interpolate"); //subsFixedOrProportionalSpacing = serializedObject.FindProperty("subsFixedOrProportionalSpacing"); subSpacing = serializedObject.FindProperty("subSpacing"); showSubs = serializedObject.FindProperty("showSubs"); subPositionOffset = serializedObject.FindProperty("subPositionOffset"); subSize = serializedObject.FindProperty("subSize"); subRotation = serializedObject.FindProperty("subRotation"); showControls = serializedObject.FindProperty("showControls"); closeLoop = serializedObject.FindProperty("closeLoop"); frequency = serializedObject.FindProperty("frequency"); amplitude = serializedObject.FindProperty("amplitude"); wavePosition = serializedObject.FindProperty("wavePosition"); useWave = serializedObject.FindProperty("useWave"); useSubJoiners = serializedObject.FindProperty("useSubJoiners"); addColliders = serializedObject.FindProperty("addColliders"); allowGaps = serializedObject.FindProperty("allowGaps"); showDebugGapLine = serializedObject.FindProperty("showDebugGapLine"); gs.floatValue = 1.0f; }
//======================================================================= //-- Optionally pass in a reference mesh to hint at its size (i.e. the mesh you will be replacing) // If so, we take it that we wnat the new user mesh to be modified to fit in witht the current fence design public static GameObject CreateUncombinedAFBRailFromGameObject(GameObject inGO, AutoFenceCreator afb, GameObject inRefMesh = null) { if (inGO == null) { return(null); } //--- Instantiate a copy and zero its rotations---- GameObject thisGO = null, copyGO = GameObject.Instantiate(inGO); //copyGO.name = "copyGO"; //named to track during debug copyGO.transform.rotation = Quaternion.identity; //--- Get all GameObjects/MeshFilters and Meshes in the group and calculate the combined bounds --- List <GameObject> allMeshGameObjects = GetAllMeshGameObjectsFromGameObject(copyGO); List <MeshFilter> allMeshFilters = GetAllMeshFiltersFromGameObject(copyGO); List <Mesh> allMeshes = GetAllMeshesFromGameObject(copyGO); if (allMeshes == null || allMeshes.Count == 0) { return(null); } Bounds bounds, combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); Vector3 goScale = copyGO.transform.localScale, center, max, refSize = Vector3.one; int numNonLODMeshes = CountNonLODMeshes(copyGO); Mesh newMesh, thisMesh; List <Mesh> newMeshes = new List <Mesh>(); for (int i = 0; i < allMeshes.Count; i++) { newMesh = DuplicateMesh(allMeshes[i]); newMeshes.Add(newMesh); } //=========== Should we Rotate? ===================== float xRot = 0, yRot = 0, zRot = 0; if (afb.railBakeRotationMode == 1 || afb.railBakeRotationMode == 0) // 0 = user custom settings, 1 = auto, 2 = don't rotate mesh { if (afb.railBakeRotationMode == 1 && combinedBounds.size.z > combinedBounds.size.x * 1.5f) { yRot = 90; } else if (afb.railBakeRotationMode == 0) { yRot = afb.railUserMeshBakeRotations.y; } if (yRot != 0) // its length is along z instead of x, this is the most common error, so do it first { // The worst case scenario is when you have multiple along the z-axis. They need to be mesh-rotated and GO-rotated separately, then re-aligned Vector3 groupCentre = combinedBounds.center; for (int i = 0; i < allMeshes.Count; i++) // need to loop each set seperately so that we get the correct new bounds size { RotateMesh(newMeshes[i], new Vector3(0, yRot, 0), true); RecentreMeshOnAxis(newMeshes[i], "z"); allMeshFilters[i].sharedMesh = newMeshes[i]; // put back in to the GO afb.autoRotationResults.y = afb.railUserMeshBakeRotations.y = yRot; if (afb.railBakeRotationMode == 1) { Debug.Log(copyGO.name + " was Auto rotated " + yRot + " on the Y axis to suit wall/rail orientation (See 'XYZ') \n"); } thisGO = allMeshGameObjects[i]; Vector3 realLocalPos = thisGO.transform.position - copyGO.transform.position; Vector3 newLocalPos = RotatePointAroundPivot(realLocalPos, Vector3.zero, new Vector3(0, yRot, 0)); float xTrans = (-realLocalPos.x + newLocalPos.x); float zTrans = (-realLocalPos.z + newLocalPos.z); float x2 = (newMeshes[i].bounds.size.x / 2) * thisGO.transform.localScale.z; if (yRot == 90) { xTrans -= x2; } else if (yRot == -90) { xTrans += x2; } thisGO.transform.Translate(xTrans, 0, zTrans); Vector3 newLocalScale = new Vector3(thisGO.transform.localScale.z, thisGO.transform.localScale.y, thisGO.transform.localScale.x); thisGO.transform.localScale = newLocalScale; bounds = newMeshes[i].bounds; Debug.Log(bounds); } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } //---------- X --------------- if (afb.railBakeRotationMode == 1 && combinedBounds.size.z > combinedBounds.size.y * 1.99f) { xRot = 90; } else if (afb.railBakeRotationMode == 0) { xRot = afb.railUserMeshBakeRotations.x; } if (xRot != 0) // seems to be lying on its side { for (int i = 0; i < allMeshes.Count; i++) { RotateMesh(newMeshes[i], new Vector3(xRot, 0, 0), true); allMeshFilters[i].sharedMesh = newMeshes[i]; afb.autoRotationResults.x = afb.railUserMeshBakeRotations.x = xRot; Debug.Log(copyGO.name + " was Auto rotated " + xRot + " on the X axis to suit wall/rail orientation (See 'XYZ') \n"); } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } //---------- Z --------------- if (afb.railBakeRotationMode == 1 && combinedBounds.size.y > combinedBounds.size.x * 1.99f) { zRot = 90; } else if (afb.railBakeRotationMode == 0) { zRot = afb.railUserMeshBakeRotations.z; } if (zRot != 0) // seems to be standing up on its end { for (int i = 0; i < allMeshes.Count; i++) { RotateMesh(newMeshes[i], new Vector3(0, 0, zRot), true); allMeshFilters[i].sharedMesh = newMeshes[i]; afb.autoRotationResults.z = afb.railUserMeshBakeRotations.z = zRot; Debug.Log(copyGO.name + " was Auto rotated " + zRot + " on the Z axis to suit wall/rail orientation (See 'XYZ') \n"); } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); afb.userSubMeshRailOffsets = GetRelativePositionsOfAllGameObjects(copyGO); //========== Create Clones and reposition the mesh vertices so pivot is central and at base ============ center = combinedBounds.center; max = combinedBounds.max; float yMove = combinedBounds.min.y; Vector3 scale = Vector3.zero; float scaleFactorX = 3.0f / combinedBounds.size.x; // Set x scaling, 3 = default rail length float scaleFactorZ = scaleFactorX, scalefactorY = (1 + scaleFactorX) / 2; // scalefactorY is just an average that gives useable height, no matter what the design float scaleFactorHeight = 1.0f / combinedBounds.size.y; float proportionXZ = combinedBounds.size.x / combinedBounds.size.z; // restrict the thickness to 1/3 of the length as an initial default if (proportionXZ < 3) { scaleFactorZ = scaleFactorX * proportionXZ / 3; } for (int i = 0; i < allMeshes.Count; i++) { newMesh = newMeshes[i]; thisGO = allMeshGameObjects[i]; scale = thisGO.transform.lossyScale; float xShift = -newMesh.bounds.max.x; thisGO.transform.position += new Vector3(-max.x, 0, 0); // shift the transforms, so the edges are at the correct starting position newMesh = TranslateMesh(newMesh, new Vector3(xShift, 0, 0)); //shift the pivot thisGO.transform.position += new Vector3(-xShift * scale.x, 0, 0); // move the transform again to compensate for the pivot move newMesh = ScaleMesh(newMesh, new Vector3(scaleFactorX, 1, scaleFactorZ)); // scale everything newMesh.RecalculateBounds(); allMeshFilters[i].sharedMesh = newMesh; // put back in to the GO //---------------------------------------- float realLocalPosX = thisGO.transform.position.x - copyGO.transform.position.x; float maxXScaled = newMesh.bounds.max.x * thisGO.transform.lossyScale.x; float newMaxXScaledAndPositioned = maxXScaled + realLocalPosX; } //----scale the localPosition all objects that aren't the parent, to maintain the correct relationship------ //--- Do it in a seperate loop as we need all gos, even if they're empty folders, as they may have transform offsets ---- Transform[] allObjects = copyGO.GetComponentsInChildren <Transform>(true); //orig for (int i = 0; i < allObjects.Length; i++) { thisGO = allObjects[i].gameObject; if (thisGO != copyGO) { thisGO.transform.localPosition = new Vector3(thisGO.transform.localPosition.x * scaleFactorX, thisGO.transform.localPosition.y, thisGO.transform.localPosition.z); } } //========= Remove Colliders ======================= UpdateAllColliders(ref allMeshGameObjects); // replaces the colliders with the newly scaled-mesh sizes SetEnabledStatusAllColliders(ref allMeshGameObjects, false); Debug.Log("Created new user Rail: " + copyGO.name); return(copyGO); }
//======================================================================= public static GameObject CreateAFBPostFromGameObject(GameObject inGO, AutoFenceCreator afb, GameObject inRefMesh = null) { if (inGO == null) { return(null); } //--- Instantiate a copy and zero its rotations---- GameObject thisGO = null, copyGO = GameObject.Instantiate(inGO); copyGO.transform.rotation = Quaternion.identity; //--- Get all GameObjects/MeshFilters and Meshes in the group and calculate the combined bounds --- List <GameObject> allMeshGameObjects = GetAllMeshGameObjectsFromGameObject(copyGO); List <MeshFilter> allMeshFilters = GetAllMeshFiltersFromGameObject(copyGO); List <Mesh> allMeshes = GetAllMeshesFromGameObject(copyGO); Bounds combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); Vector3 goScale = copyGO.transform.localScale, center, max, refSize = Vector3.one; Mesh newMesh = null; List <Mesh> newMeshes = new List <Mesh>(); for (int i = 0; i < allMeshes.Count; i++) { newMesh = DuplicateMesh(allMeshes[i]); newMeshes.Add(newMesh); } //=========== Should we Rotate? ===================== float xRot = 0, yRot = 0, zRot = 0; if (afb.postBakeRotationMode == 1 || afb.postBakeRotationMode == 0) // 0 = user custom settings, 1 = auto, 2 = don't rotate mesh { //---------- Z --------------- if (afb.postBakeRotationMode == 1 && combinedBounds.size.x > combinedBounds.size.y * 1.99f) { zRot = 90; } else if (afb.postBakeRotationMode == 0) { zRot = afb.postUserMeshBakeRotations.z; } if (zRot != 0) // its length is along z instead of x, this is the most common error, so do it first { for (int i = 0; i < newMeshes.Count; i++) { RotateMesh(newMeshes[i], new Vector3(0, 0, zRot), true); allMeshFilters[i].sharedMesh = newMeshes[i]; afb.autoRotationResults.z = afb.railUserMeshBakeRotations.z = zRot; newMeshes[i].RecalculateNormals(); if (afb.postBakeRotationMode == 1) { Debug.Log(copyGO.name + " was Auto rotated 90 on the Z axis to suit post orientation\n"); } } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } //---------- X --------------- if (afb.postBakeRotationMode == 1 && combinedBounds.size.z > combinedBounds.size.y * 1.99f) { xRot = 90; } else if (afb.postBakeRotationMode == 0) { xRot = afb.postUserMeshBakeRotations.x; } if (xRot != 0) // its length is along z instead of x, this is the most common error, so do it first { for (int i = 0; i < newMeshes.Count; i++) { RotateMesh(newMeshes[i], new Vector3(xRot, 0, 0), true); allMeshFilters[i].sharedMesh = newMeshes[i]; afb.autoRotationResults.z = afb.railUserMeshBakeRotations.z = xRot; newMeshes[i].RecalculateNormals(); if (afb.postBakeRotationMode == 1) { Debug.Log(copyGO.name + " was Auto rotated 90 on the X axis to suit post orientation\n"); } } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } //---------- Y --------------- if (afb.postBakeRotationMode == 0) // Y is only user-rotated, never Auto { yRot = afb.postUserMeshBakeRotations.y; } if (yRot != 0) // its length is along z instead of x, this is the most common error, so do it first { for (int i = 0; i < newMeshes.Count; i++) { RotateMesh(newMeshes[i], new Vector3(0, yRot, 0), true); newMeshes[i].RecalculateNormals(); allMeshFilters[i].sharedMesh = newMeshes[i]; afb.autoRotationResults.y = afb.railUserMeshBakeRotations.z = yRot; } combinedBounds = GetCombinedBoundsOfAllMeshesInGameObject(copyGO, true); } } //========== Create Clones and reposition the mesh vertices so pivot is central and at base ============ center = combinedBounds.center; max = combinedBounds.max; float yMove = combinedBounds.min.y; Vector3 scale = Vector3.zero; float scaleFactorHeight = 1.0f / combinedBounds.size.y; for (int i = 0; i < allMeshes.Count; i++) { thisGO = allMeshGameObjects[i]; scale = thisGO.transform.lossyScale; newMesh = newMeshes[i]; newMesh = TranslateMesh(newMesh, new Vector3(-center.x / scale.x, -yMove / scale.y, -center.z / scale.z)); newMesh = ScaleMesh(newMesh, new Vector3(scaleFactorHeight, scaleFactorHeight, scaleFactorHeight)); // scale everything newMesh.RecalculateBounds(); allMeshFilters[i].sharedMesh = newMesh; } //======== scale the localPosition all objects that aren't the parent, to maintain the correct relationship ===== //Do it in a seperate loop as we need all gos, even if they're empty folders as they may have transform offsets Transform[] allObjects = copyGO.GetComponentsInChildren <Transform>(true); for (int i = 0; i < allObjects.Length; i++) { thisGO = allObjects[i].gameObject; if (thisGO != copyGO) { thisGO.transform.localPosition *= scaleFactorHeight; } } //========= Remove Colliders ======================= UpdateAllColliders(ref allMeshGameObjects); // replaces the colliders with the newly scaled-mesh sizes SetEnabledStatusAllColliders(ref allMeshGameObjects, false); Debug.Log("Created new user Post: " + copyGO.name); return(copyGO); }