More stuff, fix saved games

This commit is contained in:
elasota
2020-01-05 02:33:03 -05:00
parent a4b8db1065
commit aca18df74b
58 changed files with 1075 additions and 454 deletions

View File

@@ -5,11 +5,13 @@
#include "PLArrayView.h"
#include "PLBigEndian.h"
#include "PLButtonWidget.h"
#include "PLCheckboxWidget.h"
#include "PLDialogs.h"
#include "PLIconWidget.h"
#include "PLImageWidget.h"
#include "PLInvisibleWidget.h"
#include "PLLabelWidget.h"
#include "PLRadioButtonWidget.h"
#include "PLPasStr.h"
#include "PLStandardColors.h"
#include "PLSysCalls.h"
@@ -108,8 +110,6 @@ namespace PortabilityLayer
DialogItem::~DialogItem()
{
if (m_widget)
m_widget->Destroy();
}
Widget *DialogItem::GetWidget() const
@@ -303,7 +303,11 @@ namespace PortabilityLayer
widget = ImageWidget::Create(basicState);
break;
case SerializedDialogItemTypeCodes::kCheckBox:
//widget = CheckboxWidget::Create(basicState);
//break;
case SerializedDialogItemTypeCodes::kRadioButton:
widget = RadioButtonWidget::Create(basicState);
break;
case SerializedDialogItemTypeCodes::kEditBox:
default:
widget = InvisibleWidget::Create(basicState);
@@ -321,21 +325,7 @@ namespace PortabilityLayer
void DialogImpl::DrawControls(bool redraw)
{
DrawSurface *surface = m_window->GetDrawSurface();
if (redraw)
{
surface->SetForeColor(StdColors::White());
surface->FillRect(surface->m_port.GetRect());
}
for (ArrayViewIterator<const DialogItem> it = GetItems().begin(), itEnd = GetItems().end(); it != itEnd; ++it)
{
const DialogItem &item = *it;
Widget *widget = item.GetWidget();
if (widget->IsVisible())
widget->DrawControl(surface);
}
m_window->DrawControls();
}
Point DialogImpl::MouseToDialog(const GpMouseInputEvent &evt)

View File

@@ -33,6 +33,7 @@ namespace PortabilityLayer
PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t creationDisposition, IOStream *&outStream) override;
bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) override;
bool PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) override;
static FileManagerImpl *GetInstance();
@@ -181,6 +182,11 @@ namespace PortabilityLayer
return PortabilityLayer::HostFileSystem::GetInstance()->PromptSaveFile(dirID, path, outPathLength, pathCapacity, extFN);
}
bool FileManagerImpl::PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity)
{
return PortabilityLayer::HostFileSystem::GetInstance()->PromptOpenFile(dirID, path, outPathLength, pathCapacity);
}
FileManagerImpl *FileManagerImpl::GetInstance()
{
return &ms_instance;

View File

@@ -36,6 +36,7 @@ namespace PortabilityLayer
virtual PLError_t RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream) = 0;
virtual bool PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName) = 0;
virtual bool PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity) = 0;
static FileManager *GetInstance();
};

View File

@@ -1,13 +1,16 @@
#pragma once
#pragma once
#include <stdint.h>
namespace PortabilityLayer
{
class HostAudioChannel;
class HostAudioDriver
{
public:
virtual HostAudioChannel *CreateChannel() = 0;
virtual void SetMasterVolume(uint32_t vol, uint32_t maxVolume) = 0;
static HostAudioDriver *GetInstance();
static void SetInstance(HostAudioDriver *instance);

View File

@@ -20,6 +20,7 @@ namespace PortabilityLayer
virtual HostDirectoryCursor *ScanDirectory(VirtualDirectory_t virtualDirectory) = 0;
virtual bool PromptSaveFile(VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName) = 0;
virtual bool PromptOpenFile(VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity) = 0;
virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0;
static HostFileSystem *GetInstance();

View File

@@ -16,6 +16,7 @@ namespace PortabilityLayer
void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) override;
void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) override;
int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) override;
void ClearState() override;
static InputManagerImpl *GetInstance();
@@ -55,6 +56,12 @@ namespace PortabilityLayer
return m_axisStates[playerNum][gamepadAxis];
}
void InputManagerImpl::ClearState()
{
memset(&m_axisStates, 0, sizeof(m_axisStates));
memset(&m_keyMap, 0, sizeof(m_keyMap));
}
void InputManagerImpl::ApplyEventAsKey(const GpKeyboardInputEvent &vosEvent, bool bit)
{
switch (vosEvent.m_keyIDSubset)

View File

@@ -15,6 +15,7 @@ namespace PortabilityLayer
virtual void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) = 0;
virtual void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) = 0;
virtual int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) = 0;
virtual void ClearState() = 0;
static InputManager *GetInstance();
};

