Beispiel #1
0
 void OnClicked(int x, int y)
 {
     x /= TileWidth;
     y /= TileHeight;
     if (!ViewObjects)
     {
         room.SetTile(x, y, client.SelectedIndex);
         this.QueueDrawArea(x * TileWidth, y * TileWidth, TileWidth - 1, TileHeight - 1);
     }
     else
     {
         if (objectEditor != null)
         {
             ObjectGroupEditor editor = objectEditor;
             while (hoveringObjectIndices.Count > 1)
             {
                 editor.SelectedIndex = hoveringObjectIndices[0];
                 hoveringObjectIndices.RemoveAt(0);
                 editor = editor.SubEditor;
             }
             if (hoveringObjectIndices.Count == 1)
             {
                 editor.SelectedIndex = hoveringObjectIndices[0];
                 draggingObject       = true;
             }
         }
     }
 }
Beispiel #2
0
        void OnClicked(int posX, int posY)
        {
            int x = (posX - XOffset) / TileWidth;
            int y = (posY - YOffset) / TileHeight;

            if (!ViewObjects)
            {
                if (!IsInBounds(posX, posY))
                {
                    return;
                }
                room.SetTile(x, y, client.SelectedIndex);
                this.QueueDrawArea(x * TileWidth + XOffset, y * TileWidth + YOffset, TileWidth - 1, TileHeight - 1);
            }
            else
            {
                if (objectEditor != null)
                {
                    ObjectGroupEditor editor = objectEditor;
                    while (hoveringObjectIndices.Count > 1)
                    {
                        editor.SelectedIndex = hoveringObjectIndices[0];
                        hoveringObjectIndices.RemoveAt(0);
                        editor = editor.SubEditor;
                    }
                    if (hoveringObjectIndices.Count == 1)
                    {
                        editor.SelectedIndex = hoveringObjectIndices[0];
                        draggingObject       = true;
                    }
                }
            }
        }
Beispiel #3
0
 public void SetObjectGroupEditor(ObjectGroupEditor editor)
 {
     if (objectEditor != editor)
     {
         objectEditor            = editor;
         objectEditor.RoomEditor = this;
     }
 }
Beispiel #4
0
        // Methods

        public void SetRoom(Room r, int season, bool changedFromWarpFollow = false)
        {
            if (r == Room && this.season == season)
            {
                return;
            }

            if (room != null)
            {
                RoomLayout.LayoutModifiedEvent -= OnLayoutModified;
                room.GetObjectGroup().RemoveModifiedHandler(OnObjectModified);
                room.GetWarpGroup().RemoveModifiedHandler(OnWarpModified);
            }

            room = r;
            if (season != -1)
            {
                this.season = season;
            }

            if (room != null)
            {
                RoomLayout.LayoutModifiedEvent += OnLayoutModified;
                room.GetObjectGroup().AddModifiedHandler(OnObjectModified);
                room.GetWarpGroup().AddModifiedHandler(OnWarpModified);

                Width  = room.Width;
                Height = room.Height;

                ObjectGroupEditor.SetObjectGroup(room.GetObjectGroup());
            }

            if (r == null)
            {
                EditingWarpDestination = null;
            }

            GenerateRoomComponents();
            selectedComponent = null;

            if (EditingWarpDestination != null)
            {
                EditingWarpDestination.DestRoom = r;
            }

            roomEventWrapper.ReplaceEventSource(room);
            UpdateChestEvents();

            RoomChangedEvent?.Invoke(this,
                                     new RoomChangedEventArgs {
                room = r, fromFollowWarp = changedFromWarpFollow
            });

            QueueDraw();
        }
Beispiel #5
0
        protected override void TileDrawer(int index, Cairo.Context cr)
        {
            if (index >= ObjectGroup.GetNumObjects())
            {
                return;
            }

            ObjectDefinition obj = ObjectGroup.GetObject(index);

            cr.SetSourceColor(ObjectGroupEditor.GetObjectColor(obj.GetObjectType()));
            cr.Rectangle(0, 0, 18, 18);
            cr.Fill();
            cr.Rectangle(1, 1, 16, 16); // Cut off object drawing outside 16x16 area
            cr.Clip();
            DrawObject(obj, cr, 9, 9);
        }
Beispiel #6
0
        void UpdatePointerTextBox(Gtk.Entry entry, ValueReference r)
        {
            pointerFrame.Remove(pointerFrame.Child);

            subEditor = new ObjectGroupEditor();
            Gtk.Alignment alignment = new Gtk.Alignment(0.5F, 0.5F, 0.0F, 0.8F);
            try {
                Project.GetFileWithLabel(entry.Text.Trim());
                subEditor.SetObjectGroup(Project.GetDataType <ObjectGroup>(r.GetStringValue()));
                subEditor.ShowAll();
                alignment.Add(subEditor);
                r.SetValue(entry.Text.Trim());
            }
            catch (InvalidLookupException) {
                subEditor.SetObjectGroup(null);
                Gtk.Label label = new Gtk.Label("Error: label \"" + entry.Text + "\" not found.");
                label.Show();
                alignment.Add(label);
            }
            pointerFrame.Label = entry.Text;
            pointerFrame.Add(alignment);
            pointerFrame.ShowAll();
        }
Beispiel #7
0
        void GenerateRoomComponents()
        {
            if (Room == null)
            {
                return;
            }

            roomComponents    = new List <RoomComponent>();
            hoveringComponent = null;

            // We only draw the 1 component if we're editing a warp destination
            if (EditingWarpDestination != null)
            {
                WarpDestRoomComponent com = new WarpDestRoomComponent(this, EditingWarpDestination);
                com.SelectedEvent += (sender, args) => {
                    WarpEditor.SetSelectedWarp(com.warp);
                };
                roomComponents.Add(com);
                goto addedAllComponents; // I love being evil
            }

            if (ViewObjects && ObjectGroupEditor.TopObjectGroup != null)
            {
                foreach (ObjectGroup group in ObjectGroupEditor.TopObjectGroup.GetAllGroups())
                {
                    for (int i = 0; i < group.GetNumObjects(); i++)
                    {
                        ObjectDefinition obj = group.GetObject(i);
                        if (!obj.HasXY())
                        {
                            continue;
                        }
                        ObjectRoomComponent com = new ObjectRoomComponent(obj);
                        com.SelectedEvent += (sender, args) => {
                            ObjectGroupEditor.SelectObject(obj.ObjectGroup, obj.Index);
                        };
                        roomComponents.Add(com);
                    }
                }
            }

            if (ViewWarps)
            {
                int       index = 0;
                WarpGroup group = room.GetWarpGroup();

                foreach (Warp warp in group.GetWarps())
                {
                    Action <int, int, int, int> addWarpComponent = (x, y, width, height) => {
                        var rect = new Cairo.Rectangle(x, y, width, height);
                        var com  = new WarpSourceRoomComponent(this, warp, index, rect);
                        com.SelectedEvent += (sender, args) => {
                            WarpEditor.SetWarpIndex(com.index);
                        };
                        roomComponents.Add(com);
                    };

                    if (warp.WarpSourceType == WarpSourceType.Standard)
                    {
                        int middle;
                        if (Room.Width == 15) // Large room
                        {
                            middle = ((Room.Width + 1) / 2) * 16;
                        }
                        else // Small room
                        {
                            middle = ((Room.Width + 1) / 2) * 16 + 8;
                        }
                        int right  = Room.Width * 16;
                        int bottom = Room.Height * 16 - 8;

                        if (warp.TopLeft)
                        {
                            addWarpComponent(0, -8, middle, 16);
                        }
                        if (warp.TopRight)
                        {
                            addWarpComponent(middle, -8, right - middle, 16);
                        }
                        if (warp.BottomLeft)
                        {
                            addWarpComponent(0, bottom, middle, 16);
                        }
                        if (warp.BottomRight)
                        {
                            addWarpComponent(middle, bottom, right - middle, 16);
                        }

                        if (!warp.TopLeft && !warp.TopRight && !warp.BottomLeft && !warp.BottomRight)
                        {
                            addWarpComponent(0, 16 * 13, Room.Width * 16, 32);
                        }
                    }
                    else if (warp.WarpSourceType == WarpSourceType.Pointed)
                    {
                        addWarpComponent(warp.SourceX * TileWidth, warp.SourceY * TileHeight, TileWidth, TileHeight);
                    }
                    index++;
                }
            }

            if (ViewChests)
            {
                if (Room.Chest != null)
                {
                    ChestRoomComponent com = new ChestRoomComponent(Room.Chest);
                    roomComponents.Add(com);
                }
            }


addedAllComponents:
            // The "selectedComponent" now refers to an old object. Look for the corresponding new
            // object.
            RoomComponent newSelectedComponent = null;

            foreach (RoomComponent com in roomComponents)
            {
                if (com.Compare(selectedComponent))
                {
                    newSelectedComponent = com;
                    break;
                }
            }

            selectedComponent = newSelectedComponent;

            QueueDraw();
        }
        void UpdatePointerTextBox(Gtk.Entry entry, ValueReference r)
        {
            pointerFrame.Remove(pointerFrame.Child);

            subEditor = new ObjectGroupEditor();
            Gtk.Alignment alignment = new Gtk.Alignment(0.5F, 0.5F, 0.0F, 0.8F);
            try {
                Project.GetFileWithLabel(entry.Text.Trim());
                subEditor.SetObjectGroup(Project.GetDataType<ObjectGroup>(r.GetStringValue()));
                subEditor.ShowAll();
                alignment.Add(subEditor);
                r.SetValue(entry.Text.Trim());
            }
            catch (LabelNotFoundException) {
                subEditor.SetObjectGroup(null);
                Gtk.Label label = new Gtk.Label("Error: label \"" + entry.Text + "\" not found.");
                label.Show();
                alignment.Add(label);
            }
            pointerFrame.Label = entry.Text;
            pointerFrame.Add(alignment);
            pointerFrame.ShowAll();
        }
