const char *lsr_objecttostring(lua_State *L, int index) { index = lua_absindex(L, index); if (lua_isstring(L, index)) { return lua_tostring(L, index); } if (lua_isnumber(L, index)) { static char nbuffer[1024]; snprintf(nbuffer, 1024, "%f", lua_tonumber(L, 1)); return nbuffer; } if (lua_isboolean(L, index)) { return lua_toboolean(L, index) ? "true" : "false"; } if (lua_isfunction(L, index) || lua_iscfunction(L, index)) { lua_rawgeti(L, LUA_GLOBALSINDEX, LSINDEXMETHODLOOKUP); lua_pushvalue(L, 1); lua_rawget(L, -2); if (lua_isnil(L, -1)) { lua_pop(L, 2); // anonymous function return "system.Function"; } MethodBase *methodBase = (MethodBase *)lua_topointer(L, -1); lua_pop(L, 2); return methodBase->getStringSignature().c_str(); } if (lua_isnil(L, index)) { return "null"; } lualoom_getmember(L, index, "toString"); lua_call(L, 0, 1); const char *sreturn = lua_tostring(L, -1); lua_pop(L, 1); return sreturn; }
void DisplayObject::render(lua_State *L) { // Disable reentrancy for this function (read: don't cache to texture while caching to a texture) if (cacheAsBitmapInProgress) return; // Clear and free the cached image if the conditions apply if ((!cacheAsBitmap || !cacheAsBitmapValid) && cachedImage != NULL) { Quad* quad = static_cast<Quad*>(cachedImage); lmAssert(quad != NULL, "Cached image is invalid"); GFX::Texture::dispose(quad->getNativeTextureID()); quad->setNativeTextureID(-1); lmDelete(NULL, quad); cachedImage = NULL; cacheAsBitmapValid = false; } // Cache the contents into an image if the conditions apply if (cacheAsBitmap && !cacheAsBitmapValid && cachedImage == NULL) { cacheAsBitmapInProgress = true; // Used for displaying the texture Quad* quad = lmNew(NULL) Quad(); // Setup for getmember lualoom_pushnative<DisplayObject>(L, this); // Push function and arguments lualoom_getmember(L, -1, "getBounds"); lualoom_pushnative<DisplayObject>(L, this); lua_pushnil(L); // Call getBounds lua_call(L, 2, 1); // Returned result Loom2D::Rectangle *bounds = (Loom2D::Rectangle*) lualoom_getnativepointer(L, -1); cacheAsBitmapOffsetX = bounds->x; cacheAsBitmapOffsetY = bounds->y; lmscalar fracWidth = bounds->width; lmscalar fracHeight = bounds->height; // pop bounds Rectangle and the DisplayObject at the top lua_pop(L, 1+1); if (cacheApplyScale) { fracWidth *= scaleX; fracHeight *= scaleY; } // Convert to integers for the following math int texWidthI = static_cast<int>(ceil(fracWidth)); int texHeightI = static_cast<int>(ceil(fracHeight)); // Calculate power of 2 sizes if (cacheUseTexturesPot) { _UT_UTHASHTABLE_POW2(texWidthI); _UT_UTHASHTABLE_POW2(texHeightI); } // Calculate the resulting scale (as a consequence of pow2 sizes) // Used for 'trans' matrix lmscalar calcScaleX = texWidthI / bounds->width; lmscalar calcScaleY = texHeightI / bounds->height; // Setup texture TextureInfo *tinfo = Texture::initEmptyTexture(texWidthI, texHeightI); Texture::clear(tinfo->id, 0x000000, 0); tinfo->smoothing = TEXTUREINFO_SMOOTHING_BILINEAR; tinfo->wrapU = TEXTUREINFO_WRAP_CLAMP; tinfo->wrapV = TEXTUREINFO_WRAP_CLAMP; TextureID id = tinfo->id; // Setup quad for rendering the texture quad->setNativeTextureID(id); VertexPosColorTex* qv; qv = &quad->quadVertices[0]; qv->x = 0; qv->y = 0; qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 0; qv->v = 0; qv = &quad->quadVertices[1]; qv->x = (float)bounds->width; qv->y = 0; qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 1; qv->v = 0; qv = &quad->quadVertices[2]; qv->x = 0; qv->y = (float)bounds->height; qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 0; qv->v = 1; qv = &quad->quadVertices[3]; qv->x = (float)bounds->width; qv->y = (float)bounds->height; qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 1; qv->v = 1; quad->setNativeVertexDataInvalid(false); lmAssert(Texture::getRenderTarget() == -1, "Unsupported render target state: %d", Texture::getRenderTarget()); // Set render target to texture Texture::setRenderTarget(id); // Shift the contents down and to the right so that the elements extending // past the left and top edges don't get cut off, ignore other existing transforms Matrix trans; trans.translate(-cacheAsBitmapOffsetX, -cacheAsBitmapOffsetY); trans.scale(calcScaleX, calcScaleY); // Setup for Graphics::render lualoom_pushnative<DisplayObject>(L, this); lualoom_pushnative<Matrix>(L, &trans); lua_pushnumber(L, 1); // Render the contents into the texture Graphics::render(L); // Pop previous arguments lua_pop(L, 3); // Restore render target Texture::setRenderTarget(-1); // Set valid cached state cachedImage = quad; cacheAsBitmapValid = true; cacheAsBitmapInProgress = false; } }