View File

@@ -129,6 +129,7 @@ namespace PortabilityLayer
void SetMenuEnabled(const THandle<Menu> &menuHandle, bool enabled) override;
void SetItemEnabled(const THandle<Menu> &menu, unsigned int index, bool enabled) override;
void SetItemChecked(const THandle<Menu> &menu, unsigned int index, bool checked) override;
bool SetItemText(const THandle<Menu> &menu, unsigned int index, const PLPasStr &str) override;
bool IsPointInMenuBar(const Vec2i &point) const override;
void MenuSelect(const Vec2i &initialPoint, int16_t *outMenu, uint16_t *outItem) override;
@@ -442,6 +443,8 @@ namespace PortabilityLayer
if (m_lastMenu == menu)
m_lastMenu = menuPtr->prevMenu;
menu.Dispose();
DrawMenuBar();
}
@@ -476,6 +479,44 @@ namespace PortabilityLayer
menu->menuItems[index].checked = checked;
}
bool MenuManagerImpl::SetItemText(const THandle<Menu> &menu, unsigned int index, const PLPasStr &str)
{
Menu *menuPtr = *menu;
PortabilityLayer::MMHandleBlock *oldHandle = menuPtr->stringBlobHandle;
size_t oldSize = oldHandle->m_size;
const uint8_t *oldStrBlob = static_cast<const uint8_t*>(oldHandle->m_contents);
const size_t newSize = oldSize - oldStrBlob[menuPtr->menuItems[index].nameOffsetInStringBlob] + str.Length() + 1;
THandle<uint8_t> newHandle = THandle<uint8_t>(PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(newSize));
if (!newHandle)
return false;
uint8_t *strWritePtr = *newHandle;
uint32_t writeOffset = 0;
for (size_t i = 0; i < menuPtr->numMenuItems; i++)
{
MenuItem &menuItem = menuPtr->menuItems[i];
const PLPasStr copyStr = (i == index) ? str : PLPasStr(oldStrBlob + menuItem.nameOffsetInStringBlob);
menuItem.nameOffsetInStringBlob = writeOffset;
strWritePtr[writeOffset] = copyStr.Length();
writeOffset++;
memcpy(strWritePtr + writeOffset, copyStr.UChars(), copyStr.Length());
writeOffset += copyStr.Length();
}
PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(menuPtr->stringBlobHandle);
menuPtr->stringBlobHandle = newHandle.MMBlock();
}
bool MenuManagerImpl::IsPointInMenuBar(const Vec2i &point) const
{
return point.m_y >= 0 && static_cast<uint32_t>(point.m_y) < kMenuBarHeight;

View File

@@ -1,10 +1,11 @@
#pragma once
#include <stdint.h>
template<class T>
class THandle;
#include <stdint.h>
class PLPasStr;
struct IGpDisplayDriver;
struct Menu;
@@ -31,6 +32,7 @@ namespace PortabilityLayer
virtual void SetMenuEnabled(const THandle<Menu> &menuHandle, bool enabled) = 0;
virtual void SetItemEnabled(const THandle<Menu> &menu, unsigned int index, bool enabled) = 0;
virtual void SetItemChecked(const THandle<Menu> &menu, unsigned int index, bool checked) = 0;
virtual bool SetItemText(const THandle<Menu> &menu, unsigned int index, const PLPasStr &str) = 0;
virtual bool IsPointInMenuBar(const Vec2i &point) const = 0;

View File

@@ -0,0 +1,20 @@
#include "PLCheckboxWidget.h"
namespace PortabilityLayer
{
CheckboxWidget::CheckboxWidget(const WidgetBasicState &state)
: WidgetSpec<CheckboxWidget>(state)
{
}
CheckboxWidget::~CheckboxWidget()
{
}
bool CheckboxWidget::Init(const WidgetBasicState &state)
{
(void)state;
return true;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "PLWidgets.h"
namespace PortabilityLayer
{
class CheckboxWidget final : public WidgetSpec<CheckboxWidget>
{
public:
CheckboxWidget(const WidgetBasicState &state);
~CheckboxWidget();
bool Init(const WidgetBasicState &state) override;
};
}

View File

@@ -7,6 +7,12 @@ int FindControl(Point point, WindowPtr window, ControlHandle *outControl)
return 0;
}
int FindControl(Point point, WindowPtr window, PortabilityLayer::Widget **outControl)
{
PL_NotYetImplemented();
return 0;
}
void SetControlValue(ControlHandle control, int value)
{
PL_NotYetImplemented();
@@ -54,6 +60,12 @@ Boolean TrackControl(ControlHandle control, Point point, ControlActionUPP proc)
return false;
}
Boolean TrackControl(PortabilityLayer::Widget *widget, Point point, ControlActionUPP proc)
{
PL_NotYetImplemented();
return false;
}
long GetControlReference(ControlHandle control)
{
PL_NotYetImplemented();
@@ -70,3 +82,8 @@ void HiliteControl(ControlHandle control, int unknown)
{
PL_NotYetImplemented();
}
void HiliteControl(PortabilityLayer::Widget *widget, int unknown)
{
PL_NotYetImplemented();
}

View File

@@ -4,6 +4,11 @@
#include "PLCore.h"
namespace PortabilityLayer
{
class Widget;
}
struct Control
{
};
@@ -13,11 +18,6 @@ typedef THandle<Control> ControlHandle;
typedef void(*ControlActionProc)(ControlHandle control, short part);
typedef ControlActionProc ControlActionUPP;
enum BuiltinCDEFs
{
scrollBarProc = 16,
};
enum ControlParts
{
kControlUpButtonPart = 1,
@@ -29,7 +29,8 @@ enum ControlParts
};
int FindControl(Point point, WindowPtr window, ControlHandle *outControl); // Returns part
int FindControl(Point point, WindowPtr window, PortabilityLayer::Widget **outControl); // Returns part
int FindControl(Point point, WindowPtr window, ControlHandle *outControl);
void SetControlValue(ControlHandle control, int value);
@@ -41,8 +42,10 @@ ControlHandle NewControl(WindowPtr window, const Rect *rect, const PLPasStr &lab
ControlActionUPP NewControlActionUPP(ControlActionProc proc);
void DisposeControlActionUPP(ControlActionUPP upp);
Boolean TrackControl(ControlHandle control, Point point, ControlActionUPP proc);
Boolean TrackControl(PortabilityLayer::Widget *control, Point point, ControlActionUPP proc);
long GetControlReference(ControlHandle control); // Returns userdata
ControlHandle GetNewControl(int resID, WindowPtr window);
void HiliteControl(ControlHandle control, int unknown);
void HiliteControl(PortabilityLayer::Widget *widget, int unknown);
#endif

View File

@@ -30,11 +30,13 @@
#include "RenderedFont.h"
#include "ResTypeID.h"
#include "RandomNumberGenerator.h"
#include "PLArrayViewIterator.h"
#include "PLBigEndian.h"
#include "PLEventQueue.h"
#include "PLKeyEncoding.h"
#include "PLSysCalls.h"
#include "PLTimeTaggedVOSEvent.h"
#include "PLWidgets.h"
#include "QDManager.h"
#include "Vec2i.h"
#include "WindowDef.h"
@@ -184,11 +186,6 @@ void BringToFront(WindowPtr window)
PL_NotYetImplemented();
}
void ShowHide(WindowPtr window, Boolean hide)
{
PL_NotYetImplemented();
}
bool TrackGoAway(WindowPtr window, Point point)
{
PL_NotYetImplemented();
@@ -627,16 +624,6 @@ Boolean WaitMouseUp()
return false;
}
void LocalToGlobal(Point *point)
{
PL_NotYetImplemented();
}
void GlobalToLocal(Point *point)
{
PL_NotYetImplemented();
}
short Random()
{
// Should return with range -32767..32767
@@ -820,11 +807,20 @@ Window::Window()
: m_surface(PortabilityLayer::QDPortType_Window)
, m_wmX(0)
, m_wmY(0)
, m_widgets(nullptr)
, m_numWidgets(0)
{
}
Window::~Window()
{
if (m_widgets)
{
for (size_t i = 0; i < m_numWidgets; i++)
m_widgets[i]->Destroy();
PortabilityLayer::MemoryManager::GetInstance()->Release(m_widgets);
}
}
DrawSurface *Window::GetDrawSurface() const
@@ -836,3 +832,41 @@ Point Window::MouseToLocal(const GpMouseInputEvent &evt) const
{
return Point::Create(evt.m_x - m_wmX, evt.m_y - m_wmY);
}
Point Window::TopLeftCoord() const
{
return Point::Create(m_wmX, m_wmY);
}
bool Window::AddWidget(PortabilityLayer::Widget *widget)
{
if (m_widgets == nullptr)
{
m_widgets = static_cast<PortabilityLayer::Widget**>(PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(PortabilityLayer::Widget *)));
if (m_widgets == nullptr)
return false;
}
else
{
void *newBuffer = PortabilityLayer::MemoryManager::GetInstance()->Realloc(m_widgets, (m_numWidgets + 1) * sizeof(PortabilityLayer::Widget*));
if (newBuffer == nullptr)
return false;
m_widgets = static_cast<PortabilityLayer::Widget**>(newBuffer);
}
m_widgets[m_numWidgets++] = widget;
return true;
}
void Window::DrawControls()
{
DrawSurface *surface = GetDrawSurface();
for (size_t i = 0; i < m_numWidgets; i++)
{
PortabilityLayer::Widget *widget = m_widgets[i];
if (widget->IsVisible())
widget->DrawControl(surface);
}
}

View File

@@ -22,6 +22,7 @@ namespace PortabilityLayer
{
struct MMHandleBlock;
class IOStream;
class Widget;
}
typedef uint8_t Boolean;
@@ -43,6 +44,7 @@ typedef unsigned char *StringPtr;
class PLPasStr;
struct DrawSurface;
struct Menu;
typedef void *Ptr;
@@ -108,6 +110,13 @@ struct Window
// Convenience method to convert a mouse event to local point
Point MouseToLocal(const GpMouseInputEvent &evt) const;
// Convenience method that returns a 16-bit precision X/Y
Point TopLeftCoord() const;
bool AddWidget(PortabilityLayer::Widget *widget);
void DrawControls();
DrawSurface m_surface; // Must be the first item until the immediate mode draw API is completely removed
// The port is always at 0,0
@@ -117,6 +126,9 @@ struct Window
protected:
~Window();
PortabilityLayer::Widget **m_widgets;
size_t m_numWidgets;
};
struct DateTimeRec
@@ -269,7 +281,6 @@ short FindWindow(Point point, WindowPtr *window); // Translates global coordinat
void DragWindow(WindowPtr window, Point start, Rect *bounds); // Drags the window (probably not implemented)
void SendBehind(WindowPtr window, WindowPtr behind);
void BringToFront(WindowPtr window);
void ShowHide(WindowPtr window, Boolean hide);
bool TrackGoAway(WindowPtr window, Point point); // Returns true if the close box was actually clicked (?)
Int32 GrowWindow(WindowPtr window, Point start, Rect *size);
bool TrackBox(WindowPtr window, Point point, int part); // Returns true if grow/shrink box was clicked (part corresponds to type)
@@ -320,8 +331,6 @@ Boolean Button(); // Returns true if there's a mouse down event in the queue
Boolean StillDown();
Boolean WaitMouseUp();
void LocalToGlobal(Point *point);
void GlobalToLocal(Point *point);
short Random();
void GetDateTime(UInt32 *dateTime);
void GetTime(DateTimeRec *dateTime);

View File

@@ -27,6 +27,6 @@ namespace PortabilityLayer
const Point topLeftCorner = Point::Create(m_rect.left, m_rect.top);
const Point textStartPoint = topLeftCorner + Point::Create(0, surface->MeasureFontAscender());
surface->DrawString(textStartPoint, m_text.ToShortStr());
surface->DrawStringWrap(textStartPoint, m_rect, m_text.ToShortStr());
}
}

