Tutorial 20: Local edits

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.

Building with Footprint rule added without losing local edits


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

To modify individual windows, complete the following steps:

  1. Open the Simple_Building_LE_01.cej scene.
  2. 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.

  3. 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
  4. 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 }
  5. Add handles to the attributes.
    @Handle(shape=Window, axis=x)
    attr window_width = 2
    attr window_height = 1.5
  6. Save the CGA file and regenerate the building by clicking Generate on the main toolbar or pressing Ctrl+G.
    Building with handles
  7. Pull on the window handles.

    This changes the window size for all the windows in the same way.

    Local edits on windows

    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.

  8. Reset all attributes by clicking the Reset button Reset on the toolbar.
  9. Enable local edits mode by clicking the Local Edits button Local Edits on the toolbar.
  10. 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 window_width and window_height attributes can be locally set for just this window.

    Local edit selections highlighted in Inspector.
  11. 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 indicates that these attributes have been locally edited for the current selection.

    Inspector indicates local edits applied.

    With multiple selections, the same local edit can be applied to multiple windows at the same time.

  12. Press Shift while selecting a few windows to select multiple components.

    Press Ctrl while selecting to switch items in the selection—already selected items will be removed.

  13. Change the size of the windows in the selection either by pulling on the handles or by entering a value in the Inspector.

    Local edits with multiple selections

    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.

  14. To undo all local edits, right-click in the Viewport or Inspector and click > Reset all local edits.
  15. Select a window above the door.
  16. Press End to select all windows in the column above the door.

    The Home and End keys cycle backward and forward 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.

    Local edit selections with patterns
  17. Make the windows smaller either by pulling on the handles or by entering a value in the Inspector.
    After pattern local edits applied

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.

  1. Open the Simple_Building_LE_02.cej scene.
  2. Open the Simple_Building_LE_02.cga rule file.
  3. In the Simple_Building_LE_02.cga rule file, add a handle to the tile_width attribute. 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)
  4. Save the CGA file and regenerate the building.
  5. In local edits mode, select a window on the ground floor, and change its tile width, window width, and window height.
    Local edits ground floor selection

    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.

  6. 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.

    Local edits selections on higher level
  7. Increase the window width to make the windows on the ground floor bigger.
    Local edits applied on higher level.

    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.

  8. Select the inconsistent window at a lower level by using PageDown to move down a level.
  9. Right-click in the Viewport or in the Inspector and click > Reset highlighted local edits.
  10. Select the ground floor windows using PageUp.
    Local edits selections after highlight reset
  11. 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.

    Ground floor windows with same size

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 must have sibling geometry. This sibling geometry allows access to the balcony’s handle even when the balcony does not exist.

  1. Open the Simple_Building_LE_03.cej scene.
  2. Open the Simple_Building_LE_03.cga rule file.
  3. In the Simple_Building_LE_03.cga rule file, add an attribute that determines whether there are balconies.
    attr hasBalcony = false
  4. 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 when 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 -->
    Balcony -->
    	case hasBalcony:
    		split(z) { ~1: NIL
    				 | ~1: comp(f) { top: NIL
    				 			   | back: NIL
    				 			   | bottom: extrude(0.05) Bottom.
    				 			   | all= BalconyRailing } }
    BalconyRailing -->
    	comp(f) { side: s(0.05,'1,'1) center(x) extrude(0.05) Bar. }
    	[ t(0,-0.05,0) extrude(vertex.normal, 0.05) Bottom. ]
    	[ t(0,0.9,0) extrude(vertex.normal, 0.05) Railing. ]
  5. Put a toggle handle on the hasBalcony attribute 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.

    Balcony handle used for local edits.
  6. 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.

  7. Select an upper floor window and press PageUp until all the upper floors are selected.

    The PageUp and PageDown keys can be used to move up to higher levels or move down to lower levels, respectively.

  8. Add balconies by setting hasBalcony to true using the toggle handle.
    Local edits selections on highest level
  9. Select a window above the door using PageDown.
    Balconies above door

    In the Inspector, there is an up arrow ↑ next to the hasBalcony attribute. 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.

  10. Select all the windows above the door by pressing End.

    The Home and End keys can be used to select patterns.

    Balconies above door selected
  11. Remove the balconies from the windows above the door by setting hasBalcony to false.
    Removed balconies above door

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 recommended that you 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 to avoid changing the shape tree structure when changing the code.

  1. Open the Simple_Building_LE_04.cej scene.
  2. Open the Simple_Building_LE_04.cga rule file and locate the following snippet:

    Lot --> 
    	extrude(height) Building

  3. Modify the snippet to the following:
    Lot --> 
    	comp(f) { inside: Footprint | border= Grass }
    Footprint -->
    	extrude(height) Building
    Grass -->

    Because an offset is used to separate the grass from the building footprint, the Footprint rule creates the Building.

  4. Save the CGA file and regenerate the building.
    Building after Footprint rule added and local edit lost

    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 may 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 between the Lot and Building shapes.



    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.

  5. Modify the Lot rule without adding an extra rule between Lot and Building. The Footprint rule can be removed.

    Lot --> 
    	comp(f) { inside: extrude(height) 
               Building | border= Grass }
    Lot rule added without an extra rule between Lot and Building.
  6. 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.

    Building with Footprint rule added without losing local edits

The final results are in the Simple_Building_LE_05.cej scene, which uses the Simple_Building_LE_05.cga rule file.


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 may need later as you create the initial rule file. As you change the code, some local edits may not make sense anymore, so the most efficient solution may be to apply the local edits only after you are done with the CGA file.