-
-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No way to get CommonEvent #330
Comments
Hello @mbenkmann Can you please give an example of what you want to achieve and how? All events have Timestamp and Type exported. CommonEvent is returned as default value in event type switch: func goEvent(cevent *CEvent) Event {
switch cevent.Type {
case WINDOWEVENT:
return (*WindowEvent)(unsafe.Pointer(cevent))
...
default:
return (*CommonEvent)(unsafe.Pointer(cevent))
}
} But it's probably never returned since SDL events usually have more specific types. |
What I want to do is use the Timestamp in my event loop, so that I can process events for the proper frames (because of CPU load and process scheduling it's possible that I miss frame and have to catch up).
The marked line could be something like
or
Both functions are trivial casts using unsafe.Pointer, but I would like that ugliness to be in the library code not in my client code. |
Another use case I have is a function that has a type switch with common code using the timestamp for all cases. Right now it looks like this:
It's really stupid to have to start every case with
Again, it would be way better to have one of the functions I detailed above. |
Even nicer of course would be to have sdl.Event give access to the fields directly. So the subtypes would have to be declared like this
NOTE: I am not an expert on the implementation details of Go, so I do not know if the memory layout of this composite struct is guaranteed to be compatible with C. I think it's very likely but I would double-check if you go this route. |
This is another issue of Go not having unions. sdl.Event is not a struct, it's an interface. The easy solution would be adding methods to access Type and Timestamp that are common to all event types. // Event is a union of all event structures used in SDL.
// (https://wiki.libsdl.org/SDL_Event)
type Event interface {
GetType() uint32 // the event type
GetTimestamp() uint32 // timestamp of the event
}
// CommonEvent contains common event data.
// (https://wiki.libsdl.org/SDL_Event)
type CommonEvent struct {
Type uint32 // the event type
Timestamp uint32 // timestamp of the event
}
// GetType returns the event type.
func (e *CommonEvent) GetType() uint32 {
return e.Type
}
// GetTimestamp returns timestamp of the event.
func (e *CommonEvent) GetTimestamp() uint32 {
return e.Timestamp
} After doing this to all event types it will be possible to receive the needed data before the type assertion: for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
fmt.Println(event.GetTimestamp())
} Doing it this way won't add any breaking changes to the library. But I do not like the duplication of both exporting the struct data and creating a getter method for it, also "Get" should not be used in method names in Go, and we can't have both exported struct field and method have the same names. I wonder if anyone does changes to the events data. If not, it would be nicer to have all event structs data received with getter methods and unexported in the structs themselves. // JoyDeviceEvent contains joystick device event information.
// (https://wiki.libsdl.org/SDL_JoyDeviceEvent)
type JoyDeviceEvent struct {
_type uint32 // JOYDEVICEADDED, JOYDEVICEREMOVED
timestamp uint32 // the timestamp of the event
which JoystickID // the joystick device index for the JOYDEVICEADDED event or the instance id for the JOYDEVICEREMOVED event
}
// Type returns the event type.
func (e *JoyDeviceEvent ) Type() uint32 {
return e._type
}
// Timestamp returns timestamp of the event.
func (e *JoyDeviceEvent ) Timestamp() uint32 {
return e.timestamp
}
// Timestamp returns timestamp of the event.
func (e *JoyDeviceEvent ) Which() uint32 {
return e.which
} On other hand this is a breaking change and everyone would need to rewrite their event loops from using exported struct field to methods. |
Creating functions for getting the type and timestamp seems to require less work for both sides. If it's not a method, I believe it doesn't violate the Go idiom of not having |
"I wonder if anyone does changes to the events data." Please do not make the struct fields private. Being able to create and modify instances of sdl structures in client code is crucial for writing unit tests. " would be nicer to have [...] getter methods [..]" puke. Maybe for a Java programmer. They've spread around this disease. |
I've created 3 possible solutions for this issue. The following are the implementation links, followed by what the client code would look like, assuming
https://github.com/mbenkmann/go-sdl2/commit/71e00c91d82e965f5a68221855b98faff496b15c
https://github.com/mbenkmann/go-sdl2/commit/3a4151d407cf6f8418d1339adcf8b4c335ea8faf
https://github.com/mbenkmann/go-sdl2/commit/1b31011754d367d5c5d9672994055cf773c41d2f
|
Added two new methods to event interface. No breaking changes. // Event is a union of all event structures used in SDL.
// (https://wiki.libsdl.org/SDL_Event)
type Event interface {
GetType() uint32 // the event type
GetTimestamp() uint32 // timestamp of the event
} |
Unless I'm missing something there does not seem to be any way to obtain a CommonEvent from an Event without using direct pointer conversion with package "unsafe". Some way should be added to either get a *CommonEvent or to otherwise access Timestamp and Type from an sdl.Event.
The text was updated successfully, but these errors were encountered: