Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126512
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
18 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/loading.cpp b/util/loading.cpp
new file mode 100644
index 00000000..c9d08d3b
--- /dev/null
+++ b/util/loading.cpp
@@ -0,0 +1,529 @@
+#include "util/bitmap.h"
+#include "util/trans-bitmap.h"
+#include <math.h>
+#include <iostream>
+
+#include "level/utils.h"
+#include "util/messages.h"
+#include "loading.h"
+#include "util/file-system.h"
+#include "util/font.h"
+#include "util/funcs.h"
+#include "util/gradient.h"
+#include "util/thread.h"
+#include "globals.h"
+#include <vector>
+#include "util/thread.h"
+#include "util/message-queue.h"
+#include "init.h"
+
+using namespace std;
+
+namespace Loader{
+
+// Util::Thread::Lock loading_screen_mutex;
+volatile bool done_loading = true;
+
+typedef struct pair{
+ int x, y;
+} ppair;
+
+class Info{
+public:
+ Info(){
+ Global::registerInfo(&messages);
+ }
+
+ bool transferMessages(Messages & box){
+ bool did = false;
+ while (messages.hasAny()){
+ const string & str = messages.get();
+ box.addMessage(str);
+ did = true;
+ }
+ return did;
+ }
+
+ ~Info(){
+ Global::unregisterInfo(&messages);
+ }
+
+private:
+ MessageQueue messages;
+};
+
+void * loadingScreenSimple1(void * arg);
+
+#if 0
+void startLoading(Util::Thread::Id * thread, void * arg, Kind kind){
+ bool create = false;
+ Util::Thread::acquireLock(&loading_screen_mutex);
+ create = done_loading;
+ done_loading = false;
+ Util::Thread::releaseLock(&loading_screen_mutex);
+
+ /* prevent multiple loading threads from being made */
+ if (create){
+ switch (kind){
+ case Default: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreen, arg); break;
+ case SimpleCircle: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreenSimple1, arg); break;
+ }
+ }
+}
+
+void stopLoading(Util::Thread::Id thread){
+ bool needJoin = false;
+ Util::Thread::acquireLock( &loading_screen_mutex );
+ needJoin = ! done_loading;
+ done_loading = true;
+ Util::Thread::releaseLock( &loading_screen_mutex );
+ if (needJoin){
+ Util::Thread::joinThread(thread);
+ }
+}
+#endif
+
+static void setupBackground(const Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Bitmap & infoBackground, const Bitmap & work){
+ background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
+ Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
+ Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
+ background.BlitToScreen();
+ background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
+}
+
+static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
+ Bitmap letters(width, height);
+ letters.fill( Bitmap::MaskColor() );
+ myFont.printf( 0, 0, Bitmap::makeColor(255, 255, 255), letters, message.c_str(), 0 );
+
+ vector< ppair > pairs;
+ /* store every pixel we need to draw */
+ for ( int x = 0; x < letters.getWidth(); x++ ){
+ for ( int y = 0; y < letters.getHeight(); y++ ){
+ int pixel = letters.getPixel(x, y);
+ if (pixel != Bitmap::MaskColor()){
+ ppair p;
+ p.x = x;
+ p.y = y;
+ pairs.push_back( p );
+ }
+ }
+ }
+
+ return pairs;
+}
+
+/* shows time elapsed */
+class TimeCounter{
+public:
+ TimeCounter():
+ work(200, 40){
+ start = Global::second_counter;
+ last = 0;
+ }
+
+ void draw(int x, int y){
+ const Font & font = Font::getDefaultFont(24, 24);
+ if (Global::second_counter != last){
+ work.clear();
+ last = Global::second_counter;
+ font.printf(0, 0, Bitmap::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
+ work.BlitAreaToScreen(x, y);
+ }
+ }
+
+ Bitmap work;
+ unsigned int start;
+ unsigned int last;
+};
+
+/* FIXME: get rid of this method */
+#if 0
+void * loadingScreen(void * arg){
+ int load_x = 80;
+ int load_y = 220;
+ const int infobox_width = 300;
+ const int infobox_height = 150;
+ Info info;
+ const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
+ const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
+ Level::LevelInfo levelInfo;
+ if (arg != NULL){
+ levelInfo = *(Level::LevelInfo*) arg;
+ }
+
+ if (levelInfo.getPositionX() != -1){
+ load_x = levelInfo.getPositionX();
+ }
+
+ if (levelInfo.getPositionY() != -1){
+ load_y = levelInfo.getPositionY();
+ }
+
+ // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
+ int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
+ int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
+
+ const int infobox_x = load_x;
+ const int infobox_y = load_y + load_height * 2;
+
+ Global::debug( 2 ) << "loading screen" << endl;
+
+ Bitmap work( load_width, load_height );
+
+ vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
+
+ Messages infobox(infobox_width, infobox_height);
+ Bitmap infoWork(infobox_width, infobox_height);
+ Bitmap infoBackground(infobox_width, infobox_height);
+
+ const int MAX_COLOR = 200;
+
+ /* blend from dark grey to light red */
+ Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
+
+ Global::speed_counter = 0;
+
+ if (levelInfo.getBackground() != 0){
+ setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
+ } else {
+ setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
+ }
+
+ Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
+
+ TimeCounter counter;
+
+ bool firstDraw = true;
+
+ while ( ! quit.get() ){
+
+ /* true if a logic loop has passed */
+ bool draw = firstDraw;
+
+ /* will be true if any new info messages appeared */
+ bool drawInfo = firstDraw;
+ firstDraw = false;
+ if ( Global::speed_counter > 0 ){
+ double think = Global::speed_counter;
+ Global::speed_counter = 0;
+ draw = true;
+
+ while ( think > 0 ){
+ gradient.backward();
+ think -= 1;
+ }
+
+ /* if no new messages appeared this will be false */
+ drawInfo = info.transferMessages(infobox);
+ } else {
+ Util::rest( 1 );
+ }
+
+ if (draw){
+ for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
+ int color = gradient.current(it->x);
+ work.putPixel(it->x, it->y, color);
+ }
+
+ // counter.draw(200, 100);
+
+ /* we might not have to draw the whole info box again if no new
+ * messages appeared.
+ */
+ if (drawInfo){
+ infoBackground.Blit(infoWork);
+
+ /* cheesy hack to change the font size. the font
+ * should store the size and change it on its own
+ */
+ Font::getFont(Global::DEFAULT_FONT, 13, 13);
+ infobox.draw(0, 0, infoWork, infoFont);
+ Font::getFont(Global::DEFAULT_FONT, 24, 24);
+ infoWork.BlitAreaToScreen(infobox_x, infobox_y);
+ }
+ /* work already contains the correct background */
+ // work.Blit( load_x, load_y, *Bitmap::Screen );
+ work.BlitAreaToScreen(load_x, load_y);
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+static void loadingScreen1(LoadingContext & context, const Level::LevelInfo & levelInfo){
+ int load_x = 80;
+ int load_y = 220;
+ const int infobox_width = 300;
+ const int infobox_height = 150;
+ Info info;
+ const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
+ const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
+
+ if (levelInfo.getPositionX() != -1){
+ load_x = levelInfo.getPositionX();
+ }
+
+ if (levelInfo.getPositionY() != -1){
+ load_y = levelInfo.getPositionY();
+ }
+
+ // const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
+ int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
+ int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
+
+ const int infobox_x = load_x;
+ const int infobox_y = load_y + load_height * 2;
+
+ Global::debug(2) << "loading screen" << endl;
+
+ Bitmap work(load_width, load_height);
+
+ vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
+
+ Messages infobox(infobox_width, infobox_height);
+ Bitmap infoWork(infobox_width, infobox_height);
+ Bitmap infoBackground(infobox_width, infobox_height);
+
+ const int MAX_COLOR = 200;
+
+ /* blend from dark grey to light red */
+ Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
+
+ Global::speed_counter = 0;
+
+ if (levelInfo.getBackground() != 0){
+ setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
+ } else {
+ setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
+ }
+
+ TimeCounter counter;
+
+ bool firstDraw = true;
+
+ while (! context.done()){
+
+ /* true if a logic loop has passed */
+ bool draw = firstDraw;
+
+ /* will be true if any new info messages appeared */
+ bool drawInfo = firstDraw;
+ firstDraw = false;
+ if ( Global::speed_counter > 0 ){
+ double think = Global::speed_counter;
+ Global::speed_counter = 0;
+ draw = true;
+
+ while ( think > 0 ){
+ gradient.backward();
+ think -= 1;
+ }
+
+ /* if no new messages appeared this will be false */
+ drawInfo = info.transferMessages(infobox);
+ } else {
+ Util::rest( 1 );
+ }
+
+ if (draw){
+ for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
+ int color = gradient.current(it->x);
+ work.putPixel(it->x, it->y, color);
+ }
+
+ // counter.draw(200, 100);
+
+ /* we might not have to draw the whole info box again if no new
+ * messages appeared.
+ */
+ if (drawInfo){
+ infoBackground.Blit(infoWork);
+
+ /* cheesy hack to change the font size. the font
+ * should store the size and change it on its own
+ */
+ Font::getFont(Global::DEFAULT_FONT, 13, 13);
+ infobox.draw(0, 0, infoWork, infoFont);
+ Font::getFont(Global::DEFAULT_FONT, 24, 24);
+ infoWork.BlitAreaToScreen(infobox_x, infobox_y);
+ }
+ /* work already contains the correct background */
+ // work.Blit( load_x, load_y, *Bitmap::Screen );
+ work.BlitAreaToScreen(load_x, load_y);
+ }
+ }
+}
+
+/* shows some circles rotating around a center point */
+/* FIXME: get rid of this method */
+#if 0
+void * loadingScreenSimple1(void * arg){
+ Bitmap work(40, 40);
+ Bitmap original(40, 40);
+ original.BlitFromScreen(0, 0);
+ Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
+ Global::speed_counter = 0;
+ int angle = 0;
+ int color1 = Bitmap::makeColor(0, 0, 0);
+ int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
+ int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
+ int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
+ /* the length of this array is the number of circles to show */
+ int colors[4] = {color1, color2, color3, color4};
+ Bitmap::transBlender(0, 0, 0, 64);
+ /* speed of rotation */
+ int speed = 7;
+ while (! quit.get()){
+ bool draw = false;
+
+ if (Global::speed_counter > 0){
+ double think = Global::speed_counter;
+ Global::speed_counter = 0;
+ draw = true;
+
+ while (think > 0){
+ angle += speed;
+ think -= 1;
+ }
+ } else {
+ Util::rest(1);
+ }
+
+ if (draw){
+ int max = sizeof(colors) / sizeof(int);
+ double middleX = work.getWidth() / 2;
+ double middleY = work.getHeight() / 2;
+ original.Blit(work);
+ for (int i = 0; i < max; i++){
+ double x = cos(Util::radians(angle + 360 / max * i)) * 15;
+ double y = sin(Util::radians(angle + 360 / max * i)) * 15;
+ /* ghost circle */
+ work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
+ x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
+ y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
+ /* real circle */
+ work.circleFill(middleX + x, middleY + y, 2, colors[i]);
+ }
+ work.BlitAreaToScreen(0, 0);
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+static void loadingScreenSimpleX1(LoadingContext & context, const Level::LevelInfo & levelInfo){
+ Bitmap work(40, 40);
+ Bitmap original(40, 40);
+ original.BlitFromScreen(0, 0);
+ Global::speed_counter = 0;
+ int angle = 0;
+ int color1 = Bitmap::makeColor(0, 0, 0);
+ int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
+ int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
+ int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
+ /* the length of this array is the number of circles to show */
+ int colors[4] = {color1, color2, color3, color4};
+ Bitmap::transBlender(0, 0, 0, 64);
+ /* speed of rotation */
+ int speed = 7;
+ while (! context.done()){
+ bool draw = false;
+
+ if (Global::speed_counter > 0){
+ double think = Global::speed_counter;
+ Global::speed_counter = 0;
+ draw = true;
+
+ while (think > 0){
+ angle += speed;
+ think -= 1;
+ }
+ } else {
+ Util::rest(1);
+ }
+
+ if (draw){
+ int max = sizeof(colors) / sizeof(int);
+ double middleX = work.getWidth() / 2;
+ double middleY = work.getHeight() / 2;
+ original.Blit(work);
+ for (int i = 0; i < max; i++){
+ double x = cos(Util::radians(angle + 360 / max * i)) * 15;
+ double y = sin(Util::radians(angle + 360 / max * i)) * 15;
+ /* ghost circle */
+ work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
+ x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
+ y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
+ /* real circle */
+ work.circleFill(middleX + x, middleY + y, 2, colors[i]);
+ }
+ work.BlitAreaToScreen(0, 0);
+ }
+ }
+}
+
+LoadingContext::LoadingContext():
+finished(false){
+ Util::Thread::initializeLock(&lock);
+}
+
+LoadingContext::~LoadingContext(){
+}
+
+void LoadingContext::doLoad(){
+ this->load();
+ Util::Thread::acquireLock(&lock);
+ finished = true;
+ Util::Thread::releaseLock(&lock);
+}
+
+bool LoadingContext::done(){
+ bool ok = false;
+ Util::Thread::acquireLock(&lock);
+ ok = this->finished;
+ Util::Thread::releaseLock(&lock);
+ return ok;
+}
+
+void * LoadingContext::load_it(void * arg){
+ LoadingContext * context = (LoadingContext*) arg;
+ context->doLoad();
+ return NULL;
+}
+
+static void showLoadMessage(){
+ int screenX = 80;
+ int screenY = 50;
+ Bitmap work(110, 50);
+ work.BlitFromScreen(screenX, screenY);
+ Bitmap top(110, 50);
+ top.fill(Bitmap::makeColor(0, 0, 0));
+ Font::getDefaultFont(25, 25).printf(10, 5, Bitmap::makeColor(192, 192, 192), top, "Loading", 0);
+ Bitmap::transBlender(0, 0, 0, 200);
+ top.drawTrans(0, 0, work);
+ work.BlitAreaToScreen(screenX, screenY);
+}
+
+void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind){
+ Util::Thread::Id loadingThread;
+ bool created = Util::Thread::createThread(&loadingThread, NULL, (Util::Thread::ThreadFunction) LoadingContext::load_it, &context);
+ if (!created){
+ Global::debug(0) << "Could not create loading thread. Loading will occur in the main thread" << endl;
+ showLoadMessage();
+ LoadingContext::load_it(&context);
+ // throw LoadException(__FILE__, __LINE__, "Could not create loader thread");
+ } else {
+ switch (kind){
+ case Default: loadingScreen1(context, info); break;
+ case SimpleCircle: loadingScreenSimpleX1(context, info); break;
+ default: loadingScreen1(context, info); break;
+ }
+
+ Util::Thread::joinThread(loadingThread);
+ }
+}
+
+}
diff --git a/util/loading.h b/util/loading.h
new file mode 100644
index 00000000..0d648219
--- /dev/null
+++ b/util/loading.h
@@ -0,0 +1,44 @@
+#ifndef _paintown_loading_h
+#define _paintown_loading_h
+
+#include "util/thread.h"
+
+namespace Level{
+ class LevelInfo;
+}
+
+namespace Loader{
+
+/* Kind of loader to show */
+enum Kind{
+ Default,
+ SimpleCircle
+};
+
+class LoadingContext{
+public:
+ LoadingContext();
+ virtual ~LoadingContext();
+ virtual void doLoad();
+ virtual void load() = 0;
+ virtual bool done();
+ static void * load_it(void * arg);
+protected:
+ Util::Thread::Lock lock;
+ bool finished;
+};
+
+extern volatile bool done_loading;
+// extern Util::Thread::Lock loading_screen_mutex;
+
+/* deprecated, remove */
+void startLoadingX(Util::Thread::Id * thread, void * arg = 0, Kind kind = Default);
+void stopLoadingX(Util::Thread::Id thread);
+
+void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind = Default);
+
+void * loadingScreen(void *);
+
+}
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:49 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68880
Default Alt Text
(18 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline