Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,344 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "graphics/screen.h"
#include "xyzzy/events.h"
#include "xyzzy/xyzzy.h"
#include "xyzzy/views.h"
namespace Xyzzy {
Events *g_events;
Events::Events() : UIElement("Root", nullptr) {
g_events = this;
}
Events::~Events() {
g_events = nullptr;
}
void Events::runGame() {
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
Views views; // Loads all views in the structure
// Run the game
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot != -1)
g_engine->loadGameState(saveSlot);
addView("View1");
Common::Event e;
while (!_views.empty() && !shouldQuit()) {
while (g_system->getEventManager()->pollEvent(e)) {
if (e.type == Common::EVENT_QUIT ||
e.type == Common::EVENT_RETURN_TO_LAUNCHER) {
_views.clear();
break;
} else {
processEvent(e);
}
}
if (_views.empty())
break;
g_system->delayMillis(10);
if ((currTime = g_system->getMillis()) >= nextFrameTime) {
nextFrameTime = currTime + FRAME_DELAY;
tick();
drawElements();
_screen->update();
}
}
delete _screen;
}
void Events::processEvent(Common::Event &ev) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
if (ev.kbd.keycode < Common::KEYCODE_NUMLOCK)
msgKeypress(KeypressMessage(ev.kbd));
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
msgAction(ActionMessage(ev.customType));
break;
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_MBUTTONDOWN:
msgMouseDown(MouseDownMessage(ev.type, ev.mouse));
break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
case Common::EVENT_MBUTTONUP:
msgMouseUp(MouseUpMessage(ev.type, ev.mouse));
break;
case Common::EVENT_MOUSEMOVE:
msgMouseMove(MouseMoveMessage(ev.type, ev.mouse));
break;
default:
break;
}
}
void Events::replaceView(UIElement *ui, bool replaceAllViews) {
assert(ui);
UIElement *priorView = focusedView();
if (replaceAllViews) {
clearViews();
} else if (!_views.empty()) {
priorView->msgUnfocus(UnfocusMessage());
_views.pop();
}
_views.push(ui);
ui->redraw();
ui->msgFocus(FocusMessage(priorView));
}
void Events::replaceView(const Common::String &name, bool replaceAllViews) {
replaceView(findView(name));
}
void Events::addView(UIElement *ui) {
assert(ui);
UIElement *priorView = focusedView();
if (!_views.empty())
priorView->msgUnfocus(UnfocusMessage());
_views.push(ui);
ui->redraw();
ui->msgFocus(FocusMessage(priorView));
}
void Events::addView(const Common::String &name) {
addView(findView(name));
}
void Events::popView() {
UIElement *priorView = focusedView();
priorView->msgUnfocus(UnfocusMessage());
_views.pop();
for (int i = 0; i < (int)_views.size() - 1; ++i) {
_views[i]->redraw();
_views[i]->draw();
}
if (!_views.empty()) {
UIElement *view = focusedView();
view->msgFocus(FocusMessage(priorView));
view->redraw();
view->draw();
}
}
void Events::redrawViews() {
for (uint i = 0; i < _views.size(); ++i) {
_views[i]->redraw();
_views[i]->draw();
}
}
bool Events::isPresent(const Common::String &name) const {
for (uint i = 0; i < _views.size(); ++i) {
if (_views[i]->_name == name)
return true;
}
return false;
}
void Events::clearViews() {
if (!_views.empty())
focusedView()->msgUnfocus(UnfocusMessage());
_views.clear();
}
void Events::addKeypress(const Common::KeyCode kc) {
Common::KeyState ks;
ks.keycode = kc;
if (kc >= Common::KEYCODE_SPACE && kc <= Common::KEYCODE_TILDE)
ks.ascii = kc;
focusedView()->msgKeypress(KeypressMessage(ks));
}
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) :
_bounds(0, 0, 320, 200),
_innerBounds(innerBounds),
left(_bounds.left), top(_bounds.top),
right(_bounds.right), bottom(_bounds.bottom) {
}
Bounds &Bounds::operator=(const Common::Rect &r) {
_bounds = r;
_innerBounds = r;
_innerBounds.grow(-_borderSize);
return *this;
}
void Bounds::setBorderSize(size_t borderSize) {
_borderSize = borderSize;
_innerBounds = *this;
_innerBounds.grow(-_borderSize);
}
/*------------------------------------------------------------------------*/
UIElement::UIElement(const Common::String &name) :
_name(name), _parent(g_engine), _bounds(_innerBounds) {
g_engine->_children.push_back(this);
}
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
_name(name), _parent(uiParent),
_bounds(_innerBounds) {
if (_parent)
_parent->_children.push_back(this);
}
void UIElement::redraw() {
_needsRedraw = true;
for (size_t i = 0; i < _children.size(); ++i)
_children[i]->redraw();
}
void UIElement::drawElements() {
if (_needsRedraw) {
draw();
_needsRedraw = false;
}
for (size_t i = 0; i < _children.size(); ++i)
_children[i]->drawElements();
}
UIElement *UIElement::findViewGlobally(const Common::String &name) {
return g_events->findView(name);
}
void UIElement::focus() {
g_events->replaceView(this);
}
void UIElement::close() {
assert(g_events->focusedView() == this);
g_events->popView();
}
bool UIElement::isFocused() const {
return g_events->focusedView() == this;
}
void UIElement::clearSurface() {
Graphics::ManagedSurface s = getSurface();
s.fillRect(Common::Rect(s.w, s.h), 0);
}
void UIElement::draw() {
for (size_t i = 0; i < _children.size(); ++i) {
_children[i]->draw();
}
}
bool UIElement::tick() {
if (_timeoutCtr && --_timeoutCtr == 0) {
timeout();
}
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
return true;
}
return false;
}
UIElement *UIElement::findView(const Common::String &name) {
if (_name.equalsIgnoreCase(name))
return this;
UIElement *result;
for (size_t i = 0; i < _children.size(); ++i) {
if ((result = _children[i]->findView(name)) != nullptr)
return result;
}
return nullptr;
}
void UIElement::replaceView(UIElement *ui, bool replaceAllViews) {
g_events->replaceView(ui, replaceAllViews);
}
void UIElement::replaceView(const Common::String &name, bool replaceAllViews) {
g_events->replaceView(name, replaceAllViews);
}
void UIElement::addView(UIElement *ui) {
g_events->addView(ui);
}
void UIElement::addView(const Common::String &name) {
g_events->addView(name);
}
void UIElement::addView() {
g_events->addView(this);
}
Graphics::ManagedSurface UIElement::getSurface() const {
return Graphics::ManagedSurface(*g_events->getScreen(), _bounds);
}
int UIElement::getRandomNumber(int minNumber, int maxNumber) {
return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
}
int UIElement::getRandomNumber(int maxNumber) {
return g_engine->getRandomNumber(maxNumber);
}
void UIElement::delaySeconds(uint seconds) {
_timeoutCtr = seconds * FRAME_RATE;
}
void UIElement::delayFrames(uint frames) {
_timeoutCtr = frames;
}
void UIElement::timeout() {
redraw();
}
} // namespace Xyzzy

View File

@@ -0,0 +1,397 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_EVENTS_H
#define XYZZY_EVENTS_H
#include "common/array.h"
#include "common/stack.h"
#include "graphics/screen.h"
#include "xyzzy/messages.h"
namespace Xyzzy {
#define FRAME_RATE 20
#define FRAME_DELAY (1000 / FRAME_RATE)
class Events;
/**
* Implements a thunk layer around an element's bounds,
* allowing access to it as if it were a simple Common::Rect,
* but any changes to it will also be applied to a linked inner bounds
*/
struct Bounds {
private:
Common::Rect _bounds;
Common::Rect &_innerBounds;
int _borderSize = 0;
public:
const int16 &left;
const int16 &top;
const int16 &right;
const int16 &bottom;
public:
Bounds(Common::Rect &innerBounds);
operator const Common::Rect &() const { return _bounds; }
Bounds &operator=(const Common::Rect &r);
void setBorderSize(size_t borderSize);
size_t borderSize() const { return _borderSize; }
int16 width() const { return _bounds.width(); }
int16 height() const { return _bounds.height(); }
};
/**
* User interface element
*/
class UIElement {
friend class Events;
private:
int _timeoutCtr = 0;
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
Common::Rect _innerBounds;
Bounds _bounds;
bool _needsRedraw = true;
Common::String _name;
protected:
/**
* Set a delay countdown in seconds, after which timeout() is called
*/
void delaySeconds(uint seconds);
/**
* Set a delay countdown in frames, after which timeout() is called
*/
void delayFrames(uint frames);
/**
* Returns true if a delay is active
*/
bool isDelayActive() const {
return _timeoutCtr != 0;
}
/**
* Cancels any active delay
*/
void cancelDelay() {
_timeoutCtr = 0;
}
/**
* Called when an active timeout countdown expired
*/
virtual void timeout();
private:
/**
* Outer method for doing drawing
*
*/
void drawElements();
/**
* Finds a view globally
*/
static UIElement *findViewGlobally(const Common::String &name);
public:
UIElement(const Common::String &name, UIElement *uiParent);
UIElement(const Common::String &name);
virtual ~UIElement() {}
/**
* Returns true if the elements needs to be redrawn
*/
bool needsRedraw() const { return _needsRedraw; }
/**
* Sets that the element needs to be redrawn
*/
void redraw();
/**
* Focuses the element as the current view
*/
void focus();
/**
* Closes the current view. The view must have been added
* via addView, so there's a remaining view afterwards
*/
virtual void close();
/*
* Returns true if the view is focused
*/
bool isFocused() const;
/**
* Sets the focus to a new view
*/
void replaceView(UIElement *ui, bool replaceAllViews = false);
void replaceView(const Common::String &name, bool replaceAllViews = false);
/**
* Adds a focused view to the view stack without replacing current one
*/
void addView(UIElement *ui);
void addView(const Common::String &name);
void addView();
void open() { addView(); }
/**
* Returns a random number
*/
int getRandomNumber(int minNumber, int maxNumber);
int getRandomNumber(int maxNumber);
/**
* Sets the element's bounds
*/
virtual void setBounds(const Common::Rect &r) {
_bounds = r;
}
/**
* Gets the element's bounds
*/
Common::Rect getBounds() const {
return _bounds;
}
/**
* Returns a surface for drawing the element
*/
Graphics::ManagedSurface getSurface() const;
/**
* Clear the surface
*/
virtual void clearSurface();
/**
* Draws the element
*/
virtual void draw();
/**
* Called for game frame ticks
*/
virtual bool tick();
/**
* Find a view by name
*/
virtual UIElement *findView(const Common::String &name);
/**
* Handles events
*/
// Mouse move only has a minimal implementation for performance reasons
protected:
virtual bool msgMouseMove(const MouseMoveMessage &msg) { return false; }
public:
bool send(const MouseMoveMessage &msg) { return msgMouseMove(msg); }
#define MESSAGE(NAME) \
protected: \
virtual bool msg##NAME(const NAME##Message &e) { \
for (Common::Array<UIElement *>::iterator it = _children.begin(); \
it != _children.end(); ++it) { \
if ((*it)->msg##NAME(e)) return true; \
} \
return false; \
} \
public: \
bool send(const Common::String &viewName, const NAME##Message &msg) { \
UIElement *view = UIElement::findViewGlobally(viewName); \
assert(view); \
return view->msg##NAME(msg); \
} \
bool send(const NAME##Message &msg) { \
return msg##NAME(msg); \
} \
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(MouseEnter);
MESSAGE(MouseLeave);
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
MESSAGE(Action);
MESSAGE(Game);
MESSAGE(Value);
#undef MESSAGE
};
/**
* Main events and view manager. This is kept separate from the engine
* class because the engine may add a lot of globals and bring in other
* classes. So to save on compilation time, classes that only need to
* access basic view management methods like addView or replaceView
* only need to include events.h rather than the whole engine.
*/
class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
Common::Stack<UIElement *> _views;
protected:
/**
* Process an event
*/
void processEvent(Common::Event &ev);
/**
* Returns true if the game should quit
*/
virtual bool shouldQuit() const = 0;
/**
* Overrides events we want to only go to the focused view
*/
#define MESSAGE(NAME) \
bool msg##NAME(const NAME##Message &e) override { \
return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
}
MESSAGE(Action);
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(MouseEnter);
MESSAGE(MouseLeave);
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
MESSAGE(MouseMove);
#undef MESSAGE
public:
Events();
virtual ~Events();
/**
* Main game loop
*/
void runGame();
/**
* Sets the focus to a new view
*/
void replaceView(UIElement *ui, bool replaceAllViews = false);
void replaceView(const Common::String &name, bool replaceAllViews = false);
/**
* Adds a focused view to the view stack without replacing current one
*/
void addView(UIElement *ui);
void addView(const Common::String &name);
/**
* Clears the view list
*/
void clearViews();
/**
* Pops a view from the view stack
*/
void popView();
/**
* Redraws the views in order. This is used in rare cases
* where a view draws outside it's defined area, and needs
* to restore whether the background was before
*/
void redrawViews();
/**
* Returns the currently focused view, if any
*/
UIElement *focusedView() const {
return _views.empty() ? nullptr : _views.top();
}
/**
* Returns the view prior to the current view, if any
*/
UIElement *priorView() const {
return _views.size() < 2 ? nullptr :
_views[_views.size() - 2];
}
/**
* Returns true if a view of a given name is present
* at all in the visible view stack
*/
bool isPresent(const Common::String &name) const;
/**
* Returns true if combat is active
*/
bool isInCombat() const {
return isPresent("Combat");
}
/**
* Returns the underlying screen
*/
Graphics::Screen *getScreen() const {
return _screen;
}
/**
* Draws the focused view
*/
void drawElements() {
if (!_views.empty())
focusedView()->drawElements();
}
/**
* Add a keypress to the event queue
*/
void addKeypress(const Common::KeyCode kc);
/**
* Events manager doesn't have any intrinsic drawing
*/
void draw() override {}
/**
* Called once every game frame
*/
bool tick() override {
return !_views.empty() ? focusedView()->tick() : false;
}
/**
* Calling the close method for g_events closes the active view
*/
void close() override {
focusedView()->close();
}
};
extern Events *g_events;
} // namespace Xyzzy
#endif

View File

@@ -0,0 +1,43 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "xyzzy/messages.h"
namespace Xyzzy {
MouseMessage::MouseMessage(Common::EventType type,
const Common::Point &pos) : Message(), _pos(pos) {
switch (type) {
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_RBUTTONUP:
_button = MB_RIGHT;
break;
case Common::EVENT_MBUTTONDOWN:
case Common::EVENT_MBUTTONUP:
_button = MB_MIDDLE;
break;
default:
_button = MB_LEFT;
break;
}
}
} // namespace Xyzzy

View File

@@ -0,0 +1,111 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_MESSAGES_H
#define XYZZY_MESSAGES_H
#include "common/array.h"
#include "common/events.h"
#include "common/str.h"
namespace Xyzzy {
class UIElement;
struct Message {};
struct FocusMessage : public Message {
UIElement *_priorView = nullptr;
FocusMessage() : Message() {}
FocusMessage(UIElement *priorView) : Message(),
_priorView(priorView) {}
};
struct UnfocusMessage : public Message {};
struct MouseEnterMessage : public Message {};
struct MouseLeaveMessage : public Message {};
struct KeypressMessage : public Message, public Common::KeyState {
KeypressMessage() : Message() {}
KeypressMessage(const Common::KeyState &ks) :
Message(), Common::KeyState(ks) {}
};
struct MouseMessage : public Message {
enum Button { MB_LEFT, MB_RIGHT, MB_MIDDLE };
Button _button;
Common::Point _pos;
MouseMessage() : Message(), _button(MB_LEFT) {}
MouseMessage(Button btn, const Common::Point &pos) :
Message(), _button(btn), _pos(pos) {}
MouseMessage(Common::EventType type, const Common::Point &pos);
};
struct MouseDownMessage : public MouseMessage {
MouseDownMessage() : MouseMessage() {}
MouseDownMessage(Button btn, const Common::Point &pos) :
MouseMessage(btn, pos) {}
MouseDownMessage(Common::EventType type, const Common::Point &pos) :
MouseMessage(type, pos) {}
};
struct MouseUpMessage : public MouseMessage {
MouseUpMessage() : MouseMessage() {}
MouseUpMessage(Button btn, const Common::Point &pos) :
MouseMessage(btn, pos) {}
MouseUpMessage(Common::EventType type, const Common::Point &pos) :
MouseMessage(type, pos) {}
};
typedef MouseMessage MouseMoveMessage;
struct GameMessage : public Message {
Common::String _name;
int _value;
Common::String _stringValue;
GameMessage() : Message(), _value(-1) {}
GameMessage(const Common::String &name) : Message(),
_name(name), _value(-1) {}
GameMessage(const Common::String &name, int value) : Message(),
_name(name), _value(value) {}
GameMessage(const Common::String &name, const Common::String &value) :
Message(), _name(name), _stringValue(value) {}
};
struct ValueMessage : public Message {
int _value;
ValueMessage() : Message(), _value(0) {}
ValueMessage(int value) : Message(),
_value(value) {}
};
struct ActionMessage : public Message {
int _action;
ActionMessage() : Message(), _action(0) {
}
ActionMessage(int action) : Message(),
_action(action) {
}
};
} // namespace Xyzzy
#endif

View File

@@ -0,0 +1,21 @@
MODULE := engines/xyzzy
MODULE_OBJS = \
xyzzy.o \
console.o \
events.o \
messages.o \
metaengine.o \
view.o \
view1.o
# This module can be built as a plugin
ifeq ($(ENABLE_XYZZY), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

View File

@@ -0,0 +1,81 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "xyzzy/view.h"
namespace Xyzzy {
void View::checkFocusedControl(const Common::Point &mousePos) {
if (_focusedElement) {
if (!_focusedElement->getBounds().contains(mousePos)) {
_focusedElement->send(MouseLeaveMessage());
_focusedElement = nullptr;
}
} else {
for (UIElement *child : _children) {
if (child->getBounds().contains(mousePos)) {
_focusedElement = child;
child->send(MouseEnterMessage());
break;
}
}
}
}
UIElement *View::getElementAtPos(const Common::Point &pos) const {
for (UIElement *child : _children) {
if (child->getBounds().contains(pos))
return child;
}
return nullptr;
}
bool View::msgFocus(const FocusMessage &msg) {
_focusedElement = nullptr;
return UIElement::msgFocus(msg);
}
bool View::msgUnfocus(const UnfocusMessage &msg) {
if (_focusedElement)
_focusedElement->send(MouseLeaveMessage());
return UIElement::msgUnfocus(msg);
}
bool View::msgMouseMove(const MouseMoveMessage &msg) {
checkFocusedControl(msg._pos);
return true;
}
bool View::msgMouseDown(const MouseDownMessage &msg) {
UIElement *child = getElementAtPos(msg._pos);
return child ? child->send(msg) : false;
}
bool View::msgMouseUp(const MouseUpMessage &msg) {
UIElement *child = getElementAtPos(msg._pos);
return child ? child->send(msg) : false;
}
} // namespace Xyzzy

View File

@@ -0,0 +1,73 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_VIEW_H
#define XYZZY_VIEW_H
#include "xyzzy/events.h"
namespace Xyzzy {
/**
* Base view class for screens and dialogs that appear on-screen.
* The View class takes care of two important things:
* 1) By default events get sent to all controls on a view until one
* handles it. For mouse events, we instead want only the control the
* mouse cursor is over to receive the events, saving the individual
* controls from having to check if the mouse is within their bounds.
* 2) Individual elements will get a Focus/Unfocus message as the
* mouse enters and leaves them. This allows, for example, buttons
* that have been pressed to de-select if the mouse leaves their bounds.
*/
class View : public UIElement {
private:
UIElement *_focusedElement = nullptr;
/**
* Checks if a control is entered or left
*/
void checkFocusedControl(const Common::Point &mousePos);
/**
* Check for an element at the given position
*/
UIElement *getElementAtPos(const Common::Point &pos) const;
public:
View(const Common::String &name, UIElement *uiParent) :
UIElement(name, uiParent) {
}
View(const Common::String &name) :
UIElement(name) {
}
virtual ~View() {
}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
bool msgMouseMove(const MouseMoveMessage &msg) override;
bool msgMouseDown(const MouseDownMessage &msg) override;
bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace Xyzzy
#endif

View File

@@ -0,0 +1,64 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/system.h"
#include "graphics/paletteman.h"
#include "xyzzy/view1.h"
namespace Xyzzy {
bool View1::msgFocus(const FocusMessage &msg) {
Common::fill(&_pal[0], &_pal[256 * 3], 0);
_offset = 128;
return true;
}
bool View1::msgKeypress(const KeypressMessage &msg) {
// Any keypress to close the view
close();
return true;
}
void View1::draw() {
// Draw a bunch of squares on screen
Graphics::ManagedSurface s = getSurface();
for (int i = 0; i < 100; ++i)
s.frameRect(Common::Rect(i, i, 320 - i, 200 - i), i);
}
bool View1::tick() {
// Cycle the palette
++_offset;
for (int i = 0; i < 256; ++i)
_pal[i * 3 + 1] = (i + _offset) % 256;
g_system->getPaletteManager()->setPalette(_pal, 0, 256);
// Below is redundant since we're only cycling the palette, but it demonstrates
// how to trigger the view to do further draws after the first time, since views
// don't automatically keep redrawing unless you tell it to
if ((_offset % 256) == 0)
redraw();
return true;
}
} // namespace Xyzzy

View File

@@ -0,0 +1,46 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_VIEW1_H
#define XYZZY_VIEW1_H
#include "xyzzy/view.h"
namespace Xyzzy {
class View1 : public View {
private:
byte _pal[256 * 3] = { 0 };
int _offset = 0;
public:
View1() : View("View1") {}
virtual ~View1() {}
bool msgFocus(const FocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
bool tick() override;
};
} // namespace Xyzzy
#endif

View File

@@ -0,0 +1,35 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_VIEWS_H
#define XYZZY_VIEWS_H
#include "xyzzy/view1.h"
namespace Xyzzy {
struct Views {
View1 _view1;
};
} // namespace Xyzzy
#endif

View File

@@ -0,0 +1,76 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "xyzzy/xyzzy.h"
#include "xyzzy/detection.h"
#include "xyzzy/console.h"
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/system.h"
#include "engines/util.h"
#include "graphics/paletteman.h"
namespace Xyzzy {
XyzzyEngine *g_engine;
XyzzyEngine::XyzzyEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Xyzzy") {
g_engine = this;
}
XyzzyEngine::~XyzzyEngine() {
}
uint32 XyzzyEngine::getFeatures() const {
return _gameDescription->flags;
}
Common::String XyzzyEngine::getGameId() const {
return _gameDescription->gameId;
}
Common::Error XyzzyEngine::run() {
// Initialize 320x200 paletted graphics mode
initGraphics(320, 200);
// Set the engine's debugger console
setDebugger(new Console());
runGame();
return Common::kNoError;
}
Common::Error XyzzyEngine::syncGame(Common::Serializer &s) {
// The Serializer has methods isLoading() and isSaving()
// if you need to specific steps; for example setting
// an array size after reading it's length, whereas
// for saving it would write the existing array's length
int dummy = 0;
s.syncAsUint32LE(dummy);
return Common::kNoError;
}
} // End of namespace Xyzzy

View File

@@ -0,0 +1,112 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef XYZZY_H
#define XYZZY_H
#include "common/scummsys.h"
#include "common/system.h"
#include "common/error.h"
#include "common/fs.h"
#include "common/hash-str.h"
#include "common/random.h"
#include "common/serializer.h"
#include "common/util.h"
#include "engines/engine.h"
#include "engines/savestate.h"
#include "graphics/screen.h"
#include "xyzzy/detection.h"
#include "xyzzy/events.h"
namespace Xyzzy {
struct XyzzyGameDescription;
class XyzzyEngine : public Engine, public Events {
private:
const ADGameDescription *_gameDescription;
Common::RandomSource _randomSource;
protected:
// Engine APIs
Common::Error run() override;
/**
* Returns true if the game should quit
*/
bool shouldQuit() const override {
return Engine::shouldQuit();
}
public:
XyzzyEngine(OSystem *syst, const ADGameDescription *gameDesc);
~XyzzyEngine() override;
uint32 getFeatures() const;
/**
* Returns the game Id
*/
Common::String getGameId() const;
/**
* Gets a random number
*/
uint32 getRandomNumber(uint maxNum) {
return _randomSource.getRandomNumber(maxNum);
}
bool hasFeature(EngineFeature f) const override {
return
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime) ||
(f == kSupportsReturnToLauncher);
};
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
return true;
}
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
return true;
}
/**
* Uses a serializer to allow implementing savegame
* loading and saving using a single method
*/
Common::Error syncGame(Common::Serializer &s);
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override {
Common::Serializer s(nullptr, stream);
return syncGame(s);
}
Common::Error loadGameStream(Common::SeekableReadStream *stream) override {
Common::Serializer s(stream, nullptr);
return syncGame(s);
}
};
extern XyzzyEngine *g_engine;
#define SHOULD_QUIT ::Xyzzy::g_engine->shouldQuit()
} // End of namespace Xyzzy
#endif // XYZZY_H