// Copyright (c) 2023 Alex Diener. All rights reserved. #include "gamemath/MouseCoordinateTransforms.h" #include "PROJECT_NAME/Atoms.h" #include "PROJECT_NAME/Events.h" #include "PROJECT_NAME/GameScreen.h" #include "PROJECT_NAME/Globals.h" #include "PROJECT_NAME/SharedDefinitions.h" #include "shadercollection/ShaderCollection.h" #define stemobject_implementation GameScreen v_begin(); v_func(dispose); v_func(activate); v_func(deactivate); v_func(update); v_func(resized); v_func(mouseDown); v_func(mouseUp); v_func(mouseMoved); v_func(mouseDragged); v_func(mouseLeave); v_func(scrollWheel); v_func(keyDown); v_func(keyUp); v_func(keyModifiersChanged); v_func(gamepadAxisMoved); v_func(gamepadButtonDown); v_func(gamepadButtonUp); v_func(gamepadAttached); v_func(gamepadDetached); v_func(needsRedraw); v_func(listRenderables); v_end(); GameScreen * GameScreen_create(void) { stemobject_create_implementation(init) } static void listRenderables(RenderableIO * renderableIO, void * context) { GameScreen * self = context; call_virtual(listRenderables, self, renderableIO, 0, RECT4i_EMPTY); } bool GameScreen_init(GameScreen * self) { call_super(init, self); self->rootContainer = UIContainer_create(VECTOR2f(0.0f, 0.0f), VECTOR2f_ZERO, VECTOR2f_ZERO, VECTOR2f_ZERO, false, g_uiAppearance); self->renderLayer = RenderLayer_create(RENDER_LAYER_SORT_DRAW_ORDER_ONLY, listRenderables, self); self->active = false; self->lastMousePosition = g_lastMousePosition; self->backgrounded = false; return true; } void GameScreen_dispose(GameScreen * self) { UIContainer_dispose(self->rootContainer); RenderLayer_dispose(self->renderLayer); call_super(dispose, self); } static bool resized(Atom eventID, void * eventData, void * context) { GameScreen * self = context; call_virtual(resized, self); return true; } static bool backgrounded(Atom eventID, void * eventData, void * context) { GameScreen * self = context; self->backgrounded = true; return true; } static bool foregrounded(Atom eventID, void * eventData, void * context) { GameScreen * self = context; self->backgrounded = false; return true; } static bool mouseMoved(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseEvent * event = eventData; self->lastMousePosition = event->position; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(event->position, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); Vector2f transformedDelta = transformMouseDelta_aspectBox(event->delta, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); bool handled = call_virtual(mouseMoved, self, transformedPosition.x, transformedPosition.y, transformedDelta.x, transformedDelta.y, event->modifiers, event->timestamp); Shell_setCursor(call_virtual(getCursorAtPosition, self->rootContainer, transformedPosition.x, transformedPosition.y)); return handled; } static bool mouseDown(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseEvent * event = eventData; self->lastMousePosition = event->position; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(event->position, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); return call_virtual(mouseDown, self, event->buttonNumber, event->buttonMask, transformedPosition.x, transformedPosition.y, event->modifiers, event->timestamp); } static bool mouseDragged(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseEvent * event = eventData; self->lastMousePosition = event->position; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(event->position, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); Vector2f transformedDelta = transformMouseDelta_aspectBox(event->delta, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); return call_virtual(mouseDragged, self, event->buttonMask, transformedPosition.x, transformedPosition.y, transformedDelta.x, transformedDelta.y, event->modifiers, event->timestamp); } static bool mouseUp(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseEvent * event = eventData; self->lastMousePosition = event->position; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(event->position, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); return call_virtual(mouseUp, self, event->buttonNumber, event->buttonMask, transformedPosition.x, transformedPosition.y, event->modifiers, event->timestamp); } static bool mouseLeave(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseEvent * event = eventData; return call_virtual(mouseLeave, self, event->modifiers, event->timestamp); } static bool scrollWheel(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct mouseWheelEvent * event = eventData; self->lastMousePosition = event->position; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(event->position, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); return call_virtual(scrollWheel, self, transformedPosition.x, transformedPosition.y, event->deltaX, event->deltaY, event->buttonMask, event->modifiers, event->timestamp); } static bool keyDown(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct keyEvent * event = eventData; return call_virtual(keyDown, self, event->charCode, event->keyCode, event->modifiers, event->isRepeat, event->timestamp); } static bool keyUp(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct keyEvent * event = eventData; return call_virtual(keyUp, self, event->keyCode, event->modifiers, event->timestamp); } static bool keyModifiersChanged(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct keyEvent * event = eventData; return call_virtual(keyModifiersChanged, self, event->modifiers, event->lastModifiers, event->timestamp); } static bool gamepadAxisMoved(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct gamepadAxisEvent * event = eventData; call_virtual(gamepadAxisMoved, self, event->device, event->axisID, event->value, event->lastValue, event->timestamp); return false; } static bool gamepadButtonDown(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct gamepadButtonEvent * event = eventData; return call_virtual(gamepadButtonDown, self, event->device, event->buttonID, event->timestamp); } static bool gamepadButtonUp(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct gamepadButtonEvent * event = eventData; return call_virtual(gamepadButtonUp, self, event->device, event->buttonID, event->timestamp); } static bool gamepadAttached(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct Gamepad_device * device = eventData; return call_virtual(gamepadAttached, self, device); } static bool gamepadDetached(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct Gamepad_device * device = eventData; return call_virtual(gamepadDetached, self, device); } static bool draw(Atom eventID, void * eventData, void * context) { GameScreen * self = context; struct drawEvent * event = eventData; if (self->lastMousePosition.x != g_lastMousePosition.x || self->lastMousePosition.y != g_lastMousePosition.y) { self->lastMousePosition = g_lastMousePosition; Vector2f transformedPosition = transformMousePosition_aspectBoxLowerLeft(g_lastMousePosition, g_viewWidth, g_viewHeight, DISPLAY_WIDTH, DISPLAY_HEIGHT); call_virtual(mouseMoved, self, transformedPosition.x, transformedPosition.y, 0.0f, 0.0f, 0, event->referenceTime); } call_virtual(update, self, event->deltaTime); if (!self->active) { return false; } Renderer_clear(g_renderer, COLOR4f(0.0f, 0.0f, 0.0f, 0.0f)); Renderer_drawLayer(g_renderer, self->renderLayer, event->referenceTime, event->deltaTime); if (call_virtual(needsRedraw, self)) { Shell_redisplay(); } return true; } void GameScreen_update(GameScreen * self, double deltaTime) { } void GameScreen_resized(GameScreen * self) { } bool GameScreen_mouseDown(GameScreen * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, double timestamp) { bool handled = call_virtual(mouseDown, self->rootContainer, buttonNumber, buttonMask, x, y, modifiers, false, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_mouseUp(GameScreen * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, double timestamp) { bool handled = call_virtual(mouseUp, self->rootContainer, buttonNumber, buttonMask, x, y, modifiers, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_mouseMoved(GameScreen * self, float x, float y, float deltaX, float deltaY, unsigned int modifiers, double timestamp) { bool handled = call_virtual(mouseMoved, self->rootContainer, x, y, deltaX, deltaY, modifiers, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_mouseDragged(GameScreen * self, unsigned int buttonMask, float x, float y, float deltaX, float deltaY, unsigned int modifiers, double timestamp) { bool handled = call_virtual(mouseDragged, self->rootContainer, buttonMask, x, y, deltaX, deltaY, modifiers, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_mouseLeave(GameScreen * self, unsigned int modifiers, double timestamp) { return false; } bool GameScreen_scrollWheel(GameScreen * self, float x, float y, int deltaX, int deltaY, unsigned int buttonMask, unsigned int modifiers, double timestamp) { bool handled = call_virtual(scrollWheel, self->rootContainer, x, y, deltaX, deltaY, buttonMask, modifiers, false, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_keyDown(GameScreen * self, unsigned int charCode, unsigned int keyCode, unsigned int modifiers, bool isRepeat, double timestamp) { bool handled = call_virtual(keyDown, self->rootContainer, charCode, keyCode, modifiers, isRepeat, false, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_keyUp(GameScreen * self, unsigned int keyCode, unsigned int modifiers, double timestamp) { bool handled = call_virtual(keyUp, self->rootContainer, keyCode, modifiers, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_keyModifiersChanged(GameScreen * self, unsigned int modifiers, unsigned int lastModifiers, double timestamp) { bool handled = call_virtual(keyModifiersChanged, self->rootContainer, modifiers, lastModifiers, timestamp); if (handled) { Shell_redisplay(); } return handled; } bool GameScreen_gamepadAxisMoved(GameScreen * self, struct Gamepad_device * device, unsigned int axisID, float value, float lastValue, double timestamp) { return false; } bool GameScreen_gamepadButtonDown(GameScreen * self, struct Gamepad_device * device, unsigned int buttonID, double timestamp) { return false; } bool GameScreen_gamepadButtonUp(GameScreen * self, struct Gamepad_device * device, unsigned int buttonID, double timestamp) { return false; } bool GameScreen_gamepadAttached(GameScreen * self, struct Gamepad_device * device) { return false; } bool GameScreen_gamepadDetached(GameScreen * self, struct Gamepad_device * device) { return false; } bool GameScreen_needsRedraw(GameScreen * self) { if (call_virtual(needsRedraw, self->rootContainer)) { return true; } return false; } void GameScreen_listRenderables(GameScreen * self, RenderableIO * renderableIO, int drawOrderOffset, Rect4i clipBounds) { call_virtual(listRenderables, self->rootContainer, renderableIO, drawOrderOffset, clipBounds); } void GameScreen_activate(GameScreen * self, Screen * lastScreen, const char * transitionName) { EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_draw, draw, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_resized, resized, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_backgrounded, backgrounded, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_foregrounded, foregrounded, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_down, mouseDown, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_up, mouseUp, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_moved, mouseMoved, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_dragged, mouseDragged, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_leave, mouseLeave, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_scroll_wheel, scrollWheel, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_key_down, keyDown, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_key_up, keyUp, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_key_modifiers_changed, keyModifiersChanged, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_axis_move, gamepadAxisMoved, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_button_down, gamepadButtonDown, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_button_up, gamepadButtonUp, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_attached, gamepadAttached, self); EventDispatcher_registerForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_detached, gamepadDetached, self); self->active = true; Shell_redisplay(); } void GameScreen_deactivate(GameScreen * self, Screen * lastScreen, const char * transitionName) { self->active = false; self->lastMousePosition = g_lastMousePosition; EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_draw, draw, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_resized, resized, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_backgrounded, backgrounded, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_foregrounded, foregrounded, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_down, mouseDown, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_up, mouseUp, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_moved, mouseMoved, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_dragged, mouseDragged, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_leave, mouseLeave, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_mouse_scroll_wheel, scrollWheel, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_key_down, keyDown, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_key_up, keyUp, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_key_modifiers_changed, keyModifiersChanged, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_axis_move, gamepadAxisMoved, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_button_down, gamepadButtonDown, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_button_up, gamepadButtonUp, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_attached, gamepadAttached, self); EventDispatcher_unregisterForEvent(self->screenManager->eventDispatcher, ATOM_event_gamepad_detached, gamepadDetached, self); }