Beispiel #9
0
        int DrawObjectGroup(Graphics g, int index, ref int cursorX, ref int cursorY, ref int selectedX, ref int selectedY, ObjectGroup group, ObjectGroupEditor editor, ref List <int> objectIndices)
        {
            if (group == null)
            {
                return(index);
            }

            List <int> localObjectIndices = new List <int>(objectIndices);

            bool foundHoveringMatch = false;

            for (int i = 0; i < group.GetNumObjects(); i++)
            {
                ObjectData data = group.GetObjectData(i);
                if (data.GetObjectType() >= ObjectType.Pointer &&
                    data.GetObjectType() <= ObjectType.AntiBossPointer)
                {
                    ObjectGroup nextGroup = data.GetPointedObjectGroup();
                    if (nextGroup != null)
                    {
                        List <int> pointerObjectIndices = new List <int>(objectIndices);
                        pointerObjectIndices.Add(i);
                        if (editor != null && i == editor.SelectedIndex)
                        {
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                                    ref selectedX, ref selectedY, nextGroup, editor.SubEditor, ref pointerObjectIndices);
                        }
                        else
                        {
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                                    ref selectedX, ref selectedY, nextGroup, null, ref pointerObjectIndices);
                        }
                        if (pointerObjectIndices.Count > objectIndices.Count + 1)
                        {
                            localObjectIndices = pointerObjectIndices;
                        }
                    }
                }
                else
                {
                    Color color = data.GetColor();
                    int   x, y;
                    int   width;
                    if (data.HasXY())
                    {
                        x     = data.GetX();
                        y     = data.GetY();
                        width = 16;
                        // Objects with specific positions get
                        // transparency
                        color = Color.FromArgb(0xd0, color.R, color.G, color.B);
                    }
                    else
                    {
                        // No X/Y values exist
                        x = index;
                        y = 0;
                        while (x >= 0xf)
                        {
                            x -= 0xf;
                            y++;
                        }
                        x    *= 16;
                        y    *= 16;
                        x    += 8;
                        y    += 8;
                        width = 8;
                        index++;
                    }

                    if (editor != null && i == editor.SelectedIndex)
                    {
                        selectedX = x - 8;
                        selectedY = y - 8;
                    }
                    if (mouseX >= x - 8 && mouseX < x + 8 &&
                        mouseY >= y - 8 && mouseY < y + 8)
                    {
                        if (localObjectIndices.Count == objectIndices.Count)
                        {
                            if (foundHoveringMatch)
                            {
                                localObjectIndices[localObjectIndices.Count - 1] = i;
                            }
                            else
                            {
                                localObjectIndices.Add(i);
                            }
                            cursorX            = x - 8;
                            cursorY            = y - 8;
                            foundHoveringMatch = true;
                        }
                    }

                    x -= width / 2;
                    y -= width / 2;


                    g.FillRectangle(new SolidBrush(color), x, y, width, width);
                }
            }

            objectIndices = localObjectIndices;
            return(index);
        }
