To access the tutorials in CityEngine, click Help > Download Tutorials and Examples.... After choosing a tutorial or example, the project is automatically downloaded and added to your workspace.
Prerequisites
- CityEngine 2017.0 or later
Introduction
This tutorial shows how to make local edits in CityEngine. Starting from where Tutorial 6 left off, you will add code to begin enabling local edits. Using local edits, you can modify individual window sizes, make alterations to the ground floor, and add selective balconies without the need to specify these local variations in the CGA code.
Modify individual windows
- Open the Simple_Building_LE_01.cej scene.
- Open the Simple_Building_LE_01.cga rule file.
Local edits are available on attributes that have handles. To enable local editing of window sizes, attributes for the windows dimensions are created, the Tile rule is modified to use these attributes, and handles are added to the attributes.
- In the Simple_Building_LE_01.cga rule file, add attributes for the window width and height.
attr window_width = 2 attr window_height = 1.5
- Find the Tile rule and replace the exact values for the window size with these attributes.
A tile contains a window with some surrounding wall on all four sides. The Tile rule creates the window with the desired width and height in the center of the tile.
Tile --> split(x){ ~1 : Wall | window_width: split(y){ ~1: Wall | window_height: Window | ~1: Wall } | ~1 : Wall }
- Add handles to the attributes.
@Handle(shape=Window, axis=x) attr window_width = 2 @Handle(shape=Window) attr window_height = 1.5
- Save the CGA file and regenerate the building by clicking Generate on the main toolbar or pressing Ctrl + G.
- Pull on the window handles.
This changes the window size for all the windows in the same way.
With local edits, it is possible to change the width of each window individually even though only one attribute for window width exists in the rule.
- Reset all attributes by clicking the Reset tool on the toolbar.
- Enable local edits mode by clicking the Local Edits tool on the toolbar.
- Select a window.
The orange highlighting in the viewport indicates the current selection. The attributes in the Inspector that are also highlighted in orange are those that can be locally edited for the current selection. The attributes window_width and window_height can be locally set for just this window.
- Pull on the handles for window width and height to change the size of this window only.
In the Inspector, the * symbol next to the window_width and window_height attributes indicate that these attributes have been locally edited for the current selection.
With multiple selections, the same local edit can be applied to multiple windows at the same time.
- Press Shift while selecting a few windows to select multiple components.
Press Ctrl while selecting to toggle items in the selection - already selected items will be removed.
- Change the size of the windows in the selection either by pulling on the handles or by entering a value in the Inspector.
Windows above a door are often smaller because that’s where the staircase is. You can undo all previous changes and create this using local edits.
- To undo all local edits, right click in the Viewport or Inspector > Reset all local edits.
- Select a window above the door.
- Press End to select all windows in the column above the door.
The Home and End keys cycle backwards and forwards through available patterns. Patterns are automatically detected based on the shape tree and how the CGA code creates the shape tree. In this case, the option available is the selection of the column of windows above the ground floor.
- Make the windows smaller either by pulling on the handles or by entering a value in the Inspector.
Make the ground floor different
Ground floors are often different from the upper floors of a building. For example, ground floor windows are typically larger than upper floor windows. This simple building rule uses the same window tiling code to create the same window tiles on all floors. With local edits, the ground floor windows on the front of the building can be made bigger without needing to write a separate rule for the ground floor tiles.
- Open the Simple_Building_LE_02.cej scene.
- Open the Simple_Building_LE_02.cga rule file.
- In the Simple_Building_LE_02.cga rule file, add a handle to the attribute tile_width. This allows the attribute to be locally editable.
@Handle(shape=Tile, axis=x) @Range(min=1, max=10, restricted=false) attr tile_width = rand(2.5,6)
- Save the CGA file and regenerate the building.
- In local edits mode, select a window on the ground floor, and change its tile width, window width, and window height.
This changes one tile on the ground floor. However, the goal is to change all the tiles on the ground floor. This is possible by selecting shapes at a higher level.
- Press PageUp to go up one level in the local edits hierarchy.
Now all the windows on the ground floor are selected and highlighted in orange. The PageUp and PageDown keys move up to higher levels and move down to lower levels, respectively. Local edits are linked to the shape tree, and they can be applied to multiple objects, such as all windows on a floor, by putting the edits on higher levels of the shape tree.
- Increase the window width to make the windows on the ground floor bigger.
This changes all the windows on the ground floor except for the first window that was changed in Step 5. This is because the edits made to the first window in Step 5 were at a lower level. When multiple edits on the same object exist, the edit made at the lowest level has precedence.
In the Inspector, the down arrow ↓ next to the tile_width, window_width, and window_height attributes indicates that these attributes have been edited at a lower level than the current selection level. The * symbol next to the window_width attribute means it has also been edited at the current selection level. Since all ground floor windows should be the same, the changes made at the lower level to the inconsistent window should be undone.
- Select the inconsistent window at a lower level by using PageDown to move down a level.
- Right click in the Viewport or in the Inspector > Reset highlighted local edits.
- Select the ground floor windows using PageUp.
- Increase the tile width, window width, and window height to make the ground floor windows bigger.
Now all windows have the same size since there are no local edits at a lower level. You may need to reselect the ground floor windows if the orange highlight is lost after the tile width change.
Add balconies
Providing options to add geometry or details to the building locally is possible, but there needs to be a way for users to access the handle when the geometry doesn’t exist. For example, local edits can be used to put balconies on select windows. To do this, the balcony needs to have sibling geometry. This sibling geometry allows access to the balcony’s handle even when the balcony does not exist.
- Open the Simple_Building_LE_03.cej scene.
- Open the Simple_Building_LE_03.cga rule file.
- In the Simple_Building_LE_03.cga rule file, add an attribute that determines whether or not there are balconies.
attr hasBalcony = false
- 4) Add code to create balconies.
Since the Balcony rule may either generate geometry for the balcony or not generate anything (NIL), there should be a sibling shape with geometry so that the handle can be accessed in the case that there is no balcony. That sibling shape is the Window. The BalconyMass rule creates a volume into which the balcony is inserted, and the remaining rules create the balcony geometry.
Tile --> split(x){ ~1 : Wall | window_width: split(y){ ~1: Wall | window_height: Window BalconyMass | ~1: Wall } | ~1 : Wall } BalconyMass --> s('1,0.9,0.9) t(0,0,'-0.5) Balcony Balcony --> case hasBalcony: primitiveCylinder(32) color(0.8,0.8,0.8) split(z) { ~1: NIL | ~1: comp(f) { top: NIL | back: NIL | bottom: extrude(0.05) Bottom. | all= BalconyRailing } } else: NIL BalconyRailing --> comp(f) { side: s(0.05,'1,'1) center(x) extrude(0.05) Bar. } s('1,0.05,'1) [ t(0,-0.05,0) extrude(vertex.normal, 0.05) Bottom. ] [ t(0,0.9,0) extrude(vertex.normal, 0.05) Railing. ]
- Put a toggle handle on the attribute hasBalcony to enable local edits.
@Handle(shape=Balcony, type=toggle, occlusion=false) attr hasBalcony = false
When hovering over the handle, a shaded volume displays where the handle is attached. Because the handle is attached to the Balcony rule, a shaded volume shows the placement of the balcony.
- Save the CGA file and regenerate the building.
Usually balconies only make sense on the upper floors of the building and are often excluded from the staircase windows above the door.
- Select an upper floor window and press PageUp until all the upper floors are selected.
Tip:
The PageUp and PageDown keys can be used to move up to higher levels or move down to lower levels, respectively.
- Add balconies by setting hasBalcony to true using the toggle handle.
- Select a window above the door using PageDown.
In the Inspector, there is an up arrow ↑ next to the attribute hasBalcony. This means that this attribute has been locally edited at a higher level. This change can be overridden because edits performed at a lower level take precedence.
- Select all the windows above the door by pressing End.
Tip:
The Home and End keys can be used to select patterns.
- Remove the balconies from the windows above the door by setting hasBalcony to false.
Add a grass border
Local edits are linked to the shape tree. One limitation with local edits is that changing the shape tree structure may cause already applied local edits to be lost. This means that changing the code after applying local edits can lead to unexpected results. It is advisable to try to make local edits only after the code is finished, to create placeholder rules as you code to account for future changes to the code, and/or to avoid changing the shape tree structure when changing the code.
- Open the Simple_Building_LE_04.cej scene.
- Open the Simple_Building_LE_04.cga rule file and locate the following snippet:
Lot --> extrude(height) Building
- Modify the snippet to the following:
Lot --> offset(-1) comp(f) { inside: Footprint | border= Grass } Footprint --> extrude(height) Building Grass --> color("#4c7b1e")
Because an offset is used to separate the grass from the building footprint, the Footprint rule creates the Building.
- Save the CGA file and regenerate the building.
This causes a loss of local edits because they are relative to the shape tree. When the structure of the shape tree changes, local edits remain but might cause unexpected results. To verify the local edits, you can change the code back to the original state.
The shape trees before and after Step 3 show that the Footprint shape has been inserted in between the Lot and Building shapes.
Note:
To open the shape tree, go to Window > Model Hierarchy, select the building, and click Inspect model in the Model Hierarchy tab. See Model Hierarchy for more information.
- Modify the Lot rule without adding an extra rule in between Lot and Building. The Footprint rule can be removed.
Lot --> offset(-1) comp(f) { inside: extrude(height) Building | border= Grass }
- Save the CGA file and regenerate the building.
Now the shape tree goes from Lot directly to Building. Below is the building with the local edits preserved and a grass border around it.
The final results are in the Simple_Building_LE_05.cej scene which uses the Simple_Building_LE_05.cga rule file.
Tip:
One way to avoid losing local edits is to try not to change the shape tree structure as you add code. Another way is to try to create placeholders for rules that you think you might need later as you create the initial rule file. As you change the code, some local edits might not make sense anymore, so the easiest solution might be to apply the local edits only after you are done with the CGA file.