int NativeDelegate::__op_assignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, true, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } // set the VM, and recreate callbacks table delegate->setVM(L, true); delegate->getCallbacks(L); if (!lua_istable(L, -1)) { LSError("Bad native delegates table"); } // clear current callbacks for (int i = 0; i < delegate->_callbackCount; i++) { lua_pushnumber(L, (double)i); lua_pushnil(L); lua_settable(L, -3); } // reset delegate->_callbackCount = 0; if (lua_isnil(L, 2)) { return 0; } if (!lua_isfunction(L, 2) && !lua_iscfunction(L, 2)) { LSError("Unknown type on NativeDelegate assignment operator"); } // add the lua function or cfunction to our delegate's callback table lua_pushnumber(L, (double)0); lua_pushvalue(L, 2); lua_settable(L, -3); lua_pop(L, 1); // pop __lscallbacks delegate->_callbackCount++; return 0; }
int Assembly::loadBytes(lua_State *L) { utByteArray *bytes = static_cast<utByteArray*>(lualoom_getnativepointer(L, 1, false, "system.ByteArray")); Assembly *assembly = LSLuaState::getExecutingVM(L)->loadExecutableAssemblyBinary(static_cast<const char*>(bytes->getDataPtr()), bytes->getSize()); lmAssert(assembly, "Error loading assembly bytes"); lualoom_pushnative(L, assembly); assembly->freeByteCode(); return 1; }
int NativeDelegate::__op_plusassignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } delegate->setVM(L); delegate->getCallbacks(L); int tidx = lua_gettop(L); if (!lua_istable(L, -1)) { LSError("Bad native delegates table"); } if (lua_isfunction(L, 2) || lua_iscfunction(L, 2)) { // check if we already added this callback for (int i = 0; i < delegate->_callbackCount; i++) { lua_rawgeti(L, tidx, i); if (lua_equal(L, 2, -1)) { lua_pop(L, 1); return 0; // already added } lua_pop(L, 1); } // add the lua function or cfunction to our delegate's callback table lua_pushnumber(L, (double)delegate->_callbackCount++); lua_pushvalue(L, 2); lua_settable(L, -3); lua_pop(L, 1); // pop __lscallbacks } else { LSError("Unknown type on NativeDelegate += operator"); } return 0; }
int NativeDelegate::__op_minusassignment(lua_State *L) { NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1, "system.NativeDelegate"); if (!delegate) { LSError("Unable to get native delegate on += operator"); } if (!delegate->_callbackCount) { return 0; } delegate->setVM(L); delegate->getCallbacks(L); int tidx = lua_gettop(L); if (!lua_istable(L, tidx)) { LSError("Bad native delegates table"); } if (lua_isfunction(L, 2) || lua_iscfunction(L, 2)) { int idx = -1; for (int i = 0; i < delegate->_callbackCount; i++) { lua_rawgeti(L, tidx, i); if (lua_equal(L, 2, -1)) { idx = i; lua_pop(L, 1); break; } lua_pop(L, 1); } // this function was never added in the first place if (idx == -1) { return 0; } // shift the other delegates down lua_pushnumber(L, (double)idx); lua_pushnil(L); lua_settable(L, tidx); int ntable = 0; if (delegate->_callbackCount > 1) { // temp table lua_newtable(L); ntable = lua_gettop(L); int c = 0; for (int nidx = 0; nidx < delegate->_callbackCount; nidx++) { lua_pushnumber(L, (double)nidx); lua_gettable(L, tidx); if (lua_isnil(L, -1)) { lua_pop(L, 1); continue; } lua_pushnumber(L, (double)c); lua_pushvalue(L, -2); lua_settable(L, ntable); // pop lua_function lua_pop(L, 1); c++; } } // clear it delegate->_callbackCount--; // and copy from new temp table for (int nidx = 0; nidx < delegate->_callbackCount; nidx++) { lua_pushnumber(L, (double)nidx); lua_pushnumber(L, (double)nidx); lua_gettable(L, ntable); lua_settable(L, tidx); } } else { LSError("Unknown type on NativeDelegate -= operator"); } return 0; }
void DisplayObjectContainer::renderChildren(lua_State *L) { if (!visible) { return; } // containers can set a new view to render into, but we must restore the // current view after, so take a snapshot int viewRestore = GFX::Graphics::getView(); // set the current view we will be rendering into. if (viewRestore != _view) { GFX::Graphics::setView(_view); } renderState.alpha = parent ? parent->renderState.alpha * alpha : alpha; renderState.cachedClipRect = parent ? parent->renderState.cachedClipRect : (unsigned short)-1; int docidx = lua_gettop(L); lua_rawgeti(L, docidx, (int)childrenOrdinal); lua_rawgeti(L, -1, LSINDEXVECTOR); int childrenVectorIdx = lua_gettop(L); int numChildren = lsr_vector_get_length(L, -2); if (_depthSort && ((int)sSortBucket.size() < numChildren)) { sSortBucket.resize(numChildren); } // Is there a cliprect? If so, set it. if ((clipX != 0) || (clipY != 0) || (clipWidth != 0) || (clipHeight != 0)) { GFX::QuadRenderer::submit(); Matrix res; DisplayObject *stage = this; while (stage->parent) { stage = stage->parent; } getTargetTransformationMatrix(NULL, &res); int x1 = (int) ((float)clipX * res.a + res.tx) ; int y1 = (int) ((float)clipY * res.d + res.ty); int x2 = (int) ((float)clipWidth * res.a); int y2 = (int) ((float)clipHeight * res.d); renderState.cachedClipRect = GFX::Graphics::setClipRect(x1, y1, x2, y2); } else { GFX::Graphics::setClipRect(renderState.cachedClipRect); } for (int i = 0; i < numChildren; i++) { lua_rawgeti(L, childrenVectorIdx, i); DisplayObject *dobj = (DisplayObject *)lualoom_getnativepointer(L, -1); lua_rawgeti(L, -1, LSINDEXTYPE); dobj->type = (Type *)lua_topointer(L, -1); lua_pop(L, 1); dobj->validate(L, lua_gettop(L)); if (!_depthSort) { renderType(L, dobj->type, dobj); } else { sSortBucket[i].index = i; sSortBucket[i].displayObject = dobj; } // pop instance lua_pop(L, 1); } if (_depthSort) { qsort(sSortBucket.ptr(), numChildren, sizeof(DisplayObjectSort), DisplayObjectSortFunction); for (int i = 0; i < numChildren; i++) { DisplayObjectSort *ds = &sSortBucket[i]; lua_rawgeti(L, childrenVectorIdx, ds->index); renderType(L, ds->displayObject->type, ds->displayObject); // pop instance lua_pop(L, 1); } } lua_settop(L, docidx); // Restore clip state. if ((clipX != 0) || (clipY != 0) || (clipWidth != 0) || (clipHeight != 0)) { GFX::QuadRenderer::submit(); GFX::Graphics::clearClipRect(); } // restore view if (viewRestore != _view) { GFX::Graphics::setView(viewRestore); } }
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; } }