Beispiel #10
0
        int DrawObjectGroup(Graphics g, int index, ref int cursorX, ref int cursorY, ref int selectedX, ref int selectedY, ObjectGroup group, ObjectGroupEditor editor, ref List <int> objectIndices)
        {
            if (group == null)
            {
                return(index);
            }

            List <int> localObjectIndices = new List <int>(objectIndices);

            bool foundHoveringMatch = false;

            for (int i = 0; i < group.GetNumObjects(); i++)
            {
                ObjectData data = group.GetObjectData(i);
                if (data.GetObjectType() >= ObjectType.Pointer &&
                    data.GetObjectType() <= ObjectType.AntiBossPointer)
                {
                    ObjectGroup nextGroup = data.GetPointedObjectGroup();
                    if (nextGroup != null)
                    {
                        List <int> pointerObjectIndices = new List <int>(objectIndices);
                        pointerObjectIndices.Add(i);
                        if (editor != null && i == editor.SelectedIndex)
                        {
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                                    ref selectedX, ref selectedY, nextGroup, editor.SubEditor, ref pointerObjectIndices);
                        }
                        else
                        {
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                                    ref selectedX, ref selectedY, nextGroup, null, ref pointerObjectIndices);
                        }
                        if (pointerObjectIndices.Count > objectIndices.Count + 1)
                        {
                            localObjectIndices = pointerObjectIndices;
                        }
                    }
                }
                else
                {
                    Color color = data.GetColor();
                    int   x, y;
                    int   width;
                    if (data.HasXY())
                    {
                        x     = data.GetX();
                        y     = data.GetY();
                        width = 16;
                        // Objects with specific positions get
                        // transparency
                        color = Color.FromArgb(0xd0, color.R, color.G, color.B);
                    }
                    else
                    {
                        // No X/Y values exist
                        x = index;
                        y = 0;
                        while (x >= 0xf)
                        {
                            x -= 0xf;
                            y++;
                        }
                        x    *= 16;
                        y    *= 16;
                        x    += 8;
                        y    += 8;
                        width = 8;
                        index++;
                    }

                    if (editor != null && i == editor.SelectedIndex)
                    {
                        selectedX = x - 8 + XOffset;
                        selectedY = y - 8 + YOffset;
                    }
                    if (mouseX - XOffset >= x - 8 && mouseX - XOffset < x + 8 &&
                        mouseY - YOffset >= y - 8 && mouseY - YOffset < y + 8)
                    {
                        if (localObjectIndices.Count == objectIndices.Count)
                        {
                            if (foundHoveringMatch)
                            {
                                localObjectIndices[localObjectIndices.Count - 1] = i;
                            }
                            else
                            {
                                localObjectIndices.Add(i);
                            }
                            cursorX            = x - 8 + XOffset;
                            cursorY            = y - 8 + YOffset;
                            foundHoveringMatch = true;
                        }
                    }

                    // x and y are the center coordinates for the object

                    if (ViewObjectBoxes)
                    {
                        g.FillRectangle(new SolidBrush(color), x - width / 2 + XOffset, y - width / 2 + YOffset, width, width);
                    }

                    if (data.GetGameObject() != null)
                    {
                        try {
                            ObjectAnimationFrame o = data.GetGameObject().DefaultAnimation.GetFrame(0);
                            o.Draw(g, x + XOffset, y + YOffset);
                        }
                        catch (NoAnimationException) {
                            // No animation defined
                        }
                        catch (InvalidAnimationException) {
                            // Error parsing an animation; draw a blue X to indicate the error
                            int xPos = x - width / 2 + XOffset;
                            int yPos = y - width / 2 + YOffset;
                            g.DrawLine(new Pen(Color.Blue), xPos, yPos, xPos + width - 1, yPos + width - 1);
                            g.DrawLine(new Pen(Color.Blue), xPos + width - 1, yPos, xPos, yPos + width - 1);
                        }
                    }
                }
            }

            objectIndices = localObjectIndices;
            return(index);
        }
