Refactor overlay image code to an own subclass

pull/110/head
Hleb Valoshka 2018-10-13 21:48:05 +03:00
parent 974686cf15
commit e546a53e19
6 changed files with 126 additions and 85 deletions

View File

@ -834,12 +834,12 @@ Command* CommandParser::parseCommand()
}
else if (commandName == "overlay")
{
double duration;
float duration;
float xoffset;
float yoffset;
float alpha;
string filename;
int fitscreen;
bool fitscreen;
if(!paramList->getNumber("duration", duration))
duration = 3;
@ -851,8 +851,14 @@ Command* CommandParser::parseCommand()
alpha = 1;
if(!paramList->getString("filename", filename))
filename = "";
if(!paramList->getNumber("fitscreen", fitscreen))
fitscreen = 0;
if(!paramList->getBoolean("fitscreen", fitscreen))
{
int f;
if(!paramList->getNumber("fitscreen", f))
fitscreen = false;
else
fitscreen = (bool) f;
}
cmd = new CommandScriptImage(duration, xoffset, yoffset, alpha, filename, fitscreen);
}

View File

@ -1001,8 +1001,9 @@ double RepeatCommand::getDuration() const
}
// ScriptImage command
CommandScriptImage::CommandScriptImage(double _duration, float _xoffset,
float _yoffset, float _alpha, std::string _filename, int _fitscreen) :
CommandScriptImage::CommandScriptImage(float _duration, float _xoffset,
float _yoffset, float _alpha,
std::string _filename, bool _fitscreen) :
duration(_duration),
xoffset(_xoffset),
yoffset(_yoffset),

View File