View File

@@ -0,0 +1,14 @@
#include "PLPopupMenuWidget.h"
namespace PortabilityLayer
{
PopupMenuWidget::PopupMenuWidget(const WidgetBasicState &state)
: WidgetSpec<PopupMenuWidget>(state)
{
}
bool PopupMenuWidget::Init(const WidgetBasicState &state)
{
return true;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "PascalStr.h"
#include "PLWidgets.h"
namespace PortabilityLayer
{
class PopupMenuWidget final : public WidgetSpec<PopupMenuWidget>
{
public:
explicit PopupMenuWidget(const WidgetBasicState &state);
bool Init(const WidgetBasicState &state) override;
};
}

View File

@@ -427,11 +427,6 @@ static void PlotLine(PortabilityLayer::QDState *qdState, DrawSurface *surface, c
surface->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
void SetOrigin(int x, int y)
{
PL_NotYetImplemented();
}
namespace
{
static bool SystemColorToRGBAColor(SystemColorID color, PortabilityLayer::RGBAColor &rgbaColor)
@@ -610,6 +605,116 @@ void DrawSurface::DrawString(const Point &point, const PLPasStr &str)
m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str)
{
PortabilityLayer::QDPort *port = &m_port;
PortabilityLayer::QDState *qdState = m_port.GetState();
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
const int fontSize = qdState->m_fontSize;
const int fontVariationFlags = qdState->m_fontVariationFlags;
PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily;
PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, fontVariationFlags);
Point penPos = point;
const size_t len = str.Length();
const uint8_t *chars = str.UChars();
PixMap *pixMap = *port->GetPixMap();
const Rect limitRect = pixMap->m_rect.Intersect(constrainRect);;
const Rect areaRect = constrainRect;
if (!limitRect.IsValid() || !areaRect.IsValid())
return; // ???
Point paraStartPos = penPos;
size_t currentStartChar = 0;
size_t currentSpanLength = 0;
for (;;)
{
if (currentStartChar == len)
break;
size_t lastWhitespace = currentStartChar;
bool shouldSkipSpaces = false;
size_t committedLength = 0;
size_t i = currentStartChar;
// Find a span to print
int32_t spanWidth = 0;
for (;;)
{
if (i == len)
{
committedLength = i - currentStartChar;
break;
}
uint8_t character = chars[i];
if (character <= ' ')
{
committedLength = i - currentStartChar + 1;
if (character == '\r')
break;
i++;
}
else
{
const PortabilityLayer::RenderedGlyphMetrics *metrics = nullptr;
const void *glyphData = nullptr;
if (!rfont->GetGlyph(chars[i], metrics, glyphData))
{
i++;
continue;
}
spanWidth += metrics->m_advanceX;
int32_t glyphEnd = penPos.h + spanWidth;
if (glyphEnd >= constrainRect.right)
{
if (committedLength == 0)
{
// Word didn't fit
committedLength = i - currentStartChar;
if (committedLength == 0)
committedLength = 1; // Nothing fit, consume one char
}
break;
}
i++;
}
}
for (size_t ci = 0; ci < committedLength; ci++)
{
const uint8_t character = chars[currentStartChar + ci];
DrawGlyph(qdState, pixMap, pixMap->m_rect, penPos, rfont, character);
}
currentStartChar += committedLength;
paraStartPos.v += rfont->GetMetrics().m_linegap;
penPos = paraStartPos;
}
m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
size_t DrawSurface::MeasureString(const PLPasStr &str)
{
const PortabilityLayer::QDState *qdState = m_port.GetState();
@@ -650,6 +755,26 @@ int32_t DrawSurface::MeasureFontAscender()
return rfont->GetMetrics().m_ascent;
}
int32_t DrawSurface::MeasureFontLineGap()
{
const PortabilityLayer::QDState *qdState = m_port.GetState();
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily;
if (!fontFamily)
return 0;
const int variationFlags = qdState->m_fontVariationFlags;
const int fontSize = qdState->m_fontSize;
PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, variationFlags);
if (!rfont)
return 0;
return rfont->GetMetrics().m_linegap;
}
void DrawSurface::DrawPicture(THandle<Picture> pictHdl, const Rect &bounds)
{
if (!pictHdl)
@@ -799,7 +924,7 @@ void DrawSurface::FillRect(const Rect &rect)
void DrawSurface::FillRectWithPattern8x8(const Rect &rect, const uint8_t *pattern)
{
PL_NotYetImplemented();
PL_NotYetImplemented_TODO("FillWithPattern");
m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}

View File

@@ -105,7 +105,6 @@ PLError_t PlotIconSuite(Rect *rect, Handle iconSuite);
void SetRect(Rect *rect, short left, short top, short right, short bottom);
int TextWidth(const PLPasStr &str, int firstChar1Based, int length);
void SetOrigin(int x, int y);
void ForeColor(SystemColorID color);
void BackColor(SystemColorID color);
void GetForeColor(RGBColor *color);

View File

@@ -0,0 +1,54 @@
#include "PLRadioButtonWidget.h"
#include "PLStandardColors.h"
#include "FontFamily.h"
#include <algorithm>
namespace PortabilityLayer
{
RadioButtonWidget::RadioButtonWidget(const WidgetBasicState &state)
: WidgetSpec<RadioButtonWidget>(state)
, m_text(state.m_text)
{
}
RadioButtonWidget::~RadioButtonWidget()
{
}
bool RadioButtonWidget::Init(const WidgetBasicState &state)
{
(void)state;
return true;
}
void RadioButtonWidget::DrawControl(DrawSurface *surface)
{
if (!m_rect.IsValid())
return;
uint16_t radioFrameSize = std::min<uint16_t>(12, std::min(m_rect.Width(), m_rect.Height()));
int16_t top = (m_rect.top + m_rect.bottom - static_cast<int16_t>(radioFrameSize)) / 2;
surface->SetForeColor(StdColors::Black());
const Rect radioRect = Rect::Create(top, m_rect.left, top + static_cast<int16_t>(radioFrameSize), m_rect.left + static_cast<int16_t>(radioFrameSize));
surface->FillEllipse(radioRect);
if (!m_state)
{
surface->SetForeColor(StdColors::White());
surface->FillEllipse(radioRect.Inset(1, 1));
}
surface->SetForeColor(StdColors::Black());
surface->SetSystemFont(12, FontFamilyFlag_Bold);
int32_t textV = (m_rect.top + m_rect.bottom + surface->MeasureFontAscender()) / 2;
surface->DrawString(Point::Create(m_rect.left + radioFrameSize + 2, textV), m_text.ToShortStr());
}
void RadioButtonWidget::SetString(const PLPasStr &str)
{
m_text = PascalStr<255>(str);
}
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "PascalStr.h"
#include "PLWidgets.h"
namespace PortabilityLayer
{
class RadioButtonWidget final : public WidgetSpec<RadioButtonWidget>
{
public:
RadioButtonWidget(const WidgetBasicState &state);
~RadioButtonWidget();
bool Init(const WidgetBasicState &state) override;
void DrawControl(DrawSurface *surface) override;
void SetString(const PLPasStr &str) override;
private:
PascalStr<255> m_text;
};
}

View File

@@ -0,0 +1,14 @@
#include "PLScrollBarWidget.h"
namespace PortabilityLayer
{
ScrollBarWidget::ScrollBarWidget(const WidgetBasicState &state)
: WidgetSpec<ScrollBarWidget>(state)
{
}
bool ScrollBarWidget::Init(const WidgetBasicState &state)
{
return true;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "PascalStr.h"
#include "PLWidgets.h"
namespace PortabilityLayer
{
class ScrollBarWidget final : public WidgetSpec<ScrollBarWidget>
{
public:
explicit ScrollBarWidget(const WidgetBasicState &state);
bool Init(const WidgetBasicState &state) override;
};
}

View File

@@ -329,7 +329,11 @@ namespace PortabilityLayer
static SoundSystemImpl *GetInstance();
private:
SoundSystemImpl();
static SoundSystemImpl ms_instance;
uint8_t m_volume;
};
AudioChannel *SoundSystemImpl::CreateChannel()
@@ -367,16 +371,16 @@ namespace PortabilityLayer
return new (storage) PortabilityLayer::AudioChannelImpl(audioChannel, threadEvent, mutex);
}
void SoundSystemImpl::SetVolume(uint8_t vol)
{
PL_NotYetImplemented_TODO("Volume");
PortabilityLayer::HostAudioDriver::GetInstance()->SetMasterVolume(vol, 255);
m_volume = vol;
}
uint8_t SoundSystemImpl::GetVolume() const
{
PL_NotYetImplemented_TODO("Volume");
return 255;
return m_volume;
}
SoundSystemImpl *SoundSystemImpl::GetInstance()
@@ -384,6 +388,11 @@ namespace PortabilityLayer
return &ms_instance;
}
SoundSystemImpl::SoundSystemImpl()
: m_volume(255)
{
}
SoundSystemImpl SoundSystemImpl::ms_instance;
SoundSystem *SoundSystem::GetInstance()

View File

@@ -6,8 +6,12 @@ namespace PortabilityLayer
WidgetBasicState::WidgetBasicState()
: m_resID(0)
, m_rect(Rect::Create(0, 0, 0, 0))
, m_enabled(true)
, m_window(nullptr)
, m_refConstant(0)
, m_min(0)
, m_max(0)
, m_state(0)
, m_enabled(true)
{
}
@@ -23,6 +27,31 @@ namespace PortabilityLayer
(void)surface;
}
void Widget::SetMin(int32_t v)
{
}
void Widget::SetMax(int32_t v)
{
}
void Widget::SetPosition(const Point &pos)
{
uint16_t width = m_rect.Width();
uint16_t height = m_rect.Height();
m_rect.left = pos.h;
m_rect.top = pos.v;
Resize(width, height);
}
void Widget::Resize(uint16_t width, uint16_t height)
{
m_rect.right = m_rect.left + width;
m_rect.bottom = m_rect.top + height;
}
void Widget::SetEnabled(bool enabled)
{
m_enabled = enabled;
@@ -35,6 +64,11 @@ namespace PortabilityLayer
OnStateChanged();
}
int16_t Widget::GetState() const
{
return m_state;
}
void Widget::SetVisible(bool visible)
{
m_visible = visible;
@@ -64,8 +98,8 @@ namespace PortabilityLayer
: m_rect(state.m_rect)
, m_window(state.m_window)
, m_enabled(state.m_enabled)
, m_state(state.m_state)
, m_visible(true)
, m_state(0)
{
}

View File

@@ -28,10 +28,14 @@ namespace PortabilityLayer
WidgetBasicState();
Rect m_rect;
int16_t m_resID;
PascalStr<255> m_text;
bool m_enabled;
Window *m_window;
uint32_t m_refConstant;
int32_t m_min;
int32_t m_max;
int16_t m_state;
int16_t m_resID;
bool m_enabled;
};
class Widget
@@ -42,8 +46,15 @@ namespace PortabilityLayer
virtual WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt);
virtual void DrawControl(DrawSurface *surface);
virtual void SetMin(int32_t v);
virtual void SetMax(int32_t v);
void SetPosition(const Point &pos);
void Resize(uint16_t width, uint16_t height);
void SetEnabled(bool enabled);
void SetState(int16_t state);
int16_t GetState() const;
void SetVisible(bool visible);
bool IsVisible() const;
@@ -71,6 +82,7 @@ namespace PortabilityLayer
};
}
#include "PLCore.h"
#include <new>
#include <stdint.h>
@@ -91,7 +103,7 @@ namespace PortabilityLayer
Widget::BaseRelease(static_cast<T*>(this));
}
static WidgetSpec<T> *Create(const WidgetBasicState &state)
static T *Create(const WidgetBasicState &state)
{
void *storage = Widget::BaseAlloc(sizeof(T));
if (!storage)
@@ -99,13 +111,23 @@ namespace PortabilityLayer
T *widgetT = new (storage) T(state);
Widget *widget = static_cast<Widget*>(widgetT);
// Conversion check
WidgetSpec<T> *downcastWidget = widgetT;
(void)downcastWidget;
Widget *widget = widgetT;
if (!widget->Init(state))
{
widget->Destroy();
return nullptr;
}
if (!static_cast<Window*>(state.m_window)->AddWidget(widget))
{
widget->Destroy();
return nullptr;
}
return widgetT;
}
};

