Today started with making some meaningful progress on level editing, and devolved into re-writing most of the low-level mouse input API. Bah.
I did make some progress rearranging and designing things such that each component can basically handle its own editor functionality (deciding how do draw its selection box, whether it's clicked or not, and what to display when it's the active object). This looks like it will work better than having some sort of master "editor" class running the show.
Then I started to notice some weird input problems. After clicking on an object and selecting Rotate, it wouldn't let me rotate for some reason. Trying a second time would work. It turns out the "mouse up" event from selecting the object was basically being saved as the last mouse event, and was then being read as the "mouse up" event for committing the edit immediately after entering the edit mode.
The thing with handling mouse input is that it's possible to get multiple mouse events in a single frame, or it's possible to get none. It's also important to know the mouse location at each button event. During the game update, if you only look at the last event each frame, or even some sort of union of the states on a frame, you miss some meaningful information.
The keyboard is a little more forgiving - generally, you only want to know if a key is down right now, or if a key was pressed for the first time since the last update. Mouse input cares a lot more about both button up and button down events, where the cursor was when it happened, and what order it happened in.
So, the current solution is to buffer the mouse input for a frame so I can play it back, basically like a keyboard buffer. This works OK, except where I have some key-checking and mouse-checking code mixed together, and the key-checking code doesn't execute unless there has been a mouse event on that frame.
I get the feeling I have caught teh dumb and that there is a simple, clean and obvious solution that I am just not seeing.
The only thing that really comes to mind is to do the input processing from the mouse event callback, so there is only ever one mouse event in the queue... which I was actually doing at one point, but abandoned when I moved to the component architecture.
I hear the Giant Code Axe being sharpened.