RootBlock paradigm

Eyeshot 2020 includes a Block, called RootBlock, that represents the scene root. This means that every single piece of geometry is always inside a Block definition. There is no longer a collection of entities associated with the environment, the Environment.Entities collection is now a shortcut that refers always to a Block.Entities collection, normally of the RootBlock if you don't work with the assembly navigation features.


The BlockKeyedCollection, if and only if assigned to an Environment, always has a root block defined. The root block is not typed, has no properties different than other blocks, it simply must be identified to initialize the scene when a new BlockKeyedCollection is assigned to an environment. For it, you have to use the BlockKeyedCollection.SetRootBlock(string key) method:

BlockKeyedCollection blocks = new BlockKeyedCollection();
string name = "MyRootBlock";
blocks.Add(new Block(name));
model1.Blocks = blocks;

Once the BlockKeyedCollection is assigned to an environment, the root block can't be removed, but you can rename it simply by changing its name property or replace it:

model.RootBlock.Name = "newName";

The name of the RootBlock is stored in the BlockKeyedCollection.RootBlockName. If this string is null or empty, the collection doesn't have a root block specified. To get an instance, there is the Environment.RootBlock shortcut.

Block with EntityList

The Block.Entities collection is now an EntityList, no longer a simple List<Entity>. Properties and methods of the EntityList work now at block level so it's possible to operate only in a specified context and not on the whole scene. To work on the whole scene you should always refer to the RootBlock.

For example:

block.Entities.Regen(); //regenerates only the entities of the block
model1.RootBlock.Entities.Regen(); //regenerates all the entities of the root block that are also all the entities of the model.

Now when an entity is added to a Block already assigned to an Environment it's automatically regenerated. It's highly recommended to fill the block entities before adding it to the Environment.Blocks collection to prevent performance slow down during the geometry loading. For editing/reorganization of already loaded geometry, it's possible to temporarily suspend the automatic regeneration with BlockKeyedCollection.TakeOffLine(), to resume it call BlockKeyedCollection.BringOnline().

The following features, which are strictly related to the control, are moved from the EntityList to the Environment.

UpdateBoundingBox: the scene bounding box is now updated by Environment.UpdateBoundingBox(), because it needs to manage also the OverrideSceneExtents option. This method updates also the Turbo representation. Block.Entities.UpdateBoundingBox() works only at block level, so each block has now its own bounding box.

Assembly Navigation: see the related article.

Visual Refinement Deviation: it is now always computed based on the RootBlock extents. It's possible to use a custom value by overriding the Environment.GetVisualRefinementDeviation() method.


For the file formats that support the root block, the default behavior of the various AddToScene methods is to replace the environment root block with the one loaded from the file. To change this behavior you must use the AddToScene method that accepts the replaceRootBlock flag as a parameter.

Generally, in writer classes, we use the root block entities as main entities to be exported, but it's still possible to specify the desired list of entities by using the constructor with the collections:

Brep box = Brep.CreateBox(10, 10, 10);
WriteFileParams writeFileParams = new WriteFileParams(new Entity[]{box});
WriteFile writeFile = new WriteFile(writeFileParams, "box.eye");

Adding the file contents to an existing 3D scene

A small example of how to insert the content of a file (*.eye or *.igs, *.stp, *.stl, etc.) to the existing 3D scene follows. In the case that the file contains a root block, its name may collide with the current one, so we need to change it.

ReadFileAsyncWithBlocks rfawb = rfa as ReadFileAsyncWithBlocks;
if (rfawb == null || rfawb.Blocks.RootBlockName == null) { rfa.FillAllCollectionsData(model1); model1.Entities.AddRange(rfa.Entities); } else // the file contains a root block with a name that may collide with current one { const string newName = "dummy"; rfawb.Blocks["RootBlock"].Name = newName; rfawb.FillAllCollectionsData(model1); Entity ent = new BlockReference(newName); model1.Entities.Add(ent); }

You can read more on this topic here.

Was this article helpful?
3 out of 4 found this helpful
Have more questions? Submit a request



Please sign in to leave a comment.