@ -768,8 +768,8 @@ class RepeatCommand : public Command
class CommandScriptImage : public InstantaneousCommand
{
public:
CommandScriptImage(double _duration, float _xoffset, float _yoffset,
float _alpha, std::string, int _fitscreen);
CommandScriptImage(float _duration, float _xoffset, float _yoffset,
float _alpha, std::string, bool _fitscreen);
void process(ExecutionEnvironment&);
private:

View File

@ -88,18 +88,6 @@ static void warning(string s)
}
struct OverlayImage
{
Texture* texture;
int xSize;
int ySize;
int left;
int bottom;
};
vector<OverlayImage> overlayImages;
// Extremely basic implementation of an ExecutionEnvironment for
// running scripts.
class CoreExecutionEnvironment : public ExecutionEnvironment
@ -3288,29 +3276,75 @@ static void showViewFrame(const View* v, int width, int height)
}
void CelestiaCore::setScriptImage(double duration, float xoffset,
float yoffset, float alpha, const string& filename, int fitscreen)
void CelestiaCore::setScriptImage(float duration,
float xoffset,
float yoffset,
float alpha,
const string& filename,
bool fitscreen)
{
imageStart = currentTime;
imageDuration = duration;
imageXoffset = xoffset;
imageYoffset = yoffset;
imageAlpha = alpha;
imageFitscreen = fitscreen;
if (scriptImageFilename != (string("images") + "/" + filename).c_str()) // Check if the image is already loaded
if (!image || !image->isNewImage(filename))
{
delete scriptImage;
scriptImageFilename = (string("images") + "/" + filename).c_str();
scriptImage = LoadTextureFromFile(scriptImageFilename);
delete image;
image = new CelestiaCore::OverlayImage(filename);
}
image->setStartTime((float) currentTime);
image->setDuration(duration);
image->setOffset(xoffset, yoffset);
image->setAlpha(alpha);
image->fitScreen(fitscreen);
}
CelestiaCore::OverlayImage::OverlayImage(string f)
{
filename = std::move(f);
delete texture;
texture = LoadTextureFromFile(string("images/") + filename);
}
void CelestiaCore::OverlayImage::render(float curr_time, int width, int height)
{
if (!texture || (curr_time >= start + duration))
return;
float xSize = texture->getWidth();
float ySize = texture->getHeight();
// center overlay image horizontally if offsetX = 0
float left = (width * (1 + offsetX) - xSize)/2;
// center overlay image vertically if offsetY = 0
float bottom = (height * (1 + offsetY) - ySize)/2;
if (fitscreen)
{
float coeffx = xSize / width; // overlay pict width/view window width ratio
float coeffy = ySize / height; // overlay pict height/view window height ratio
xSize = xSize / coeffx; // new overlay picture width size to fit viewport
ySize = ySize / coeffy; // new overlay picture height to fit viewport
left = (width - xSize) / 2; // to be sure overlay pict is centered in viewport
bottom = 0; // overlay pict locked at bottom of screen
}
glEnable(GL_TEXTURE_2D);
texture->bind();
glBegin(GL_TRIANGLE_FAN);
glColor4f(1.0f, 1.0f, 1.0f, alpha);
glTexCoord2f(0.0f, 1.0f); glVertex2f(left, bottom);
glTexCoord2f(1.0f, 1.0f); glVertex2f(left + xSize, bottom);
glTexCoord2f(1.0f, 0.0f); glVertex2f(left + xSize, bottom + ySize);
glTexCoord2f(0.0f, 0.0f); glVertex2f(left, bottom + ySize);
glEnd();
}
void CelestiaCore::renderOverlay()
{
#ifdef CELX
if (luaHook) luaHook->callLuaHook(this,"renderoverlay");
if (luaHook) luaHook->callLuaHook(this, "renderoverlay");
#endif
if (font == nullptr)
return;
@ -3323,41 +3357,15 @@ void CelestiaCore::renderOverlay()
overlay->begin();
if (scriptImage != nullptr && currentTime < imageStart + imageDuration && (runningScript != nullptr || celxScript != nullptr))
#ifdef CELX
if (runningScript || celxScript)
{
glEnable(GL_TEXTURE_2D);
float xSize = (scriptImage->getWidth());
float ySize = (scriptImage->getHeight());
float left = (width*(1 + imageXoffset) - xSize)/2; // center overlay image horizontally if imageXoffset = 0
float bottom = (height*(1 + imageYoffset) - ySize)/2; // center overlay image vertically if imageYoffset = 0
if (imageFitscreen == 1)
{
float coeffx = xSize/width; // compute overlay pict width/view window width ratio
float coeffy = ySize/height; // compute overlay pict height/view window height ratio
xSize = int (xSize/coeffx); // compute new overlay picture width size to fit viewport
ySize = int (ySize/coeffy); // compute new overlay picture height to fit viewport
left = (width - xSize)/2; // almost useless, just to be sure overlay pict is perfectly centered in viewport
bottom = 0; // overlay pict locked at bottom of screen
}
scriptImage->bind();
glBegin(GL_QUADS);
glColor4f(1.0f, 1.0f, 1.0f, imageAlpha);
glTexCoord2f(0.0f, 1.0f);
glVertex2i(int (left), int (bottom));
glTexCoord2f(1.0f, 1.0f);
glVertex2i(int (left) + int (xSize), int (bottom));
glColor4f(1.0f, 1.0f, 1.0f, imageAlpha);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(int (left) + int (xSize), int (bottom) + int (ySize));
glTexCoord2f(0.0f, 0.0f);
glVertex2i(int (left), int (bottom) + int (ySize));
glEnd();
#else
if (runningScript)
{
#endif
if (image)
image->render((float) currentTime, width, height);
}
if (views.size() > 1)

View File

@ -190,15 +190,45 @@ class CelestiaCore // : public Watchable<CelestiaCore>
enum
{
ShowNoElement = 0x001,
ShowTime = 0x002,
ShowNoElement = 0x001,
ShowTime = 0x002,
ShowVelocity = 0x004,
ShowSelection = 0x008,
ShowFrame = 0x010,
ShowSelection = 0x008,
ShowFrame = 0x010,
};
typedef void (*ContextMenuFunc)(float, float, Selection);
private:
class OverlayImage
{
public:
OverlayImage(string);
~OverlayImage() { delete texture; }
OverlayImage() =default;
OverlayImage(OverlayImage&) =delete;
OverlayImage(OverlayImage&&) =delete;
void render(float, int, int);
inline bool isNewImage(const string& f) { return filename != f; }
void setStartTime(float t) { start = t; }
void setDuration(float t) { duration = t; }
void setOffset(float x, float y) { offsetX = x; offsetY = y; }
void setAlpha(float t) { alpha = t; }
void fitScreen(bool t) { fitscreen = t; }
private:
float start{ 0.0f };
float duration{ 0.0f };
float offsetX{ 0.0f };
float offsetY{ 0.0f };
float alpha{ 0.0f };
bool fitscreen{ false };
std::string filename;
Texture* texture{ nullptr };
};
public:
CelestiaCore();
~CelestiaCore();
@ -346,6 +376,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
void fatalError(const std::string&, bool visual = true);
void setScriptImage(float, float, float, float, const std::string&, bool);
protected:
bool readStars(const CelestiaConfig&, ProgressNotifier*);
void renderOverlay();
@ -379,13 +411,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
double messageDuration{ 0.0 };
Color textColor{ Color(1.0f, 1.0f, 1.0f) };
double imageStart{ 0.0 };
double imageDuration{ 0.0 };
float imageXoffset{ 0.0f };
float imageYoffset{ 0.0f };
float imageAlpha{ 0.0f };
int imageFitscreen{ 0 };
std::string scriptImageFilename;
OverlayImage *image{ nullptr };
std::string typedText;
std::vector<std::string> typedTextCompletion;
@ -454,7 +480,6 @@ class CelestiaCore // : public Watchable<CelestiaCore>
ContextMenuFunc contextMenuCallback{ nullptr };
Texture* logoTexture{ nullptr };
Texture* scriptImage{ nullptr };
Alerter* alerter{ nullptr };
std::vector<CelestiaWatcher*> watchers;
@ -483,9 +508,6 @@ class CelestiaCore // : public Watchable<CelestiaCore>
friend TextureFont* getFont(CelestiaCore*);
friend TextureFont* getTitleFont(CelestiaCore*);
#endif
public:
void setScriptImage(double, float, float, float, const std::string&, int);
};
#endif // _CELESTIACORE_H_

View File

@ -3471,12 +3471,16 @@ static int celestia_overlay(lua_State* l)
Celx_CheckArgs(l, 2, 7, "One to Six arguments expected to function celestia:overlay");
CelestiaCore* appCore = this_celestia(l);
double duration = Celx_SafeGetNumber(l, 2, WrongType, "First argument to celestia:overlay must be a number (duration)", 3.0);
float duration = Celx_SafeGetNumber(l, 2, WrongType, "First argument to celestia:overlay must be a number (duration)", 3.0);
float xoffset = Celx_SafeGetNumber(l, 3, WrongType, "Second argument to celestia:overlay must be a number (xoffset)", 0.0);
float yoffset = Celx_SafeGetNumber(l, 4, WrongType, "Third argument to celestia:overlay must be a number (yoffset)", 0.0);
float alpha = Celx_SafeGetNumber(l, 5, WrongType, "Fourth argument to celestia:overlay must be a number (alpha)", 1.0);
const char* filename = Celx_SafeGetString(l, 6, AllErrors, "Fifth argument to celestia:overlay must be a string (filename)");
int fitscreen = Celx_SafeGetNumber(l, 7, WrongType, "Sixth argument to celestia:overlay must be a number (fitscreen)", 0);
bool fitscreen;
if (lua_isboolean(l, 7))
fitscreen = lua_toboolean(l, 7);
else
fitscreen = (bool) Celx_SafeGetNumber(l, 7, WrongType, "Sixth argument to celestia:overlay must be a number or a boolean(fitscreen)", 0);
appCore->setScriptImage(duration, xoffset, yoffset, alpha, filename, fitscreen);