1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
//
//
#include "texture.h"
#include "bmpman/bmpman.h"
#define BMPMAN_INTERNAL
#include "bmpman/bm_internal.h"
namespace scripting {
namespace api {
texture_h::texture_h() = default;
texture_h::texture_h(int bm, bool refcount) : handle(bm) {
if (refcount && isValid())
bm_get_entry(bm)->load_count++;
}
texture_h::~texture_h()
{
if (!isValid()) {
// There is nothing to release
return;
}
//Note: We previously checked the load count here to make sure we don't unload the texture if it is in use otherwise.
//That is dangerous, as if anything else locks a lua-created texture while lua loses scope of the texture, we leak
//the texture as the load_count from the creation in lua will never decrease. To fix this, we need to properly refcount
//the textures using load_count. Anything that creates a texture object must also increase load count, unless it is
//created in a way that already increases load_count (like bm_load). That way, a texture going out of scope needs to be
//released and is safed against memleaks. -Lafiel
bm_release(handle);
}
bool texture_h::isValid() const { return bm_is_valid(handle) != 0; }
texture_h::texture_h(texture_h&& other) noexcept {
*this = std::move(other);
}
texture_h& texture_h::operator=(texture_h&& other) noexcept {
std::swap(handle, other.handle);
return *this;
}
//**********HANDLE: Texture
ADE_OBJ(l_Texture, texture_h, "texture", "Texture handle");
//WMC - int should NEVER EVER be an invalid handle. Return Nil instead. Nil FTW.
ADE_FUNC(__eq, l_Texture, "texture, texture", "Checks if two texture handles refer to the same texture", "boolean", "True if textures are equal")
{
texture_h* th;
texture_h* th2;
if (!ade_get_args(L, "oo", l_Texture.GetPtr(&th), l_Texture.GetPtr(&th2)))
return ADE_RETURN_NIL;
if (th->handle == th2->handle)
return ADE_RETURN_TRUE;
return ADE_RETURN_FALSE;
}
ADE_INDEXER(l_Texture, "number",
"Returns texture handle to specified frame number in current texture's animation."
"This means that [1] will always return the first frame in an animation, no matter what frame an animation is."
"You cannot change a texture animation frame.",
"texture",
"Texture handle, or invalid texture handle if index is invalid")
{
texture_h* th;
int frame=-1;
int newframe=-1; //WMC - Ignore for now
if (!ade_get_args(L, "oi|i", l_Texture.GetPtr(&th), &frame, &newframe))
return ade_set_error(L, "o", l_Texture.Set(texture_h()));
if(frame < 1)
return ade_set_error(L, "o", l_Texture.Set(texture_h()));
if (!th->isValid()) {
return ade_set_error(L, "o", l_Texture.Set(texture_h()));
}
//Get me some info
int num=-1;
int first = bm_get_info(th->handle, nullptr, nullptr, nullptr, &num);
//Check it's a valid one
if(first < 0 || frame > num)
return ade_set_error(L, "o", l_Texture.Set(texture_h()));
frame--; //Lua->FS2
//Get actual texture handle
frame = first + frame;
return ade_set_args(L, "o", l_Texture.Set(texture_h(frame)));
}
ADE_FUNC(isValid, l_Texture, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", th->isValid());
}
ADE_FUNC(unload, l_Texture, NULL, "Unloads a texture from memory", NULL, NULL)
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ADE_RETURN_NIL;
if (!th->isValid())
return ADE_RETURN_NIL;
bm_release(th->handle);
//WMC - invalidate this handle
th->handle = -1;
return ADE_RETURN_NIL;
}
ADE_FUNC(destroyRenderTarget, l_Texture, nullptr, "Destroys a texture's render target. Call this when done drawing to a texture, as it frees up resources.", nullptr, nullptr)
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ADE_RETURN_NIL;
if (!th->isValid())
return ADE_RETURN_NIL;
if (!bm_is_render_target(th->handle)) {
LuaError(L, "Tried to destroy a render target of a non-renderable texture!");
return ADE_RETURN_NIL;
}
bm_release_rendertarget(th->handle);
return ADE_RETURN_NIL;
}
ADE_FUNC(getFilename, l_Texture, NULL, "Returns filename for texture", "string", "Filename, or empty string if handle is invalid")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ade_set_error(L, "s", "");
if (!th->isValid())
return ade_set_error(L, "s", "");
return ade_set_args(L, "s", bm_get_filename(th->handle));
}
ADE_FUNC(getWidth, l_Texture, NULL, "Gets texture width", "number", "Texture width, or 0 if handle is invalid")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ade_set_error(L, "i", 0);
if (!th->isValid())
return ade_set_error(L, "i", 0);
int w = -1;
if (bm_get_info(th->handle, &w) < 0)
return ade_set_error(L, "i", 0);
return ade_set_args(L, "i", w);
}
ADE_FUNC(getHeight, l_Texture, NULL, "Gets texture height", "number", "Texture height, or 0 if handle is invalid")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ade_set_error(L, "i", 0);
if (!th->isValid())
return ade_set_error(L, "i", 0);
int h=-1;
if (bm_get_info(th->handle, nullptr, &h) < 0)
return ade_set_error(L, "i", 0);
return ade_set_args(L, "i", h);
}
ADE_FUNC(getFPS, l_Texture, NULL,"Gets frames-per-second of texture", "number", "Texture FPS, or 0 if handle is invalid")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ade_set_error(L, "i", 0);
if (!th->isValid())
return ade_set_error(L, "i", 0);
int fps=-1;
if (bm_get_info(th->handle, nullptr, nullptr, nullptr, nullptr, &fps) < 0)
return ade_set_error(L, "i", 0);
return ade_set_args(L, "i", fps);
}
ADE_FUNC(getFramesLeft, l_Texture, NULL, "Gets number of frames left, from handle's position in animation", "number", "Frames left, or 0 if handle is invalid")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ADE_RETURN_NIL;
if (!th->isValid())
return ADE_RETURN_NIL;
int num=-1;
if (bm_get_info(th->handle, nullptr, nullptr, nullptr, &num) < 0)
return ade_set_error(L, "i", 0);
return ade_set_args(L, "i", num);
}
ADE_FUNC(getFrame, l_Texture, "number ElapsedTimeSeconds, [boolean Loop]",
"Get the frame number from the elapsed time of the animation<br>"
"The 1st argument is the time that has elapsed since the animation started<br>"
"If 2nd argument is set to true, the animation is expected to loop when the elapsed time exceeds the duration "
"of a single playback",
"number", "Frame number")
{
texture_h* th;
int frame = 0;
float elapsed_time;
bool loop = false;
if (!ade_get_args(L, "of|b", l_Texture.GetPtr(&th), &elapsed_time, &loop))
return ADE_RETURN_NIL;
if (!th->isValid())
return ADE_RETURN_NIL;
frame = bm_get_anim_frame(th->handle, elapsed_time, 0.0f, loop);
frame++; // C++ to LUA array idx
return ade_set_args(L, "i", frame);
}
}
}
|