From d6177955912b885c62f32c0e5843b90f160f9cd8 Mon Sep 17 00:00:00 2001 From: elasota Date: Tue, 25 Feb 2020 23:09:09 -0500 Subject: [PATCH] Level editor work --- Documentation/leveleditor.txt | 26 +++++++++ GpApp/Events.cpp | 22 ++++---- GpCommon/GpVOSEvent.h | 2 + PortabilityLayer/InputManager.cpp | 15 ++++++ PortabilityLayer/InputManager.h | 4 +- PortabilityLayer/PLCore.cpp | 16 +----- PortabilityLayer/PLCore.h | 2 - PortabilityLayer/PLKeyEncoding.h | 1 + PortabilityLayer/PLSysCalls.cpp | 4 ++ PortabilityLayer/WindowManager.cpp | 87 ++++++++++++++++++++++++++++++ PortabilityLayer/WindowManager.h | 2 + 11 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 Documentation/leveleditor.txt diff --git a/Documentation/leveleditor.txt b/Documentation/leveleditor.txt new file mode 100644 index 0000000..ad7038f --- /dev/null +++ b/Documentation/leveleditor.txt @@ -0,0 +1,26 @@ +The Room Editor is not yet fully functional. + +As with Glider PRO's Room Editor, custom backgrounds, sounds, and TV videos +are supported. + +Since Glider PRO used formats that were very Mac-specific, Aerofoil has +replaced most of them with more current formats. + +To add resources to a house, create a ZIP file with the extension ".gpa" with +the same name as the .gpd and .gpf files that already exist for the house. + +You can add resources by adding them to a folder named as the resource type, +with the appropriate extension. + +For example, for a "PICT" resource of ID "3000", create a file named "3000.bmp" +and put it in the "PICT" directory in the .gpa archive. + +PICT resources, used for custom decorations and backgrounds, must be BMP files. + +Sounds should go in a directory named "snd$20" +Sounds must be WAV format, monaural, 8-bit unsigned PCM, 22255 Hz. +Sounds recorded at a different sample rate will play back at the wrong speed. +Sounds that are not monaural or 8-bit unsigned PCM will fail to load. + +Resource IDs must be between -32768 and 32767. Other resource IDs will fail +to load. \ No newline at end of file diff --git a/GpApp/Events.cpp b/GpApp/Events.cpp index b921baf..bf69bf9 100644 --- a/GpApp/Events.cpp +++ b/GpApp/Events.cpp @@ -17,6 +17,7 @@ #include "House.h" #include "InputManager.h" #include "ObjectEdit.h" +#include "WindowManager.h" short BitchAboutColorDepth (void); @@ -74,18 +75,15 @@ void HandleMouseEvent (const GpMouseInputEvent &theEvent, uint32_t tick) switch (thePart) { - case inMenuBar: + case inMenuBar: menuChoice = MenuSelect(evtPoint); DoMenuChoice(menuChoice); break; - case inDrag: - DragWindow(whichWindow, evtPoint, &thisMac.screen); + case inDrag: + PortabilityLayer::WindowManager::GetInstance()->DragWindow(whichWindow, evtPoint, thisMac.screen); if (whichWindow == mainWindow) - { - SendBehind(mainWindow, (WindowPtr)0L); GetWindowLeftTop(whichWindow, &isEditH, &isEditV); - } else if (whichWindow == mapWindow) GetWindowLeftTop(whichWindow, &isMapH, &isMapV); else if (whichWindow == toolsWindow) @@ -97,7 +95,7 @@ void HandleMouseEvent (const GpMouseInputEvent &theEvent, uint32_t tick) HiliteAllWindows(); break; - case inGoAway: + case inGoAway: if (TrackGoAway(whichWindow, evtPoint)) { if (whichWindow == mapWindow) @@ -111,7 +109,7 @@ void HandleMouseEvent (const GpMouseInputEvent &theEvent, uint32_t tick) } break; - case inGrow: + case inGrow: if (whichWindow == mapWindow) { newSize = GrowWindow(mapWindow, evtPoint, &thisMac.gray); @@ -119,13 +117,13 @@ void HandleMouseEvent (const GpMouseInputEvent &theEvent, uint32_t tick) } break; - case inZoomIn: - case inZoomOut: + case inZoomIn: + case inZoomOut: if (TrackBox(whichWindow, evtPoint, thePart)) ZoomWindow(whichWindow, thePart, true); break; - case inContent: + case inContent: if (whichWindow == mainWindow) { hDelta = evtPoint.h - lastWhere.h; @@ -153,7 +151,7 @@ void HandleMouseEvent (const GpMouseInputEvent &theEvent, uint32_t tick) HandleLinkClick(evtPoint); break; - default: + default: break; } } diff --git a/GpCommon/GpVOSEvent.h b/GpCommon/GpVOSEvent.h index 403ec4a..9a8ef6f 100644 --- a/GpCommon/GpVOSEvent.h +++ b/GpCommon/GpVOSEvent.h @@ -220,6 +220,8 @@ namespace GpMouseButtons kRight, kX1, kX2, + + kCount }; } diff --git a/PortabilityLayer/InputManager.cpp b/PortabilityLayer/InputManager.cpp index fef420d..7cac251 100644 --- a/PortabilityLayer/InputManager.cpp +++ b/PortabilityLayer/InputManager.cpp @@ -15,6 +15,7 @@ namespace PortabilityLayer const KeyDownStates *GetKeys() const override; void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) override; void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) override; + void ApplyMouseEvent(const GpMouseInputEvent &vosEvent) override; int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) override; void ClearState() override; @@ -22,6 +23,7 @@ namespace PortabilityLayer private: void ApplyEventAsKey(const GpKeyboardInputEvent &vosEvent, bool bit); + void ApplyEventAsMouseButton(const GpMouseInputEvent &vosEvent, bool bit); void ApplyAnalogAxisEvent(const GpGamepadAnalogAxisEvent &axisEvent); KeyDownStates m_keyMap; @@ -49,6 +51,14 @@ namespace PortabilityLayer ApplyAnalogAxisEvent(vosEvent.m_event.m_analogAxisEvent); } + void InputManagerImpl::ApplyMouseEvent(const GpMouseInputEvent &vosEvent) + { + if (vosEvent.m_eventType == GpMouseEventTypes::kUp || vosEvent.m_eventType == GpMouseEventTypes::kLeave) + this->ApplyEventAsMouseButton(vosEvent, false); + else if (vosEvent.m_eventType == GpMouseEventTypes::kDown) + this->ApplyEventAsMouseButton(vosEvent, true); + } + int16_t InputManagerImpl::GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) { assert(playerNum < PL_INPUT_MAX_PLAYERS); @@ -105,6 +115,11 @@ namespace PortabilityLayer } } + void InputManagerImpl::ApplyEventAsMouseButton(const GpMouseInputEvent &vosEvent, bool bit) + { + m_keyMap.m_mouse.Set(vosEvent.m_button, bit); + } + void InputManagerImpl::ApplyAnalogAxisEvent(const GpGamepadAnalogAxisEvent &axisEvent) { if (axisEvent.m_player < PL_INPUT_MAX_PLAYERS) diff --git a/PortabilityLayer/InputManager.h b/PortabilityLayer/InputManager.h index 611c6b8..3a2044b 100644 --- a/PortabilityLayer/InputManager.h +++ b/PortabilityLayer/InputManager.h @@ -2,8 +2,9 @@ #include "GpVOSEvent.h" -struct GpKeyboardInputEvent; struct GpGamepadInputEvent; +struct GpKeyboardInputEvent; +struct GpMouseInputEvent; struct KeyDownStates; namespace PortabilityLayer @@ -14,6 +15,7 @@ namespace PortabilityLayer virtual const KeyDownStates *GetKeys() const = 0; virtual void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) = 0; virtual void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) = 0; + virtual void ApplyMouseEvent(const GpMouseInputEvent &vosEvent) = 0; virtual int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) = 0; virtual void ClearState() = 0; diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index eaa9dcd..11a08b7 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -108,16 +108,6 @@ short FindWindow(Point point, WindowPtr *window) return part; } -void DragWindow(WindowPtr window, Point start, Rect *bounds) -{ - PL_NotYetImplemented(); -} - -void SendBehind(WindowPtr window, WindowPtr behind) -{ - PL_NotYetImplemented(); -} - void BringToFront(WindowPtr window) { PL_NotYetImplemented(); @@ -519,14 +509,12 @@ Boolean Button() Boolean StillDown() { - PL_NotYetImplemented(); - return false; + return PortabilityLayer::InputManager::GetInstance()->GetKeys()->m_mouse.Get(GpMouseButtons::kLeft); } Boolean WaitMouseUp() { - PL_NotYetImplemented(); - return false; + return StillDown(); } short Random() diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index a407d90..d7901f4 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -247,8 +247,6 @@ void HideCursor(); void Delay(int ticks, UInt32 *endTickCount); short FindWindow(Point point, WindowPtr *window); // Translates global coordinates to window coordinates, returns a region ID -void DragWindow(WindowPtr window, Point start, Rect *bounds); // Drags the window (probably not implemented) -void SendBehind(WindowPtr window, WindowPtr behind); void BringToFront(WindowPtr window); bool TrackGoAway(WindowPtr window, Point point); // Returns true if the close box was actually clicked (?) Int32 GrowWindow(WindowPtr window, Point start, Rect *size); diff --git a/PortabilityLayer/PLKeyEncoding.h b/PortabilityLayer/PLKeyEncoding.h index 2e8ea1d..796c57c 100644 --- a/PortabilityLayer/PLKeyEncoding.h +++ b/PortabilityLayer/PLKeyEncoding.h @@ -60,6 +60,7 @@ struct KeyDownStates GpBitfield m_numPadSpecial; GpBitfield m_fKey; GpBitfield m_gamepadButtons[PL_INPUT_MAX_PLAYERS]; + GpBitfield m_mouse; bool IsSet(intptr_t packedVOSCode) const; }; diff --git a/PortabilityLayer/PLSysCalls.cpp b/PortabilityLayer/PLSysCalls.cpp index 9161536..95ea907 100644 --- a/PortabilityLayer/PLSysCalls.cpp +++ b/PortabilityLayer/PLSysCalls.cpp @@ -32,6 +32,10 @@ static void TranslateMouseInputEvent(const GpVOSEvent &vosEventBase, uint32_t ti if (TimeTaggedVOSEvent *evt = queue->Enqueue()) *evt = TimeTaggedVOSEvent::Create(vosEventBase, timestamp); } + + PortabilityLayer::InputManager *inputManager = PortabilityLayer::InputManager::GetInstance(); + + inputManager->ApplyMouseEvent(vosEvent); } static void TranslateGamepadInputEvent(const GpGamepadInputEvent &vosEvent, PortabilityLayer::EventQueue *queue) diff --git a/PortabilityLayer/WindowManager.cpp b/PortabilityLayer/WindowManager.cpp index d304140..0dfeddf 100644 --- a/PortabilityLayer/WindowManager.cpp +++ b/PortabilityLayer/WindowManager.cpp @@ -13,6 +13,7 @@ #include "QDGraf.h" #include "QDManager.h" #include "QDPixMap.h" +#include "PLTimeTaggedVOSEvent.h" #include "Vec2i.h" #include "WindowDef.h" @@ -27,6 +28,7 @@ namespace PortabilityLayer { virtual void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const = 0; virtual void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const = 0; + virtual bool GetChromeInteractionZone(const WindowImpl *window, const Vec2i &point, RegionID &outRegion) const = 0; }; template @@ -44,6 +46,7 @@ namespace PortabilityLayer public: void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const override; void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const override; + bool GetChromeInteractionZone(const WindowImpl *window, const Vec2i &point, RegionID &outRegion) const override; }; class GenericWindowChromeTheme final : public WindowChromeThemeSingleton @@ -51,6 +54,7 @@ namespace PortabilityLayer public: void GetChromePadding(const WindowImpl *window, uint16_t padding[WindowChromeSides::kCount]) const override; void RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const override; + bool GetChromeInteractionZone(const WindowImpl *window, const Vec2i &point, RegionID &outRegion) const override; private: void RenderChromeTop(WindowImpl *window, DrawSurface *surface) const; @@ -89,6 +93,7 @@ namespace PortabilityLayer void GetChromePadding(uint16_t padding[WindowChromeSides::kCount]) const; void GetChromeDimensions(int width, int height, Rect dimensions[WindowChromeSides::kCount]) const; + bool GetChromeInteractionZone(const Vec2i &point, RegionID &outRegion) const; bool IsBorderless() const; uint16_t GetStyleFlags() const; @@ -118,6 +123,7 @@ namespace PortabilityLayer void HideWindow(Window *window) override; void FindWindow(const Point &point, Window **outWindow, short *outRegion) const override; void DestroyWindow(Window *window) override; + void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) override; void RenderFrame(IGpDisplayDriver *displayDriver) override; @@ -157,6 +163,11 @@ namespace PortabilityLayer padding[WindowChromeSides::kRight] = 1; } + bool SimpleBoxChromeTheme::GetChromeInteractionZone(const WindowImpl *window, const Vec2i &point, RegionID &outRegion) const + { + return false; + } + void SimpleBoxChromeTheme::RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const { surface->SetForeColor(StdColors::Black()); @@ -194,6 +205,31 @@ namespace PortabilityLayer } } + bool GenericWindowChromeTheme::GetChromeInteractionZone(const WindowImpl *window, const Vec2i &point, RegionID &outRegion) const + { + const DrawSurface *surface = window->GetDrawSurface(); + const Rect rect = (*surface->m_port.GetPixMap())->m_rect; + + if (window->GetStyleFlags() & WindowStyleFlags::kMiniBar) + { + if (point.m_x >= 0 && point.m_x < rect.Width() && point.m_y < 0 && point.m_y >= -13) + { + outRegion = RegionID::inDrag; + return true; + } + } + else + { + if (point.m_x >= 0 && point.m_x < rect.Width() && point.m_y < 0 && point.m_y >= -17) + { + outRegion = RegionID::inDrag; + return true; + } + } + + return false; + } + void GenericWindowChromeTheme::RenderChrome(WindowImpl *window, DrawSurface *surface, WindowChromeSide_t chromeSide) const { if (window->GetStyleFlags() & WindowStyleFlags::kMiniBar) @@ -529,6 +565,11 @@ namespace PortabilityLayer dimensions[WindowChromeSides::kRight] = Rect::Create(0, 0, leftAndRightHeight, padding[WindowChromeSides::kRight]); } + bool WindowImpl::GetChromeInteractionZone(const Vec2i &point, RegionID &outRegion) const + { + return m_chromeTheme->GetChromeInteractionZone(this, point, outRegion); + } + bool WindowImpl::IsBorderless() const { return (m_styleFlags & WindowStyleFlags::kBorderless) != 0; @@ -658,6 +699,14 @@ namespace PortabilityLayer const int32_t localX = point.h - window->m_wmX; const int32_t localY = point.v - window->m_wmY; + RegionID chromeInteractionZone = inContent; + if (window->GetChromeInteractionZone(Vec2i(localX, localY), chromeInteractionZone)) + { + *outRegion = chromeInteractionZone; + *outWindow = window; + return; + } + if (localX >= 0 && localY >= 0 && localX < windowRect.right && localY < windowRect.bottom) { if (outWindow) @@ -692,6 +741,44 @@ namespace PortabilityLayer PortabilityLayer::MemoryManager::GetInstance()->Release(windowImpl); } + void WindowManagerImpl::DragWindow(Window *window, const Point &startPointRef, const Rect &constraintRect) + { + int32_t baseX = startPointRef.h; + int32_t baseY = startPointRef.v; + + for (;;) + { + TimeTaggedVOSEvent evt; + if (WaitForEvent(&evt, 1)) + { + if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) + { + const GpMouseInputEvent &mouseEvent = evt.m_vosEvent.m_event.m_mouseInputEvent; + int32_t x = mouseEvent.m_x; + int32_t y = mouseEvent.m_y; + + if (x < constraintRect.left) + x = constraintRect.left; + if (x >= constraintRect.right) + x = constraintRect.right - 1; + if (y < constraintRect.top) + y = constraintRect.top; + if (y >= constraintRect.bottom) + y = constraintRect.bottom - 1; + + window->m_wmX += x - baseX; + window->m_wmY += y - baseY; + + baseX = x; + baseY = y; + + if (mouseEvent.m_eventType == GpMouseEventTypes::kUp) + break; + } + } + } + } + void WindowManagerImpl::RenderFrame(IGpDisplayDriver *displayDriver) { PortabilityLayer::DisplayDeviceManager *dd = PortabilityLayer::DisplayDeviceManager::GetInstance(); diff --git a/PortabilityLayer/WindowManager.h b/PortabilityLayer/WindowManager.h index eb3670a..a55f3b5 100644 --- a/PortabilityLayer/WindowManager.h +++ b/PortabilityLayer/WindowManager.h @@ -5,6 +5,7 @@ struct DrawSurface; struct GDevice; struct IGpDisplayDriver; struct Point; +struct Rect; struct Window; namespace PortabilityLayer @@ -23,6 +24,7 @@ namespace PortabilityLayer virtual void HideWindow(Window *window) = 0; virtual void FindWindow(const Point &point, Window **outWindow, short *outRegion) const = 0; virtual void DestroyWindow(Window *window) = 0; + virtual void DragWindow(Window *window, const Point &startPoint, const Rect &constraintRect) = 0; virtual void RenderFrame(IGpDisplayDriver *displayDriver) = 0;