View File

@@ -191,6 +191,7 @@
<ClInclude Include="PLArrayViewIterator.h" />
<ClInclude Include="PLBigEndian.h" />
<ClInclude Include="PLButtonWidget.h" />
<ClInclude Include="PLCheckboxWidget.h" />
<ClInclude Include="PLControlDefinitions.h" />
<ClInclude Include="PLCore.h" />
<ClInclude Include="PLCTabReducer.h" />
@@ -203,6 +204,9 @@
<ClInclude Include="PLImageWidget.h" />
<ClInclude Include="PLInvisibleWidget.h" />
<ClInclude Include="PLLabelWidget.h" />
<ClInclude Include="PLPopupMenuWidget.h" />
<ClInclude Include="PLRadioButtonWidget.h" />
<ClInclude Include="PLScrollBarWidget.h" />
<ClInclude Include="PLWidgets.h" />
<ClInclude Include="SimpleImage.h" />
<ClInclude Include="PLKeyEncoding.h" />
@@ -304,6 +308,7 @@
<ClCompile Include="PLAppleEvents.cpp" />
<ClCompile Include="PLApplication.cpp" />
<ClCompile Include="PLButtonWidget.cpp" />
<ClCompile Include="PLCheckboxWidget.cpp" />
<ClCompile Include="PLControlDefinitions.cpp" />
<ClCompile Include="PLCore.cpp" />
<ClCompile Include="PLCTabReducer.cpp" />
@@ -318,10 +323,13 @@
<ClCompile Include="PLMovies.cpp" />
<ClCompile Include="PLNavigation.cpp" />
<ClCompile Include="PLNumberFormatting.cpp" />
<ClCompile Include="PLPopupMenuWidget.cpp" />
<ClCompile Include="PLQDOffscreen.cpp" />
<ClCompile Include="PLQDraw.cpp" />
<ClCompile Include="PLRadioButtonWidget.cpp" />
<ClCompile Include="PLResourceManager.cpp" />
<ClCompile Include="PLResources.cpp" />
<ClCompile Include="PLScrollBarWidget.cpp" />
<ClCompile Include="PLSound.cpp" />
<ClCompile Include="PLStandardColors.cpp" />
<ClCompile Include="PLStringCompare.cpp" />

