package ui import ( "code.ur.gs/lupine/ordoor/internal/menus" "fmt" "log" ) func (d *Driver) registerGroup(group *menus.Group) error { // log.Printf("Adding group %v: %#+v", group.Locator, group) var dialogue bool switch group.Type { case menus.TypeStatic, menus.TypeMainBackground, menus.TypeMenu, menus.TypeDragMenu, menus.TypeRadioMenu: case menus.TypeDialogue: dialogue = true default: return fmt.Errorf("Unknown group type: %v", group.Type) } var groupWidget *Widget // Groups have a background sprite (FIXME: always?) if group.BaseSpriteID() >= 0 { var err error _, groupWidget, err = d.buildStatic(group.Props()) if err != nil { return err } } else { groupWidget = &Widget{ Locator: group.Locator, Active: group.Active, } } if dialogue { d.dialogues = append(d.dialogues, groupWidget) } else { d.widgets = append(d.widgets, groupWidget) } // TRadioGroup is best handled like this records, widget, err := d.maybeBuildInventorySelect(group, group.Records) if err != nil { return err } if widget != nil { groupWidget.Children = append(groupWidget.Children, widget) } records, widget, err = d.maybeBuildListBox(group, records) if err != nil { return err } if widget != nil { groupWidget.Children = append(groupWidget.Children, widget) } for _, record := range records { child, err := d.buildRecord(record) if err != nil { return err } if child != nil { groupWidget.Children = append(groupWidget.Children, child) } } return nil } func (d *Driver) buildRecord(r *menus.Record) (*Widget, error) { var widget *Widget var err error switch r.Type { case menus.SubTypeSimpleButton, menus.SubTypeInvokeButton: _, widget, err = d.buildButton(r.Props()) case menus.SubTypeDoorHotspot1, menus.SubTypeDoorHotspot2, menus.SubTypeDoorHotspot3: _, widget, err = d.buildDoorHotspot(r.Props()) case menus.SubTypeOverlay: _, widget, err = d.buildOverlay(r.Props()) case menus.SubTypeHypertext: _, widget, err = d.buildHypertext(r.Props()) case menus.SubTypeCheckbox: _, widget, err = d.buildCheckbox(r.Props()) case menus.SubTypeEditBox: log.Printf("Unimplemented: SubTypeEditBox: %v", r.Locator) // TODO case menus.SubTypeRadioButton: log.Printf("Unimplemented: SubTypeRadioButton: %v", r.Locator) // TODO case menus.SubTypeDropdownButton: log.Printf("Unimplemented: SubTypeDropdownButton: %v", r.Locator) // TODO case menus.SubTypeComboBoxItem: log.Printf("Unimplemented: SubTypeComboBoxItem: %v", r.Locator) // TODO case menus.SubTypeAnimationSample: _, widget, err = d.buildAnimationSample(r.Props()) case menus.SubTypeAnimationHover: _, widget, err = d.buildAnimationHover(r.Props()) case menus.SubTypeMainButton: _, widget, err = d.buildMainButton(r.Props()) case menus.SubTypeSlider: _, widget, err = d.buildSlider(r.Props()) // TODO: take sliders at an earlier point? case menus.SubTypeStatusBar: log.Printf("Unimplemented: SubTypeStatusBar: %v", r.Locator) // TODO default: return nil, fmt.Errorf("Unknown record type for %v: %v", r.Locator, r.Type) } return widget, err } func (d *Driver) maybeBuildInventorySelect(group *menus.Group, records []*menus.Record) ([]*menus.Record, *Widget, error) { var untouched []*menus.Record var touched []*menus.Record for _, record := range records { if record.Type == menus.SubTypeInventorySelect { touched = append(touched, record) } else { untouched = append(untouched, record) } } if len(touched) == 0 { return untouched, nil, nil } elements := make([]*inventorySelect, len(touched)) widget := &Widget{ Locator: group.Locator, Active: group.Active, } for i, record := range touched { element, childWidget, err := d.buildInventorySelect(record.Props()) if err != nil { return nil, nil, err } elements[i] = element widget.Children = append(widget.Children, childWidget) } elements[0].setValue("1") for _, element := range elements { element.others = elements } return untouched, widget, nil } func (d *Driver) maybeBuildListBox(group *menus.Group, records []*menus.Record) ([]*menus.Record, *Widget, error) { // Unless up, down, thumb, and items, are all present, it's not a listbox var up *menus.Record var down *menus.Record var thumb *menus.Record var items []*menus.Record var untouched []*menus.Record for _, rec := range records { switch rec.Type { case menus.SubTypeListBoxUp: if up != nil { return nil, nil, fmt.Errorf("Duplicate up buttons in menu %v", group.Locator) } up = rec case menus.SubTypeListBoxDown: if down != nil { return nil, nil, fmt.Errorf("Duplicate down buttons in menu %v", group.Locator) } down = rec case menus.SubTypeLineKbd, menus.SubTypeLineBriefing: items = append(items, rec) case menus.SubTypeThumb: if thumb != nil { return nil, nil, fmt.Errorf("Duplicate thumbs in menu %v", group.Locator) } thumb = rec default: // e.g. maingame:18.12 includes a button that is not part of the box untouched = append(untouched, rec) } } // Since not all the elements are present, this isn't a listbox if len(items) == 0 || thumb == nil || up == nil || down == nil { return untouched, nil, nil } _, widget, err := d.buildListBox(group, up, down, thumb, items...) if err != nil { return nil, nil, err } return untouched, widget, nil }