/// <summary> /// Instantiate game objects for each brick in an LXFML-file /// </summary> /// <param name="lxfml">The LXFML-file</param> /// <param name="colliders">Add colliders to part</param> /// <param name="connectivity">Add connectivity to part</param> /// <param name="isStatic">Make the part static</param> /// <param name="lightmapped">Instantiate meshes with or without lightmap UVs</param> /// <param name="randomizeRotation">Slightly rotate rotation of part</param> /// <param name="preferLegacy">Choose legacy meshes if available</param> /// <param name="lod">Instantiate meshes of a certain LOD</param> /// <param name="resultBricks">Dictionary that contains brick component, using refID as key</param> /// <param name="groupNumber">If non-negative, only instantiate bricks from the specified group number</param> public static void InstantiateModelBricks(LXFMLDoc lxfml, DictionaryIntToModelGroupImportSettings importSettings, ref Dictionary <int, Brick> resultBricks, int groupNumber = -1) { for (var i = 0; i < lxfml.bricks.Count; ++i) { if (i % 200 == 0) { EditorUtility.DisplayProgressBar("Importing", "Creating bricks.", ((float)i / lxfml.bricks.Count) * 0.7f); } var brick = lxfml.bricks[i]; var group = FindGroup(lxfml, brick); // Discard bricks from other groups if group number is specified. if (groupNumber >= 0 && group != null && group.number != groupNumber) { continue; } // Determine whether or not to be static and to generate light map UVs. var brickStatic = (group != null ? importSettings[group.number].isStatic : false); var brickLightmapped = brickStatic && (group != null ? importSettings[group.number].lightmapped : false); var brickLod = (group != null ? importSettings[group.number].lod : 0); var brickGO = new GameObject(brick.designId, typeof(Brick)); var brickComp = brickGO.GetComponent <Brick>(); Undo.RegisterCreatedObjectUndo(brickGO, "Brick"); foreach (var part in brick.parts) { GameObject partToInstantiate = null; var partExistenceResult = PartUtility.UnpackPart(part.partDesignId, brickLightmapped, group != null ? importSettings[group.number].preferLegacy : false, brickLod); if (partExistenceResult.existence != PartUtility.PartExistence.None) { // FIXME Make a note of changed design ids. partToInstantiate = PartUtility.LoadPart(partExistenceResult.designID, brickLightmapped, partExistenceResult.existence == PartUtility.PartExistence.Legacy, brickLod); } if (partToInstantiate == null) { Debug.LogError("Missing part FBX -> " + partExistenceResult.designID); continue; } var partGO = Object.Instantiate(partToInstantiate); partGO.name = partToInstantiate.name; // Assign legacy, material IDs and set up references. var partComp = partGO.AddComponent <Part>(); partComp.designID = Convert.ToInt32(part.partDesignId); partComp.legacy = partExistenceResult.existence == PartUtility.PartExistence.Legacy; foreach (var material in part.materials) { partComp.materialIDs.Add(material.colorId); } partComp.brick = brickComp; brickComp.parts.Add(partComp); if (partExistenceResult.existence == PartUtility.PartExistence.New) { // FIXME Handle normal mapped model. InstantiateKnobsAndTubes(partComp, brickLightmapped, brickLod); } // Create collider and connectivity information. var brickColliders = (group != null ? importSettings[group.number].colliders : false); var brickConnectivity = brickColliders && (group != null ? importSettings[group.number].connectivity : false); if (brickColliders) { GameObject collidersToInstantiate = null; var collidersAvailable = PartUtility.UnpackCollidersForPart(partExistenceResult.designID); if (collidersAvailable) { collidersToInstantiate = PartUtility.LoadCollidersPrefab(partExistenceResult.designID); } if (collidersToInstantiate == null && partExistenceResult.existence != PartUtility.PartExistence.Legacy) { Debug.LogError("Missing part collider information -> " + partExistenceResult.designID); } if (collidersToInstantiate) { var collidersGO = Object.Instantiate(collidersToInstantiate); collidersGO.name = "Colliders"; collidersGO.transform.SetParent(partGO.transform, false); var colliderComps = collidersGO.GetComponentsInChildren <Collider>(); partComp.colliders.AddRange(colliderComps); } } if (brickConnectivity) { GameObject connectivityToInstantiate = null; var connectivityAvailable = PartUtility.UnpackConnectivityForPart(partExistenceResult.designID); if (connectivityAvailable) { connectivityToInstantiate = PartUtility.LoadConnectivityPrefab(partExistenceResult.designID); } if (connectivityToInstantiate == null && partExistenceResult.existence != PartUtility.PartExistence.Legacy) { Debug.LogError("Missing part connectivity information -> " + partExistenceResult.designID); } if (connectivityToInstantiate) { var connectivityGO = Object.Instantiate(connectivityToInstantiate); connectivityGO.name = "Connectivity"; connectivityGO.transform.SetParent(partGO.transform, false); var connectivityComp = connectivityGO.GetComponent <Connectivity>(); partComp.connectivity = connectivityComp; brickComp.totalBounds.Encapsulate(connectivityComp.extents); connectivityComp.part = partComp; foreach (var field in connectivityComp.connectionFields) { foreach (var connection in field.connections) { MatchConnectionWithKnob(connection, partComp.knobs); MatchConnectionWithTubes(connection, partComp.tubes); } } } } SetMaterials(partComp, part.materials, partExistenceResult.existence == PartUtility.PartExistence.Legacy); SetDecorations(partComp, part.decorations, partExistenceResult.existence == PartUtility.PartExistence.Legacy); SetStaticAndGIParams(partGO, brickStatic, brickLightmapped, true); // Set Position & Rotation SetPositionRotation(partGO, part); if (group != null ? importSettings[group.number].randomizeRotation : false) { RandomizeRotation(partComp, brickConnectivity); } // If first part, place brick at same position. if (brickGO.transform.childCount == 0) { brickGO.transform.position = partGO.transform.position; brickGO.transform.rotation = partGO.transform.rotation; brickGO.transform.localScale = Vector3.one; } partGO.transform.SetParent(brickGO.transform, true); if (!brickConnectivity) { var worldBounds = ComputeBounds(partGO.transform); worldBounds.SetMinMax(brickComp.transform.InverseTransformPoint(worldBounds.min), brickComp.transform.InverseTransformPoint(worldBounds.max)); brickComp.totalBounds.Encapsulate(worldBounds); } } // If all parts were missing, discard brick. if (brickGO.transform.childCount == 0) { Undo.DestroyObjectImmediate(brickGO); continue; } SetStaticAndGIParams(brickGO, brickStatic, brickLightmapped); // Assign uuid brickComp.designID = Convert.ToInt32(brick.designId); brickComp.uuid = brick.uuid; // Add LEGOAsset component. brickGO.AddComponent <LEGOAsset>(); resultBricks[brick.refId] = brickComp; } }
private static bool UpdateConnections(Brick[] bricks) { var updated = false; foreach (var brick in bricks) { if (PrefabUtility.IsPartOfPrefabInstance(brick)) { continue; } foreach (var part in brick.parts) { var designID = part.designID.ToString(); if (!PartUtility.CheckIfConnectivityForPartIsUnpacked(designID)) { PartUtility.UnpackConnectivityForPart(designID); } var connectivity = part.connectivity; if (!connectivity) { // Unsupported or legacy. continue; } if (connectivity.version == currentVersion) { // Already up to date. continue; } var connectivityToInstantiate = PartUtility.LoadConnectivityPrefab(designID); if (connectivityToInstantiate) { GameObject.DestroyImmediate(connectivity.gameObject, true); var connectivityGO = UnityEngine.Object.Instantiate(connectivityToInstantiate); connectivityGO.name = "Connectivity"; connectivityGO.transform.SetParent(part.transform, false); var connectivityComp = connectivityGO.GetComponent <Connectivity>(); part.connectivity = connectivityComp; part.brick.totalBounds.Encapsulate(connectivityComp.extents); connectivityComp.part = part; updated = true; foreach (var tube in part.tubes) { tube.connections.Clear(); tube.field = null; } foreach (var knob in part.knobs) { knob.field = null; knob.connectionIndex = -1; } foreach (var field in connectivityComp.connectionFields) { foreach (var connection in field.connections) { ModelImporter.MatchConnectionWithKnob(connection, part.knobs); ModelImporter.MatchConnectionWithTubes(connection, part.tubes); } } } } } return(updated); }