View File

@@ -438,6 +438,18 @@
<ClInclude Include="PLImageWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PLScrollBarWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PLPopupMenuWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PLCheckboxWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PLRadioButtonWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CFileStream.cpp">
@@ -677,5 +689,17 @@
<ClCompile Include="PLImageWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PLScrollBarWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PLPopupMenuWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PLCheckboxWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PLRadioButtonWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -77,9 +77,11 @@ struct DrawSurface final
void SetApplicationFont(int size, int variationFlags);
void SetSystemFont(int size, int variationFlags);
void DrawString(const Point &point, const PLPasStr &str);
void DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str);
size_t MeasureString(const PLPasStr &str);
int32_t MeasureFontAscender();
int32_t MeasureFontLineGap();
void DrawPicture(THandle<Picture> pictHandle, const Rect &rect);

View File

@@ -27,11 +27,17 @@ struct Rect
int16_t right;
bool IsValid() const;
Rect Intersect(const Rect &rect) const;
Rect MakeValid() const;
Rect Intersect(const Rect &rect) const;
Rect Inset(int16_t h, int16_t v) const;
Rect operator-(const Point &point) const;
Rect operator+(const Point &point) const;
Rect &operator-=(const Point &point);
Rect &operator+=(const Point &point);
uint16_t Height() const;
uint16_t Width() const;
@@ -164,6 +170,11 @@ inline Rect Rect::Intersect(const Rect &other) const
return result;
}
inline Rect Rect::Inset(int16_t h, int16_t v) const
{
return Rect::Create(top + v, left + h, bottom - v, right - h);
}
inline Rect Rect::MakeValid() const
{
Rect result = *this;
@@ -186,6 +197,28 @@ inline Rect Rect::operator+(const Point &point) const
return Rect::Create(this->top + point.v, this->left + point.h, this->bottom + point.v, this->right + point.h);
}
inline Rect &Rect::operator-=(const Point &point)
{
this->top -= point.v;
this->bottom -= point.v;
this->left -= point.h;
this->right -= point.h;
return *this;
}
inline Rect &Rect::operator+=(const Point &point)
{
this->top += point.v;
this->bottom += point.v;
this->left += point.h;
this->right += point.h;
return *this;
}
inline uint16_t Rect::Height() const
{
return static_cast<uint16_t>(static_cast<int32_t>(this->bottom) - static_cast<int32_t>(this->top));

View File

@@ -11,6 +11,7 @@ namespace PortabilityLayer
kApplicationData = 1,
kGameData,
kUserData,
kUserSaves,
kPrefs,
kFonts,
kCursors,

View File

@@ -344,6 +344,9 @@ namespace PortabilityLayer
void WindowManagerImpl::RenderWindow(WindowImpl *window, IGpDisplayDriver *displayDriver)
{
if (!window->IsVisible())
return;
DrawSurface &graf = window->m_surface;
graf.PushToDDSurface(displayDriver);