Beispiel #11
0
        int DrawObjectGroup(Graphics g, int index, ref int cursorX, ref int cursorY, ref int selectedX, ref int selectedY, ObjectGroup group, ObjectGroupEditor editor, ref List<int> objectIndices)
        {
            if (group == null) return index;

            List<int> localObjectIndices = new List<int>(objectIndices);

            bool foundHoveringMatch = false;

            for (int i=0; i<group.GetNumObjects(); i++) {
                ObjectData data = group.GetObjectData(i);
                if (data.GetObjectType() >= ObjectType.Pointer &&
                        data.GetObjectType() <= ObjectType.AntiBossPointer) {
                    ObjectGroup nextGroup = data.GetPointedObjectGroup();
                    if (nextGroup != null) {
                        List<int> pointerObjectIndices = new List<int>(objectIndices);
                        pointerObjectIndices.Add(i);
                        if (editor != null && i == editor.SelectedIndex)
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                    ref selectedX, ref selectedY, nextGroup, editor.SubEditor, ref pointerObjectIndices);
                        else
                            index = DrawObjectGroup(g, index, ref cursorX, ref cursorY,
                                    ref selectedX, ref selectedY, nextGroup, null, ref pointerObjectIndices);
                        if (pointerObjectIndices.Count > objectIndices.Count+1)
                            localObjectIndices = pointerObjectIndices;
                    }
                }
                else {
                    Color color = data.GetColor();
                    int x,y;
                    int width;
                    if (data.HasXY()) {
                        x = data.GetX();
                        y = data.GetY();
                        width = 16;
                        // Objects with specific positions get
                        // transparency
                        color = Color.FromArgb(0xd0,color.R,color.G,color.B);
                    }
                    else {
                        // No X/Y values exist
                        x = index;
                        y = 0;
                        while (x >= 0xf) {
                            x -= 0xf;
                            y++;
                        }
                        x *= 16;
                        y *= 16;
                        x += 8;
                        y += 8;
                        width = 8;
                        index++;
                    }

                    if (editor != null && i == editor.SelectedIndex) {
                        selectedX = x-8;
                        selectedY = y-8;
                    }
                    if (mouseX >= x-8 && mouseX < x+8 &&
                            mouseY >= y-8 && mouseY < y+8) {
                        if (localObjectIndices.Count == objectIndices.Count) {
                            if (foundHoveringMatch)
                                localObjectIndices[localObjectIndices.Count-1] = i;
                            else
                                localObjectIndices.Add(i);
                            cursorX = x-8;
                            cursorY = y-8;
                            foundHoveringMatch = true;
                        }
                    }

                    x -= width/2;
                    y -= width/2;

                    g.FillRectangle(new SolidBrush(color), x, y, width, width);
                }
            }

            objectIndices = localObjectIndices;
            return index;
        }
Beispiel #12
0
 public void SetObjectGroupEditor(ObjectGroupEditor editor)
 {
     if (objectEditor != editor) {
         objectEditor = editor;
         objectEditor.RoomEditor = this;
     }
 }
