/// <summary> /// Initializes a new instance of the <see cref="LodGroupNode"/> class. /// </summary> /// <param name="capacity">The initial capacity of the LOD collection.</param> public LodGroupNode(int capacity) { // The actual value of the following flags does not matter. The LodGroupNodes // need be handled explicitly in scene queries! IsRenderable = true; CastsShadows = true; Levels = new LodCollection(this, capacity); }
// Instantiates the correct node type based on IDs found. public BaseNode ReadNodeAt(int offset, object context) { int preHeaderOffset = 0; if (nodeCache.ContainsKey(offset)) { return(nodeCache[offset]); } Seek(offset); int majorId = ReadInt32(); int minorId = ReadInt32(); // Edge case: one block type doesn't start with major/minor type id and actually start with another offset. // So peek ahead one more long and shuffle numbers where they go. // This may not work if globalOffset is 0. // Should be a pointer to an offset containing string "Tex00000" or similar. int peek = ReadInt32(); if (majorId > globalOffset && minorId == (long)Major.Texture) { preHeaderOffset = majorId; majorId = minorId; minorId = peek; } else if (majorId > globalOffset && minorId == 0 && peek == 1) { // This is a weird subtype found in SHUTTLE.OPT return(new NamedNodeCollection(this, majorId)); } else { BaseStream.Seek(-4, SeekOrigin.Current); } // Figure out the type of node and build appropriate object. BaseNode node; switch (majorId) { case (int)Major.Generic: switch (minorId) { case (int)GenericMinor.Branch: node = new NodeCollection(this) as BaseNode; break; case (int)GenericMinor.MeshVertex: node = MakeGenericNode(typeof(MeshVertices <>), new Type[] { Vector3T }); break; case (int)GenericMinor.TextureVertex: node = MakeGenericNode(typeof(VertexUV <>), new Type[] { Vector2T }); break; case (int)GenericMinor.TextureReferenceByName: node = new TextureReferenceByName(this) as BaseNode; break; case (int)GenericMinor.VertexNormal: node = MakeGenericNode(typeof(VertexNormals <>), new Type[] { Vector3T }); break; case (int)GenericMinor.Hardpoint: node = MakeGenericNode(typeof(Hardpoint <>), new Type[] { Vector3T }); break; case (int)GenericMinor.Transform: node = MakeGenericNode(typeof(RotationInfo <>), new Type[] { Vector3T }); break; case (int)GenericMinor.MeshLod: node = new LodCollection(this) as BaseNode; break; case (int)GenericMinor.FaceList: node = MakeGenericNode(typeof(FaceList <>), new Type[] { Vector3T }); break; case (int)GenericMinor.SkinSelector: node = new SkinCollection(this) as BaseNode; break; case (int)GenericMinor.MeshDescriptor: node = MakeGenericNode(typeof(PartDescriptor <>), new Type[] { Vector3T }); break; case (int)GenericMinor.EngineGlow: node = MakeGenericNode(typeof(EngineGlow <>), new Type[] { Vector3T }); break; default: logger?.Invoke("Found unknown node type " + majorId + " " + minorId + " at " + BaseStream.Position + " context:" + context); node = new BaseNode(this); break; } break; case (int)Major.Texture: switch (minorId) { case (int)TextureMinor.Texture: node = new Texture(this, preHeaderOffset); break; case (int)TextureMinor.TextureWithAlpha: node = new Texture(this, preHeaderOffset); break; default: logger?.Invoke("Found unknown node type " + majorId + " " + minorId + " at " + BaseStream.Position + " context:" + context); node = new Texture(this, preHeaderOffset); break; } break; default: node = new BaseNode(this); break; } nodeCache[offset] = node; return(node); }