The Parts and Whole: DR Groups

From The DarkMod Wiki
Jump to navigationJump to search

Introduction

by Geep 2022

In a hurry? See:

A Group is a convenient way to form a temporary collection of map objects. Perhaps you want to move them together to one place, go do something else, then come back and move them further, without having to redefine the collection by re-selection. This method of grouping affects only DR, not the game (i.e., not the .map file). "Temporarily" can be as long as you like and you find convenient, since there’s no performance implications. As befits the temporary concept, Groups are anonymous, i.e., unnamable.

Unlike other types of component manipulation in DR, you can’t directly pick out a particular Group element to select. Instead, you’ll need to first Ungroup, work with the particular element, and then (as desired) re-Group.

TIP: This process can be often sped up by careful use of "Hide Deselected" then "Unhide all".

Creating a DR Group

To create a DR Group, select at least two elements of interest in the camera view, then use either:

  • "Edit/Group Selection" from the Main Menu
  • the shortcut Control+Shift+G (if default binding)
  • the "Group Selection" icon in DR’s left-side toolbar
  • "Group Selection" from the RMB menu

Another way to create a DR Group is during import of a prefab. In the “Choose Prefab" window, ensure that the checkbox "Create Group out of Prefab parts" is ticked. For more about this, see Grouping.

A map object can be part of multiple Groups. Groups, while not strictly-speaking hierarchical, exhibit similar behavior. More about this next.

Making an Enlarged Group

A feature of Grouping in DR is that you can neither add an element to an existing Group, nor subtract an element from it. But you can easily create another Group that includes the original Group and a new element. This new, expanded Group in effect hides the old Group. So when you select any of its elements, you select the new Group. An example may make this clearer.

Suppose you have 3 simple brush cubes called A, B, and C. First, group A & B together with "Group Selection". Then group A, B, & C together with "Group Selection". Now A & B are members of 2 Groups, one of which has C. If you now unselect with Escape, then reselect any of the 3 cubes, all 3 will light up. You are selecting the new Group. Put otherwise, the "latest Group aka largest Group" incorporating the selected cube is being selected.

UnGrouping

To delete a Group that is selected in the camera view, use either:

  • "Edit/Ungroup Selection" from the Main Menu
  • the shortcut Control+Shift+U (if default binding)
  • the "Group Selection" icon in DR’s left-side toolbar
  • "Ungroup Selection” from the RMB menu

All members of the former Group remain selected. By removing of the "latest Group aka largest Group", selection is automatically transferred to any previously hidden "next-latest aka next-largest" Group(s), or individual now-ungrouped members. Put otherwise, this exhibits stack-like, last-in-first-out (LIFO) behavior.

In the example from the previous section, after ungrouping once. A & B remain in a Group, while C is by itself. If you ungroup all of them again, then A, B, and C are all separate.

TIP: To disassemble a Group all the way down to individual elements, just do an Ungroup action repeatedly without changing the selection. When a warning dialog appears about nothing to Ungroup, you’re done.

TIP: If you just want to momentarily examine a particular item’s attributes without changing them, just Ungroup as needed to get to it, examine it, then the Undo (Ctrl-Z) the same number of times to regroup.

Indications that an Item Is Grouped

If an item is in a Group, when selected:

  • All other items in the Group will also be selected
  • The Entity Viewer would show either blank content (through DR 2.13) or only shared content (2.14+).
  • In the orthogonal map views...
    • all items in the Group will be in "blue-dashed-line overlay", rather than "red-dashed-line overlay" of a selected Entity.
    • with the translation mode in effect, the origin will be the centroid of the Group, not of an individual element.
    • with "View/Show/Show size elements" in effect, the size brackets span the whole group
  • Hitting Tab or Shift-Tab will do nothing; cycling is not a thing with a Group.

Can I Select a Member within a Group?

Only by ungrouping as discussed in the Introduction and in UnGrouping.

Actions that you think might work but DON'T:

  • Cycling through members of a Group with Tab or Shift-Tab. (However, as of Oct. 2022, this is a bugtracker feature request #6135)
  • The top toolbar's buttons...
    • "Select Entities" (which just toggles off other buttons)
    • "Select Group Parts" (which selects particular primitives within an entity).

Can I Select a Face of a Group Member?

Yes, in the usual way with Control-Shift LMB on the face of interest.

Custom DR Scripting of Groups

If you need special functionality, DR offers Python scripting, and in particular for Groups exposes a GlobalSelectionGroupManager (including SelectionGroup and SelectionGroupVisitor) API with over a dozen function calls. See the DarkRadiant Script Reference.

How Groups are Implemented

Grouping is maintained in a DR memory structure. Changes are not instantly saved to disk, but periodically as a <project_name>_autosave.darkradiant file, and then when you save at the end of session as a <project_name>.darkradiant file, where <project_name> is the name also used to save the .map file, and routinely includes the FM name. Looking within a typical .darkradiant file with a text editor, we see that each Group is defined simply by a number in the "Selection Groups" section, e.g.:

SelectionGroups
{
	SelectionGroup 0 { "" }
	SelectionGroup 9 { "" }
	SelectionGroup 10 { "" }
	SelectionGroup 11 { "" }
	...
}

Each grouped element has a list of which Groups it is in. This information appears in the "Selection Group Node Mapping" section. For named entities, the format is:

Node { ( entity_num ) ( group_num(s) ) } // entity (name)

A typical example:

SelectionGroupNodeMapping
{
	...
	Node { ( 1591 ) ( 69 ) } // entity (atdm_moveable_metal_hook_1)
	Node { ( 1654 ) ( 79 ) } // entity (func_static_1227)
	...
	Node { ( 1680 ) ( 87 91 92 ) } // entity (func_static_1238)
	...
}

The third example node above shows an entity that's a member of 3 groups: 87, 91, and 92. The listing here is both in numeric and chronological order, since a new grouping is added to the end of the list, and Group numbers increase monotonically. Grouped brushes and patches (with entity_num = 0 and a prim_num) are indicated thusly:

	...
	Node { ( 0 2600 ) ( 136 ) } // patch (Patch)
	Node { ( 0 2603 ) ( 134 136 ) } // patch (Patch)
	Node { ( 0 2604 ) ( 134 136 ) } // brush (Brush)

If you ungroup an item, the highest number group_id (which is also the last one) in its list is removed. If there are no groups left, the node line is deleted.

See Also