[Scummvm-git-logs] scummvm master -> f1d9722f3bd58f7883f3e76c19d4a0133da73489

dreammaster paulfgilbert at gmail.com
Thu Jan 3 03:22:39 CET 2019


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f1d9722f3b GLK: FROTZ: Add support for pair windows to have more than 2 children


Commit: f1d9722f3bd58f7883f3e76c19d4a0133da73489
    https://github.com/scummvm/scummvm/commit/f1d9722f3bd58f7883f3e76c19d4a0133da73489
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-01-02T18:18:11-08:00

Commit Message:
GLK: FROTZ: Add support for pair windows to have more than 2 children

This is primarily for the V6 games, which have up to 8 windows
on-screen at the same time in arbitray positions
ext

Changed paths:
    engines/glk/frotz/windows.cpp
    engines/glk/frotz/windows.h
    engines/glk/glk_api.cpp
    engines/glk/glk_types.h
    engines/glk/utils.h
    engines/glk/window_pair.cpp
    engines/glk/window_pair.h
    engines/glk/windows.cpp


diff --git a/engines/glk/frotz/windows.cpp b/engines/glk/frotz/windows.cpp
index 1863e68..ffee639 100644
--- a/engines/glk/frotz/windows.cpp
+++ b/engines/glk/frotz/windows.cpp
@@ -22,6 +22,7 @@
 
 #include "glk/frotz/windows.h"
 #include "glk/frotz/frotz.h"
+#include "glk/window_pair.h"
 
 namespace Glk {
 namespace Frotz {
@@ -51,7 +52,8 @@ winid_t Window::getWindow() {
 		// TODO: For now I'm assuming all the extra created windows will be graphics, since Glk requires
 		// us to specify it at creation time. Not sure if it's true or not for all V6 games
 		winid_t parent = _windows->_lower;
-		_win = g_vm->glk_window_open(parent, winmethod_OnTop | winmethod_Fixed, 0, wintype_Graphics, 0);
+		_win = g_vm->glk_window_open(g_vm->glk_window_get_root(), winmethod_Arbitrary | winmethod_Fixed,
+			0, wintype_Graphics, 0);
 	}
 
 	return _win;
@@ -59,6 +61,7 @@ winid_t Window::getWindow() {
 
 void Window::setSize(const Point &newSize) {
 	winid_t win = getWindow();
+	checkRepositionLower();
 
 	win->setSize(newSize);
 /* TODO
@@ -73,6 +76,7 @@ void Window::setSize(const Point &newSize) {
 
 void Window::setPosition(const Point &newPos) {
 	winid_t win = getWindow();
+	checkRepositionLower();
 
 	win->setPosition(newPos);
 }
@@ -113,5 +117,17 @@ void Window::setProperty(WindowProperty propType, uint16 value) {
 	// TODO
 }
 
+void Window::checkRepositionLower() {
+	if (&_windows->_lower == this) {
+		PairWindow *parent = dynamic_cast<PairWindow *>(_win->_parent);
+		if (!parent)
+			error("Parent was not a pair window");
+
+		// Ensure the parent pair window is flagged as having children at arbitrary positions,
+		// just in case it isn't already
+		parent->_dir = winmethod_Arbitrary;
+	}
+}
+
 } // End of namespace Frotz
 } // End of namespace Glk
diff --git a/engines/glk/frotz/windows.h b/engines/glk/frotz/windows.h
index ba277d5..4335866 100644
--- a/engines/glk/frotz/windows.h
+++ b/engines/glk/frotz/windows.h
@@ -64,6 +64,11 @@ private:
 	 * Set a property value
 	 */
 	void setProperty(WindowProperty propType, uint16 value);
+
+	/**
+	 * Called when trying to reposition or resize windows. Does special handling for the lower window
+	 */
+	void checkRepositionLower();
 public:
 	/**
 	 * Constructor
diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp
index e2da317..6e0f33e 100644
--- a/engines/glk/glk_api.cpp
+++ b/engines/glk/glk_api.cpp
@@ -258,10 +258,11 @@ winid_t GlkAPI::glk_window_get_sibling(winid_t win) {
 	if (!parentWin)
 		return nullptr;
 
-	if (parentWin->_child1 == win)
-		return parentWin->_child2;
-	else if (parentWin->_child2 == win)
-		return parentWin->_child1;
+	int index = parentWin->_children.indexOf(win);
+	if (index == ((int)parentWin->_children.size() - 1))
+		return parentWin->_children.front();
+	else if (index >= 0)
+		return parentWin->_children[index + 1];
 
 	return nullptr;
 }
diff --git a/engines/glk/glk_types.h b/engines/glk/glk_types.h
index 2e23aec..4a29b15 100644
--- a/engines/glk/glk_types.h
+++ b/engines/glk/glk_types.h
@@ -150,12 +150,12 @@ enum WinType {
 };
 
 enum WinMethod {
-	winmethod_Left    = 0x00,
-	winmethod_Right   = 0x01,
-	winmethod_Above   = 0x02,
-	winmethod_Below   = 0x03,
-	winmethod_OnTop   = 0x04,		///< Newly introduced for ScummGlk
-	winmethod_DirMask = 0x0f,
+	winmethod_Left         = 0x00,
+	winmethod_Right        = 0x01,
+	winmethod_Above        = 0x02,
+	winmethod_Below        = 0x03,
+	winmethod_Arbitrary    = 0x04,		///< Newly introduced for ScummGlk
+	winmethod_DirMask      = 0x0f,
 
 	winmethod_Fixed        = 0x10,
 	winmethod_Proportional = 0x20,
diff --git a/engines/glk/utils.h b/engines/glk/utils.h
index 3655f57..2532f27 100644
--- a/engines/glk/utils.h
+++ b/engines/glk/utils.h
@@ -23,13 +23,20 @@
 #ifndef GLK_UTILS_H
 #define GLK_UTILS_H
 
+#include "common/array.h"
 #include "common/rect.h"
 #include "glk/glk_types.h"
 
 namespace Glk {
 
+/**
+ * Two dimensional point
+ */
 typedef Common::Point Point;
 
+/**
+ * Contains a square box/rect area
+ */
 struct Rect : public Common::Rect {
 public:
 	static Rect fromXYWH(int x, int y, int w, int h) {
@@ -42,6 +49,24 @@ public:
 };
 
 /**
+ * Derived array class
+ */
+template<class T>class Array : public Common::Array<T> {
+public:
+	/**
+	 * Return the index in the array of a passed item
+	 */
+	int indexOf(T val) {
+		for (size_t idx = 0; idx < this->size(); ++idx) {
+			if ((*this).operator[](idx) == val)
+				return idx;
+		}
+
+		return -1;
+	}
+};
+
+/**
  * Converts a decimal or hexadecimal string into a number
  */
 int strToInt(const char *s);
diff --git a/engines/glk/window_pair.cpp b/engines/glk/window_pair.cpp
index c90f389..7ddd57b 100644
--- a/engines/glk/window_pair.cpp
+++ b/engines/glk/window_pair.cpp
@@ -34,13 +34,13 @@ PairWindow::PairWindow(Windows *windows, uint method, Window *key, uint size) :
 	_wBorder((method & winmethod_BorderMask) == winmethod_Border),
 	_vertical(_dir == winmethod_Left || _dir == winmethod_Right),
 	_backward(_dir == winmethod_Left || _dir == winmethod_Above),
-	_key(key), _size(size), _keyDamage(0), _child1(nullptr), _child2(nullptr) {
+	_key(key), _size(size), _keyDamage(0) {
 	_type = wintype_Pair;
 }
 
 PairWindow::~PairWindow() {
-	delete _child1;
-	delete _child2;
+	for (uint idx = 0; idx < _children.size(); ++idx)
+		delete _children[idx];
 }
 
 void PairWindow::rearrange(const Rect &box) {
@@ -51,24 +51,23 @@ void PairWindow::rearrange(const Rect &box) {
 	_bbox = box;
 
 	if (!_backward) {
-		ch1 = _child1;
-		ch2 = _child2;
+		ch1 = _children[0];
+		ch2 = _children[1];
 	} else {
-		ch1 = _child2;
-		ch2 = _child1;
+		ch1 = _children[1];
+		ch2 = _children[0];
 	}
 
-
-	if (_dir == winmethod_OnTop) {
-		// ch2 is on top of ch1
-		ch1->rearrange(box1);
-		if (!ch2->_bbox.isEmpty() && !ch2->_bbox.contains(box)) {
-			// ch2 is outside new bounds, so clip it to the new dimensions
-			Rect subRect = ch2->_bbox;
-			subRect.clip(box);
-			ch2->rearrange(subRect);
+	if (_dir == winmethod_Arbitrary) {
+		// When a pair window is in "arbitrary" mode, each child window has it's own independant positioning,
+		// so thre's no need to be readjusting it
+		/*
+		for (int ctr = 0, idx = (_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
+				++ctr, idx += (_backward ? -1 : 1)) {
+			Window *w = _children[idx];
+			w->rearrange();
 		}
-
+		*/
 		return;
 	}
 
@@ -142,10 +141,12 @@ void PairWindow::rearrange(const Rect &box) {
 void PairWindow::redraw() {
 	Window::redraw();
 
-	_child1->redraw();
-	_child2->redraw();
+	for (int ctr = 0, idx = (_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
+		++ctr, idx += (_backward ? -1 : 1)) {
+		_children[idx]->redraw();
+	}
 
-	Window *child = !_backward ? _child1 : _child2;
+	Window *child = !_backward ? _children.front() : _children.back();
 	Rect box(child->_bbox.left, child->_yAdj ? child->_bbox.top - child->_yAdj : child->_bbox.top,
 			 child->_bbox.right, child->_bbox.bottom);
 
@@ -184,6 +185,7 @@ void PairWindow::getArrangement(uint *method, uint *size, Window **keyWin) {
 void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {
 	uint newDir;
 	bool newVertical, newBackward;
+	assert((method & winmethod_DirMask) != winmethod_Arbitrary && _dir != winmethod_Arbitrary);
 
 	if (_key) {
 		Window *wx;
@@ -226,9 +228,7 @@ void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {
 
 	if ((newBackward && !_backward) || (!newBackward && _backward)) {
 		// switch the children
-		Window *tmpWin = _child1;
-		_child1 = _child2;
-		_child2 = tmpWin;
+		SWAP(_children[0], _children[1]);
 	}
 
 	// set up everything else
@@ -245,11 +245,12 @@ void PairWindow::setArrangement(uint method, uint size, Window *keyWin) {
 }
 
 void PairWindow::click(const Point &newPos) {
-	if (_child1->_bbox.contains(newPos))
-		_child1->click(newPos);
-
-	if (_child2->_bbox.contains(newPos))
-		_child2->click(newPos);
+	for (int ctr = 0, idx = (!_backward ? (int)_children.size() - 1 : 0); ctr < (int)_children.size();
+		++ctr, idx += (_backward ? -1 : 1)) {
+		Window *w = _children[idx];
+		if (w->_bbox.contains(newPos))
+			w->click(newPos);
+	}
 }
 
 } // End of namespace Glk
diff --git a/engines/glk/window_pair.h b/engines/glk/window_pair.h
index 83cbcc8..10d9264 100644
--- a/engines/glk/window_pair.h
+++ b/engines/glk/window_pair.h
@@ -24,15 +24,17 @@
 #define GLK_WINDOW_PAIR_H
 
 #include "glk/windows.h"
+#include "glk/utils.h"
 
 namespace Glk {
 
 /**
- * Pair window
+ * Acts as a container of child windows. Under most cases there will be exactly two children,
+ * though in a special new "OnTop" mode, there can be more than two
  */
 class PairWindow : public Window {
 public:
-	Window *_child1, *_child2;
+	Array<Window *> _children;
 
 	// split info...
 	uint _dir;               ///< winmethod_Left, Right, Above, Below, or OnTop
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
index de8fa52..d75ba1f 100644
--- a/engines/glk/windows.cpp
+++ b/engines/glk/windows.cpp
@@ -104,15 +104,22 @@ Window *Windows::windowOpen(Window *splitwin, uint method, uint size,
 
 		val = (method & winmethod_DirMask);
 		if (val != winmethod_Above && val != winmethod_Below && val != winmethod_Left
-				&& val != winmethod_Right && val != winmethod_OnTop) {
+				&& val != winmethod_Right && val != winmethod_Arbitrary) {
 			warning("window_open: invalid method (bad direction)");
 			return nullptr;
 		}
 
-		oldparent = splitwin->_parent;
-		if (oldparent && oldparent->_type != wintype_Pair) {
-			warning("window_open: parent window is not Pair");
-			return nullptr;
+		if (splitwin->_type == wintype_Pair) {
+			if ((method & winmethod_DirMask) != winmethod_Arbitrary) {
+				warning("window_open: Can only add windows to a Pair window in arbitrary mode");
+				return nullptr;
+			}
+		} else {
+			oldparent = splitwin->_parent;
+			if (oldparent && oldparent->_type != wintype_Pair) {
+				warning("window_open: parent window is not Pair");
+				return nullptr;
+			}
 		}
 	}
 
@@ -125,11 +132,16 @@ Window *Windows::windowOpen(Window *splitwin, uint method, uint size,
 
 	if (!splitwin) {
 		_rootWin = newwin;
+	} else if (splitwin->_type == wintype_Pair) {
+		pairWin = static_cast<PairWindow *>(splitwin);
+		pairWin->_dir = winmethod_Arbitrary;
+		pairWin->_children.push_back(newwin);
+		newwin->_parent = pairWin;
 	} else {
 		// create pairWin, with newwin as the key
 		pairWin = newPairWindow(method, newwin, size);
-		pairWin->_child1 = splitwin;
-		pairWin->_child2 = newwin;
+		pairWin->_children.push_back(splitwin);
+		pairWin->_children.push_back(newwin);
 
 		splitwin->_parent = pairWin;
 		newwin->_parent = pairWin;
@@ -138,10 +150,11 @@ Window *Windows::windowOpen(Window *splitwin, uint method, uint size,
 		if (oldparent) {
 			PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
 			assert(parentWin);
-			if (parentWin->_child1 == splitwin)
-				parentWin->_child1 = pairWin;
-			else
-				parentWin->_child2 = pairWin;
+
+			for (uint idx = 0; idx < parentWin->_children.size(); ++idx) {
+				if (parentWin->_children[idx] == splitwin)
+					parentWin->_children[idx] = pairWin;
+			}
 		} else {
 			_rootWin = pairWin;
 		}
@@ -168,24 +181,22 @@ void Windows::windowClose(Window *win, StreamResult *result) {
 		PairWindow *pairWin = dynamic_cast<PairWindow *>(win->_parent);
 		PairWindow *grandparWin;
 
-		if (win == pairWin->_child1) {
-			sibWin = pairWin->_child2;
-		} else if (win == pairWin->_child2) {
-			sibWin = pairWin->_child1;
-		} else {
+		int index = pairWin->_children.indexOf(win);
+		if (index == -1) {
 			warning("windowClose: window tree is corrupted");
 			return;
 		}
 
+		sibWin = (index = ((int)pairWin->_children.size() - 1)) ?
+			pairWin->_children.front() : pairWin->_children[index + 1];
+
 		grandparWin = dynamic_cast<PairWindow *>(pairWin->_parent);
 		if (!grandparWin) {
 			_rootWin = sibWin;
 			sibWin->_parent = nullptr;
 		} else {
-			if (grandparWin->_child1 == pairWin)
-				grandparWin->_child1 = sibWin;
-			else
-				grandparWin->_child2 = sibWin;
+			index = grandparWin->_children.indexOf(pairWin);
+			grandparWin->_children[index] = sibWin;
 			sibWin->_parent = grandparWin;
 		}
 
@@ -197,10 +208,8 @@ void Windows::windowClose(Window *win, StreamResult *result) {
 		win->close(true);
 
 		// This probably isn't necessary, but the child *is* gone, so just in case.
-		if (win == pairWin->_child1)
-			pairWin->_child1 = nullptr;
-		else if (win == pairWin->_child2)
-			pairWin->_child2 = nullptr;
+		index = pairWin->_children.indexOf(win);
+		pairWin->_children[index] = nullptr;
 
 		// Now we can delete the parent pair.
 		pairWin->close(false);
@@ -462,21 +471,20 @@ Window *Windows::iterateTreeOrder(Window *win) {
 
 	PairWindow *pairWin = dynamic_cast<PairWindow *>(win);
 	if (pairWin) {
-		if (!pairWin->_backward)
-			return pairWin->_child1;
-		else
-			return pairWin->_child2;
+		return pairWin->_backward ? pairWin->_children.back() : pairWin->_children.front();
 	} else {
 		while (win->_parent) {
 			pairWin = dynamic_cast<PairWindow *>(win->_parent);
 			assert(pairWin);
+			int index = pairWin->_children.indexOf(win);
+			assert(index != -1);
 
 			if (!pairWin->_backward) {
-				if (win == pairWin->_child1)
-					return pairWin->_child2;
+				if (index < ((int)pairWin->_children.size() - 1))
+					return pairWin->_children[index + 1];
 			} else {
-				if (win == pairWin->_child2)
-					return pairWin->_child1;
+				if (index > 0)
+					return pairWin->_children[index - 1];
 			}
 
 			win = pairWin;
@@ -515,10 +523,11 @@ Window::~Window() {
 
 	// Remove the window from any parent
 	PairWindow *parent = dynamic_cast<PairWindow *>(_parent);
-	if (parent && parent->_child1 == this)
-		parent->_child1 = nullptr;
-	if (parent && parent->_child2 == this)
-		parent->_child2 = nullptr;
+	if (parent) {
+		int index = parent->_children.indexOf(this);
+		if (index != -1)
+			parent->_children[index] = nullptr;
+	}
 
 	// Delete any attached window stream
 	_echoStream = nullptr;
@@ -554,8 +563,8 @@ void Window::close(bool recurse) {
 
 	PairWindow *pairWin = dynamic_cast<PairWindow *>(this);
 	if (pairWin) {
-		pairWin->_child1->close(recurse);
-		pairWin->_child2->close(recurse);
+		for (uint idx = 0; idx < pairWin->_children.size(); ++idx)
+			pairWin->_children[idx]->close();
 	}
 
 	// Finally, delete the window





More information about the Scummvm-git-logs mailing list