(I don’t have any excuse, I just forgot to post that in time.)
This week I’ve sent my Cloud storage support as pull request to the main ScummVM Github repository, and thus started fixing everything what is not fixed enough, adding new minor features, etc.
Only pasting from clipboard support was added for EditableWidgets (I’d have to fix that too, btw).
I’ve added two new test suites in the Testbed: Cloud and Webserver. I’ve also added one test for openUrl in MiscTests. Almost all my tests are interactive, meaning they require user to check whether the feature works as it should, and press the right button.
Peter Bozsó (uruk-hai), my mentor, added OS X backend for openUrl. iOS backend it not there yet.
Another small feature which lacks iOS backend is the Networking::Connection::isLimited() function, which is used in DownloadDialog to notify users to think whether they want to download game data while using limited connection. For now only Android supports this, other platforms are using default backend, which always returns that connection is not limited.
AJAX version of local webserver’s Files Manager was added this week. One can navigate through directories without page refreshing all the time. This version also contains «breadcrumbs» navigation feature, so one can get up more than one level with one click at the path.
Users can override webserver’s port through the Options dialog now. Yet, if they want to use webserver for auth, they have to use the default value.
Some refactoring/cleanup in the code and different minor fixes were made. More OSD messages added to notify user of success or failure. I’ve also updated Dropbox to use their API v2 everywhere, as v1 is deprecated now.
I’ve added detailed information about the cloud storage support and local webserver to the ScummVM wiki. These should help people understand PR’s code. Some ideas are coming out in the discussion. For example, webserver is being stopped now when users close the Options dialog to prevent it being used by someone else.
In my previous post I’ve mentioned my Container PR — and voila — it was merged! So the first thing I’ve done this week was merging it from upstream’s master into my cloud fork’s master and using the Container in the Cloud tab. I’ve also fixed a few TabWidget’s height issues in that a bit later.
Box support was added this week, so the original plan to add 4 cloud services is accomplished. Box is a bit similar to Google Drive, as it uses files ids instead of paths. The other interesting thing about it is that it has yet another approach to file uploading, so I had to tune some things one more time to support this one too.
I’m not planning to add more cloud services yet. I was unable to even find out how to work with iCloud. OwnCloud uses WebDAV instead of OAuth2 + REST API and they are not going to implement one. I’m not sure how long will it take to add WebDAV support, so I’d be working on other things for now.
A few upgrades were made in the DownloadDialog and local webserver’s Files Manager. The first one now shows progress a bit more precisely because it’s calculated based on downloaded size, not the number of files downloaded. It also shows the downloaded size, total size and current speed there.
Files Manager now supports directories uploading (works in Chrome only, as that’s the only browser where this feature is implemented). I’ve also added code which should correctly determine server’s IP on Linux. Some minor improvements like file type icons were made:
Finally, I started working on openUrl and clipboard support. Windows, Linux and Android already support opening URL in the browser, OS X and iOS backends are on the way. I also have some Symbian code, but it could take some time to implement it properly.
Clipboard is already supported in SDL2, and I just started working on adding it. Right now it’s only Ctrl+V support for EditableWidget. We’re also thinking on adding selecting feature there, so users could also use Ctrl+C. I’m not sure how that should work on platforms like Android, where we usually don’t have keyboards attached. I mean, EditableWidgets are not Android EditText fields, so they don’t show a menu on long tap, which means we either implement it or make users suffer.
These two features are what I’m going to work on. Then I also should add some tests into testbed engine, and do some documenting/refactoring where needed.
This week started with the DownloadDialog, which allows users to download directories from their cloud storage onto their device. Navigating through the remote directories is a bit slower than browsing local ones, but it works fine. Download is done in the background. On the completion, OSD message is shown. If DownloadDialog was not closed, ScummVM automatically detects the game in the directory (the way it works in «Add Game») and suggests options. «Add Game» also checks whether you’re trying to specify the currently downloading directory — and notifies that this is forbidden. I’ve also recorded a video showing how storage connecting and game downloading features work:
(Youtube video in iframe here)
Then I started working on the next feature on the plan — Wi-Fi Sharing. Now there is a special «Run Server» button in the Cloud tab, which one can use to start local webserver. It also shows its IP there (works on Windows only yet):
I’ve added «/files» path to the webserver, so that’s where one can browse directories on the device. Clicking on a file causes its download, obviously. There are also two buttons: «Create directory» and «Upload files». One can’t upload directories yet, but multiple files uploading works fine.
I’ve tried downloading a 349 MB file from that webserver and it took me 16 seconds. That’s about 22 megabytes per second! Unfortunately, I can’t say the same about uploading. It took me 20 seconds to upload a 9,5 MB file and 11:15 to upload that 349 MB file. That’s about a 0.5 megabyte per second. Handling multipart/form-data POST is not an easy thing, and it doesn’t work fast in my webserver implementation yet.
What’s next? My Container PR is not merged yet and this week features might need some polishing after review. The next thing in the plan is to implement the fourth cloud support.
As I mentioned in the previous post, I had a few things to do this week: our university team was playing AltayCTF (we won the first place) and I had to move out of the dormitory. To compensate these days off, I’m working this weekend.
As planned, I’ve implemented clipping in all the other drawsteps and used these in all widgets. Now we can put any widget in the container and it would be clipped as it should be. More screenshots could be found on the special page.
Then I got all container-related commits in a new branch (because my separate container branch was based on cloud branch, as I had to test my container on Cloud tab) and issued a pull request.
I guess I’d spend some time polishing that when I’d get some feedback, but until then I’ve decided to test my cloud feature on Unix. All this time I worked on Windows and was using MinGW to check it could be built in Unix-like environment, but never launched that on actual Unix. I installed Kubuntu in VirtualBox and cloned my repo.
The first thing I found out is that our configure stops if there is no curl_config. I guess that’s not OK, because if there is no curl_config, we probably should build ScummVM without curl support (i.e. without clouds). Yet it works fine without SDL_Net installed, so my first built ScummVM was supporting clouds, but not local webserver — that’s how I checked that storage connection wizard works fine.
Then I installed SDL_Net and rebuilt ScummVM to check that the local webserver works fine too. It is. The saves sync wasn’t, though. I had to fix a few minor bugs, but that was easy. Now saves sync is OK too. I was lazy to edit .gitconfig or to setup a shared folder, so I just used ScummVM’s sync to upload necessary source files into my Dropbox :D
When I’d be done with the container, I’d start working on cloud files management — some GUI dialogs which allow users to upload and download game data.
First of all, I finally passed my exams! I’ve got a few things to do, but in July I’d be completely free to work on my project. That’s why I wasn’t too active this week and wouldn’t be on the next one.
So, this week I was working on non-cloud-related thingie: a new GUI widget, which would contain other widgets of unlimited total height — the Container. Well, it’s actually a ScrollContainerWidget, and the main thing it has is a scrollbar. As I said in the previous post, one of my dialogs — the storage wizard — is too lengthy to be displayed in that area where ScummVM shows its dialogs. We decided that I should implement the Container, so we can put dialog contents in it, and in these cases when there is no room to display all of them, the scrollbar would automatically appear and no overlap will happen.
The first thing I changed was label — it already has a clipping rectangle, so I only had to pass the right values. Then the fun (to be read as difficult) part started. Widgets doesn’t have any clipping rectangle, which means you can’t just make the button draw only part of it. And, well, each widget has its own method, so it means I’ve got to change all of these in order to make them support clipping.
I started with buttons and PopUpWidget, because those are used in the Cloud tab of the Options dialog. Their drawWidget() method calls the corresponding drawButton()/drawPopUpWidget() method of ThemeEngine. ThemeEngine uses queueDD() and queueDDText(). Some DrawData objects are created in there, then their draw steps are called. If I recall correctly, draw steps are methods of VectorRenderer, which has VectorRendererSpec backends with implementations of these. So, I’ve got to pass that clipping area information from Widget though ThemeEngine and DrawData objects right to VectorRendererSpec and use it there.
Each of those draw step implementations has some additional functions in VectorRendererSpec. And these functions have some complicated logic and lots of macros usage. And none of these happen to think that clipping would ever be needed.
So, buttons are using drawRoundedSquare() draw step method. To minimize the possibitility of breaking something, I decided to leave these methods and add new ones — drawRoundedSquareClip() in this case. It checks that clipping is actually needed (i.e. button area is not completely in the clipping area), and if not, uses the original one. If clipping is needed, then other Clip-versions are used. So, drawRoundedSquareAlgClip(), drawBorderRoundedSquareAlgClip(), drawInteriorRoundedSquareAlgClip(), gradientFillClip(), blendFillClip(), colorFillClip() and a lot of macros with names like BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP() arrived.
All this — for rounded squares. And there are also triangles, circles and other draw steps, which I didn’t touch yet. But still, Container already works with buttons, PopUpWidget and labels, and I guess in some cases it would be enough to add new draw<WidgetName>() and use all these methods, which already do clipping, so it should be getting easier as I go further. The plan is to make all other widgets support clipping, so Container could be used with any of them. Apart from that — it seems to work fine.