Beispiel #13
0
    public MainWindow(string directory)
    {
        log.Debug("Beginning Program");

        Gtk.Window.DefaultIcon = new Gdk.Pixbuf(Helper.GetResourceStream("LynnaLab.icon.ico"));

        Gtk.Builder builder = new Builder();
        builder.AddFromString(Helper.ReadResourceFile("LynnaLab.Glade.MainWindow.ui"));
        builder.Autoconnect(this);

        mainWindow                 = (builder.GetObject("mainWindow") as Gtk.Window);
        menubar1                   = (Gtk.MenuBar)builder.GetObject("menubar1");
        editMenuItem               = (Gtk.MenuItem)builder.GetObject("editMenuItem");
        actionMenuItem             = (Gtk.MenuItem)builder.GetObject("actionMenuItem");
        debugMenuItem              = (Gtk.MenuItem)builder.GetObject("debugMenuItem");
        minimapNotebook            = (Gtk.Notebook)builder.GetObject("minimapNotebook");
        contextNotebook            = (Gtk.Notebook)builder.GetObject("contextNotebook");
        worldSpinButton            = (Gtk.SpinButton)builder.GetObject("worldSpinButton");
        viewObjectsCheckButton     = (Gtk.CheckButton)builder.GetObject("viewObjectsCheckButton");
        viewWarpsCheckButton       = (Gtk.CheckButton)builder.GetObject("viewWarpsCheckButton");
        darkenDungeonRoomsCheckbox = (Gtk.CheckButton)builder.GetObject("darkenDungeonRoomsCheckbox");
        dungeonSpinButton          = (Gtk.SpinButton)builder.GetObject("dungeonSpinButton");
        floorSpinButton            = (Gtk.SpinButton)builder.GetObject("floorSpinButton");
        roomVreHolder              = (Gtk.Box)builder.GetObject("roomVreHolder");
        chestAddHolder             = (Gtk.Box)builder.GetObject("chestAddHolder");
        chestEditorBox             = (Gtk.Box)builder.GetObject("chestEditorBox");
        chestVreHolder             = (Gtk.Box)builder.GetObject("chestVreHolder");
        treasureVreHolder          = (Gtk.Box)builder.GetObject("treasureVreHolder");
        nonExistentTreasureHolder  = (Gtk.Box)builder.GetObject("nonExistentTreasureHolder");
        overallEditingContainer    = (Gtk.Box)builder.GetObject("overallEditingContainer");
        treasureDataFrame          = (Gtk.Widget)builder.GetObject("treasureDataFrame");
        treasureDataLabel          = (Gtk.Label)builder.GetObject("treasureDataLabel");

        editTilesetButton          = new Gtk.Button("Edit");
        editTilesetButton.Clicked += OnTilesetEditorButtonClicked;

        roomSpinButton        = new SpinButtonHexadecimal();
        roomSpinButton.Digits = 3;
        objectgroupeditor1    = new ObjectGroupEditor();
        tilesetViewer1        = new TilesetViewer();
        roomeditor1           = new RoomEditor();
        worldMinimap          = new HighlightingMinimap();
        dungeonMinimap        = new Minimap();
        warpEditor            = new WarpEditor(this);
        statusbar1            = new PriorityStatusbar();
        seasonComboBox        = new ComboBoxFromConstants(showHelp: false);
        seasonComboBox.SpinButton.Adjustment.Upper = 3;

        ((Gtk.Box)builder.GetObject("roomSpinButtonHolder")).Add(roomSpinButton);
        ((Gtk.Box)builder.GetObject("objectGroupEditorHolder")).Add(objectgroupeditor1);
        ((Gtk.Box)builder.GetObject("tilesetViewerHolder")).Add(tilesetViewer1);
        ((Gtk.Box)builder.GetObject("roomEditorHolder")).Add(roomeditor1);
        ((Gtk.Box)builder.GetObject("worldMinimapHolder")).Add(worldMinimap);
        ((Gtk.Box)builder.GetObject("dungeonMinimapHolder")).Add(dungeonMinimap);
        ((Gtk.Box)builder.GetObject("warpEditorHolder")).Add(warpEditor);
        ((Gtk.Box)builder.GetObject("statusbarHolder")).Add(statusbar1);
        ((Gtk.Box)builder.GetObject("seasonComboBoxHolder")).Add(seasonComboBox);

        mainWindow.Title = "LynnaLab " + Helper.ReadResourceFile("LynnaLab.version.txt");

        roomeditor1.Scale             = 2;
        roomeditor1.TilesetViewer     = tilesetViewer1;
        roomeditor1.ObjectGroupEditor = objectgroupeditor1;
        roomeditor1.WarpEditor        = warpEditor;

        eventGroup.Lock();


        // Event handlers from widgets

        roomSpinButton.ValueChanged += eventGroup.Add(OnRoomSpinButtonValueChanged);

        worldSpinButton.ValueChanged   += eventGroup.Add(OnWorldSpinButtonValueChanged);
        dungeonSpinButton.ValueChanged += eventGroup.Add(OnDungeonSpinButtonValueChanged);
        floorSpinButton.ValueChanged   += eventGroup.Add(OnFloorSpinButtonValueChanged);
        seasonComboBox.Changed         += eventGroup.Add(OnSeasonComboBoxChanged);
        minimapNotebook.SwitchPage     += new SwitchPageHandler(eventGroup.Add <SwitchPageArgs>(OnMinimapNotebookSwitchPage));
        contextNotebook.SwitchPage     += new SwitchPageHandler(eventGroup.Add <SwitchPageArgs>(OnContextNotebookSwitchPage));

        roomeditor1.RoomChangedEvent += eventGroup.Add <RoomChangedEventArgs>((sender, args) => {
            eventGroup.Lock();
            OnRoomChanged();

            // Only update minimap if the room editor did a "follow warp". Otherwise, we'll decide
            // whether to update the minimap from whatever code changed the room.
            if (args.fromFollowWarp)
            {
                UpdateMinimapFromRoom(args.fromFollowWarp);
            }

            eventGroup.Unlock();
        });

        dungeonMinimap.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) {
            OnMinimapTileSelected(sender, dungeonMinimap.SelectedIndex);
        }));
        worldMinimap.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) {
            OnMinimapTileSelected(sender, worldMinimap.SelectedIndex);
        }));

        tilesetViewer1.HoverChangedEvent += eventGroup.Add <int>((sender, tile) => {
            if (tilesetViewer1.HoveringIndex != -1)
            {
                statusbar1.Set((uint)StatusbarMessage.TileHovering,
                               "Hovering Tile: 0x" + tilesetViewer1.HoveringIndex.ToString("X2"));
            }
            else
            {
                statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering);
            }
        });
        tilesetViewer1.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) {
            statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering);
            statusbar1.Set((uint)StatusbarMessage.TileSelected, "Selected Tile: 0x" + index.ToString("X2"));
        }));

        roomeditor1.HoverChangedEvent += eventGroup.Add <int>((sender, tile) => {
            if (roomeditor1.HoveringIndex != -1)
            {
                statusbar1.Set((uint)StatusbarMessage.TileHovering, string.Format(
                                   "Hovering Pos: {0},{1} (${1:X}{0:X})", roomeditor1.HoveringX, roomeditor1.HoveringY));
            }
            else
            {
                statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering);
            }
        });
        roomeditor1.WarpDestEditModeChangedEvent += eventGroup.Add <bool>((sender, activated) => {
            if (activated)
            {
                statusbar1.Set((uint)StatusbarMessage.WarpDestEditMode,
                               "Entered warp destination editing mode. To exit this mode, right-click on the warp destination and select \"Done\".");
            }
            else
            {
                statusbar1.RemoveAll((uint)StatusbarMessage.WarpDestEditMode);
            }
        });
        statusbar1.Set((uint)StatusbarMessage.TileSelected, "Selected Tile: 0x00");

        OnDarkenDungeonRoomsCheckboxToggled(null, null);


        // Event handlers from underlying data

        chestEventWrapper.Bind <ValueModifiedEventArgs>("ModifiedEvent", (sender, args) => UpdateChestData());
        chestEventWrapper.Bind <EventArgs>("DeletedEvent", (sender, args) => UpdateChestData());


        // Load "plugins"

        pluginCore = new PluginCore(this);
        LoadPlugins();

        mainWindow.ShowAll();

        eventGroup.UnlockAndClear();


        overallEditingContainer.Sensitive = false;

        if (directory != "")
        {
            OpenProject(directory);
        }
    }