MonoObject* ScriptTextureCube::internal_getPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel) { HTexture texture = thisPtr->getHandle(); SPtr<PixelData> pixelData = texture->getProperties().allocBuffer(face, mipLevel); texture->readCachedData(*pixelData, face, mipLevel); return ScriptPixelData::create(pixelData); }
void ScriptTextureCube::internal_setPixels(ScriptTextureCube* thisPtr, MonoObject* data, UINT32 face, UINT32 mipLevel) { ScriptPixelData* scriptPixelData = ScriptPixelData::toNative(data); if (scriptPixelData != nullptr) { HTexture texture = thisPtr->getHandle(); texture->writeData(scriptPixelData->getInternalValue(), face, mipLevel, false); } }
RenderTextureProperties::RenderTextureProperties(const RENDER_TEXTURE_DESC& desc, bool requiresFlipping) { HTexture texture = desc.colorSurface.texture; if (texture.isLoaded()) { const TextureProperties& props = texture->getProperties(); construct(&props, requiresFlipping); } else construct(nullptr, requiresFlipping); }
void ScriptRenderTexture2D::internal_create(MonoObject* instance, MonoArray* colorSurfaces, ScriptTexture* depthStencilSurface) { ScriptArray colorSurfacesList(colorSurfaces); RENDER_SURFACE_DESC depthStencilSurfaceDesc; if (depthStencilSurface != nullptr) { depthStencilSurfaceDesc.face = 0; depthStencilSurfaceDesc.mipLevel = 0; depthStencilSurfaceDesc.numFaces = 1; HTexture textureHandle = depthStencilSurface->getHandle(); if (!textureHandle.isLoaded()) { LOGERR("Render texture must be created using a fully loaded texture."); } else depthStencilSurfaceDesc.texture = textureHandle; } UINT32 numSurfaces = std::min(colorSurfacesList.size(), (UINT32)BS_MAX_MULTIPLE_RENDER_TARGETS); RENDER_TEXTURE_DESC desc; for (UINT32 i = 0; i < numSurfaces; i++) { RENDER_SURFACE_DESC surfaceDesc; surfaceDesc.face = 0; surfaceDesc.mipLevel = 0; surfaceDesc.numFaces = 1; ScriptTexture* scriptSurface = colorSurfacesList.get<ScriptTexture*>(i); if (scriptSurface != nullptr) { HTexture textureHandle = scriptSurface->getHandle(); if (!textureHandle.isLoaded()) { LOGERR("Render texture must be created using a fully loaded texture."); } else surfaceDesc.texture = textureHandle; } desc.colorSurfaces[i] = surfaceDesc; } desc.depthStencilSurface = depthStencilSurfaceDesc; SPtr<RenderTarget> tex = RenderTexture::create(desc); new (bs_alloc<ScriptRenderTexture2D>()) ScriptRenderTexture2D(tex, instance); }
MonoObject* ScriptSpriteTexture::internal_GetTexture(ScriptSpriteTexture* thisPtr) { HSpriteTexture spriteTexture = thisPtr->getHandle(); if (!spriteTexture.isLoaded()) return nullptr; HTexture texture = spriteTexture->getTexture(); if (!texture.isLoaded()) return nullptr; ScriptTexture2D* scriptTexture = nullptr; ScriptResourceManager::instance().getScriptResource(texture, &scriptTexture, true); return scriptTexture->getManagedInstance(); }
MultiRenderTextureProperties::MultiRenderTextureProperties(const MULTI_RENDER_TEXTURE_DESC& desc) { for (size_t i = 0; i < desc.colorSurfaces.size(); i++) { HTexture texture = desc.colorSurfaces[i].texture; if (texture != nullptr) { const TextureProperties& texProps = texture->getProperties(); construct(&texProps); break; } } }
MonoObject* ScriptTextureCube::internal_getGPUPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel) { HTexture texture = thisPtr->getHandle(); SPtr<PixelData> readData = texture->getProperties().allocBuffer(face, mipLevel); AsyncOp asyncOp = texture->readData(readData, face, mipLevel); std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono = [&](const AsyncOp& op, const SPtr<PixelData>& returnValue) { return ScriptPixelData::create(returnValue); }; return ScriptAsyncOp::create(asyncOp, std::bind(asyncOpToMono, _1, readData)); }
void ScriptTexture::internal_getMipmapCount(ScriptTexture* thisPtr, int* value) { HTexture texture = static_resource_cast<Texture>(thisPtr->getGenericHandle()); *value = (TextureUsage)texture->getProperties().getNumMipmaps(); }
void ScriptTexture::internal_getGammaCorrection(ScriptTexture* thisPtr, bool* value) { HTexture texture = static_resource_cast<Texture>(thisPtr->getGenericHandle()); *value = (TextureUsage)texture->getProperties().isHardwareGammaEnabled(); }
void ScriptTexture::internal_getPixelFormat(ScriptTexture* thisPtr, PixelFormat* value) { HTexture texture = static_resource_cast<Texture>(thisPtr->getGenericHandle()); *value = texture->getProperties().getFormat(); }
void ScriptRenderTexture2D::internal_create(MonoObject* instance, MonoArray* colorSurfaces, MonoObject* depthStencilSurface) { ScriptArray colorSurfacesList(colorSurfaces); RENDER_SURFACE_DESC depthStencilSurfaceDesc; ScriptTexture2D* scriptDepthStencilSurface = ScriptTexture2D::toNative(depthStencilSurface); if (scriptDepthStencilSurface != nullptr) { depthStencilSurfaceDesc.face = 0; depthStencilSurfaceDesc.mipLevel = 0; depthStencilSurfaceDesc.numFaces = 1; HTexture textureHandle = scriptDepthStencilSurface->getHandle(); if (!textureHandle.isLoaded()) { LOGERR("Render texture must be created using a fully loaded texture."); } else depthStencilSurfaceDesc.texture = textureHandle; } SPtr<RenderTarget> tex; UINT32 numSurfaces = colorSurfacesList.size(); bool isMulti = numSurfaces > 1; if (isMulti) { MULTI_RENDER_TEXTURE_DESC desc; for (UINT32 i = 0; i < numSurfaces; i++) { RENDER_SURFACE_DESC surfaceDesc; surfaceDesc.face = 0; surfaceDesc.mipLevel = 0; surfaceDesc.numFaces = 1; MonoObject* surfaceObj = colorSurfacesList.get<MonoObject*>(i); ScriptTexture2D* scriptSurface = ScriptTexture2D::toNative(surfaceObj); if (scriptSurface != nullptr) { HTexture textureHandle = scriptSurface->getHandle(); if (!textureHandle.isLoaded()) { LOGERR("Render texture must be created using a fully loaded texture."); } else surfaceDesc.texture = textureHandle; } desc.colorSurfaces.push_back(surfaceDesc); } desc.depthStencilSurface = depthStencilSurfaceDesc; tex = MultiRenderTexture::create(desc); } else { RENDER_SURFACE_DESC surfaceDesc; surfaceDesc.face = 0; surfaceDesc.mipLevel = 0; surfaceDesc.numFaces = 1; if (colorSurfacesList.size() > 0) { MonoObject* surfaceObj = colorSurfacesList.get<MonoObject*>(0); ScriptTexture2D* scriptSurface = ScriptTexture2D::toNative(surfaceObj); if (scriptSurface != nullptr) { HTexture textureHandle = scriptSurface->getHandle(); if (!textureHandle.isLoaded()) { LOGERR("Render texture must be created using a fully loaded texture."); } else surfaceDesc.texture = textureHandle; } } RENDER_TEXTURE_DESC desc; desc.colorSurface = surfaceDesc; desc.depthStencilSurface = depthStencilSurfaceDesc; tex = RenderTexture::create(desc); } new (bs_alloc<ScriptRenderTexture2D>()) ScriptRenderTexture2D(tex, isMulti, instance); }
BuiltinResources::BuiltinResources() { // Set up paths mBuiltinRawDataFolder = Paths::getDataPath() + u8"Raw/"; mBuiltinDataFolder = Paths::getDataPath(); mEngineSkinSpritesFolder = mBuiltinDataFolder + SKIN_FOLDER + SPRITE_FOLDER; mEngineShaderFolder = mBuiltinDataFolder + SHADER_FOLDER; mEngineMeshFolder = mBuiltinDataFolder + MESH_FOLDER; mEngineCursorFolder = mBuiltinDataFolder + CURSOR_FOLDER; ResourceManifestPath = mBuiltinDataFolder + "ResourceManifest.asset"; // Update from raw assets if needed if (FileSystem::exists(mBuiltinRawDataFolder)) { time_t lastUpdateTime; UINT32 modifications = BuiltinResourcesHelper::checkForModifications( mBuiltinRawDataFolder, mBuiltinDataFolder + u8"Timestamp.asset", lastUpdateTime); // Check if manifest needs to be rebuilt if (modifications == 0 && !FileSystem::exists(ResourceManifestPath)) modifications = 1; if (modifications > 0) { bool fullReimport = modifications == 2; SPtr<ResourceManifest> oldResourceManifest; if (!fullReimport && FileSystem::exists(ResourceManifestPath)) { oldResourceManifest = ResourceManifest::load(ResourceManifestPath, mBuiltinDataFolder); if (oldResourceManifest != nullptr) gResources().registerResourceManifest(oldResourceManifest); } if (oldResourceManifest) mResourceManifest = oldResourceManifest; else { mResourceManifest = ResourceManifest::create("BuiltinResources"); gResources().registerResourceManifest(mResourceManifest); } preprocess(fullReimport, lastUpdateTime); BuiltinResourcesHelper::writeTimestamp(mBuiltinDataFolder + u8"Timestamp.asset"); ResourceManifest::save(mResourceManifest, ResourceManifestPath, mBuiltinDataFolder); } } // Load manifest if (mResourceManifest == nullptr) { if (FileSystem::exists(ResourceManifestPath)) mResourceManifest = ResourceManifest::load(ResourceManifestPath, mBuiltinDataFolder); if (mResourceManifest == nullptr) mResourceManifest = ResourceManifest::create("BuiltinResources"); gResources().registerResourceManifest(mResourceManifest); } if (FileSystem::exists(mBuiltinRawDataFolder)) { // Update shader bytecode for the current render backend, if needed const RenderAPIInfo& apiInfo = ct::RenderAPI::instance().getAPIInfo(); bool supportsBytecodeCaching = apiInfo.isFlagSet(RenderAPIFeatureFlag::ByteCodeCaching); if (supportsBytecodeCaching) { Path dataListsFilePath = mBuiltinRawDataFolder + DATA_LIST_JSON; SPtr<DataStream> dataListStream = FileSystem::openFile(dataListsFilePath); if (dataListStream) { json dataListJSON = json::parse(dataListStream->getAsString().c_str()); json shadersJSON = dataListJSON["Shaders"]; for (auto& entry : shadersJSON) { std::string uuidStr = entry["UUID"]; UUID uuid(uuidStr.c_str()); Path filePath; if (!mResourceManifest->uuidToFilePath(uuid, filePath)) continue; BuiltinResourcesHelper::updateShaderBytecode(filePath); } } } } // Load basic resources mShaderSpriteText = getShader(ShaderSpriteTextFile); mShaderSpriteImage = getShader(ShaderSpriteImageAlphaFile); mShaderSpriteNonAlphaImage = getShader(ShaderSpriteImageNoAlphaFile); mShaderSpriteLine = getShader(ShaderSpriteLineFile); mShaderDiffuse = getShader(ShaderDiffuseFile); mShaderTransparent = getShader(ShaderTransparentFile); mShaderParticlesUnlit = getShader(ShaderParticlesUnlitFile); SPtr<PixelData> dummyPixelData = PixelData::create(2, 2, 1, PF_RGBA8); dummyPixelData->setColorAt(Color::Red, 0, 0); dummyPixelData->setColorAt(Color::Red, 0, 1); dummyPixelData->setColorAt(Color::Red, 1, 0); dummyPixelData->setColorAt(Color::Red, 1, 1); mDummyTexture = Texture::create(dummyPixelData); mWhiteSpriteTexture = getSkinTexture(WhiteTex); mDummySpriteTexture = SpriteTexture::create(mDummyTexture); mFont = gResources().load<Font>(mBuiltinDataFolder + (DefaultFontFilename + u8".asset")); mSkin = gResources().load<GUISkin>(mBuiltinDataFolder + (GUISkinFile + u8".asset")); mEmptySkin = GUISkin::create(); /************************************************************************/ /* CURSOR */ /************************************************************************/ HTexture cursorArrowTex = getCursorTexture(CursorArrowTex); HTexture cursorArrowDragTex = getCursorTexture(CursorArrowDragTex); HTexture cursorArrowLeftRightTex = getCursorTexture(CursorArrowLeftRightTex); HTexture cursorIBeamTex = getCursorTexture(CursorIBeamTex); HTexture cursorDenyTex = getCursorTexture(CursorDenyTex); HTexture cursorWaitTex = getCursorTexture(CursorWaitTex); HTexture cursorSizeNESWTex = getCursorTexture(CursorSizeNESWTex); HTexture cursorSizeNSTex = getCursorTexture(CursorSizeNSTex); HTexture cursorSizeNWSETex = getCursorTexture(CursorSizeNWSETex); HTexture cursorSizeWETex = getCursorTexture(CursorSizeWETex); mCursorArrow = cursorArrowTex->getProperties().allocBuffer(0, 0); cursorArrowTex->readData(mCursorArrow); mCursorArrowDrag = cursorArrowDragTex->getProperties().allocBuffer(0, 0); cursorArrowDragTex->readData(mCursorArrowDrag); mCursorArrowLeftRight = cursorArrowLeftRightTex->getProperties().allocBuffer(0, 0); cursorArrowLeftRightTex->readData(mCursorArrowLeftRight); mCursorIBeam = cursorIBeamTex->getProperties().allocBuffer(0, 0); cursorIBeamTex->readData(mCursorIBeam); mCursorDeny = cursorDenyTex->getProperties().allocBuffer(0, 0); cursorDenyTex->readData(mCursorDeny); mCursorWait = cursorWaitTex->getProperties().allocBuffer(0, 0); cursorWaitTex->readData(mCursorWait); mCursorSizeNESW = cursorSizeNESWTex->getProperties().allocBuffer(0, 0); cursorSizeNESWTex->readData(mCursorSizeNESW); mCursorSizeNS = cursorSizeNSTex->getProperties().allocBuffer(0, 0); cursorSizeNSTex->readData(mCursorSizeNS); mCursorSizeNWSE = cursorSizeNWSETex->getProperties().allocBuffer(0, 0); cursorSizeNWSETex->readData(mCursorSizeNWSE); mCursorSizeWE = cursorSizeWETex->getProperties().allocBuffer(0, 0); cursorSizeWETex->readData(mCursorSizeWE); /************************************************************************/ /* ICON */ /************************************************************************/ Path iconPath = mBuiltinDataFolder + ICON_FOLDER; iconPath.append(String(IconTextureName) + u8".asset"); HTexture iconTex = gResources().load<Texture>(iconPath); mFrameworkIcon = iconTex->getProperties().allocBuffer(0, 0); iconTex->readData(mFrameworkIcon); gCoreThread().submit(true); }
void BuiltinEditorResources::preprocess(bool forceImport, time_t lastUpdateTime) { Resources::instance().unloadAllUnused(); Path dataListsFilePath = BuiltinRawDataFolder + DATA_LIST_JSON; SPtr<DataStream> dataListStream = FileSystem::openFile(dataListsFilePath); json dataListJSON = json::parse(dataListStream->getAsString().c_str()); json skinJSON = dataListJSON["Skin"]; json iconsJSON = dataListJSON["Icons"]; json includesJSON = dataListJSON["Includes"]; json shadersJSON = dataListJSON["Shaders"]; // Update DataList.json if needed bool updatedDataLists = false; updatedDataLists |= BuiltinResourcesHelper::updateJSON( EditorRawIconsFolder, BuiltinResourcesHelper::AssetType::Sprite, iconsJSON); updatedDataLists |= BuiltinResourcesHelper::updateJSON( EditorRawShaderIncludeFolder, BuiltinResourcesHelper::AssetType::Normal, includesJSON); updatedDataLists |= BuiltinResourcesHelper::updateJSON( EditorRawShaderFolder, BuiltinResourcesHelper::AssetType::Normal, shadersJSON); updatedDataLists |= BuiltinResourcesHelper::updateJSON( EditorRawSkinFolder, BuiltinResourcesHelper::AssetType::Sprite, skinJSON); dataListStream->close(); if (updatedDataLists) { FileSystem::remove(dataListsFilePath); dataListJSON["Skin"] = skinJSON; dataListJSON["Icons"] = iconsJSON; dataListJSON["Includes"] = includesJSON; dataListJSON["Shaders"] = shadersJSON; String jsonString = dataListJSON.dump(4).c_str(); dataListStream = FileSystem::createAndOpenFile(dataListsFilePath); dataListStream->writeString(jsonString); dataListStream->close(); } // If forcing import, clear all data folders since everything will be recreated anyway Path shaderDependenciesFile = BuiltinDataFolder + "ShaderDependencies.json"; if(forceImport) { FileSystem::remove(EditorIconFolder); FileSystem::remove(EditorShaderIncludeFolder); FileSystem::remove(EditorShaderFolder); FileSystem::remove(EditorSkinFolder); FileSystem::remove(shaderDependenciesFile); } // Read shader dependencies JSON json shaderDependenciesJSON; if(FileSystem::exists(shaderDependenciesFile)) { SPtr<DataStream> stream = FileSystem::openFile(shaderDependenciesFile); shaderDependenciesJSON = json::parse(stream->getAsString().c_str()); stream->close(); } // Import icons { BuiltinResourcesHelper::updateManifest( EditorIconFolder, iconsJSON, mResourceManifest, BuiltinResourcesHelper::AssetType::Sprite); Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags( iconsJSON, EditorRawIconsFolder, lastUpdateTime, forceImport); BuiltinResourcesHelper::importAssets( iconsJSON, importFlags, EditorRawIconsFolder, EditorIconFolder, mResourceManifest, BuiltinResourcesHelper::AssetType::Sprite); } // Import shaders { BuiltinResourcesHelper::updateManifest( EditorShaderIncludeFolder, includesJSON, mResourceManifest, BuiltinResourcesHelper::AssetType::Normal); BuiltinResourcesHelper::updateManifest( EditorShaderFolder, shadersJSON, mResourceManifest, BuiltinResourcesHelper::AssetType::Normal); Vector<bool> includeImportFlags = BuiltinResourcesHelper::generateImportFlags( includesJSON, EditorRawShaderIncludeFolder, lastUpdateTime, forceImport); Vector<bool> shaderImportFlags = BuiltinResourcesHelper::generateImportFlags( shadersJSON, EditorRawShaderFolder, lastUpdateTime, forceImport, &shaderDependenciesJSON, EditorRawShaderIncludeFolder); // Hidden dependency: Includes must be imported before shaders, but import flags for shaders must be generated // before includes are imported, since the process checks if imports changed BuiltinResourcesHelper::importAssets( includesJSON, includeImportFlags, EditorRawShaderIncludeFolder, EditorShaderIncludeFolder, mResourceManifest, BuiltinResourcesHelper::AssetType::Normal); BuiltinResourcesHelper::importAssets( shadersJSON, shaderImportFlags, EditorRawShaderFolder, EditorShaderFolder, mResourceManifest, BuiltinResourcesHelper::AssetType::Normal, &shaderDependenciesJSON); } // Import GUI sprites { BuiltinResourcesHelper::updateManifest( EditorSkinFolder, skinJSON, mResourceManifest, BuiltinResourcesHelper::AssetType::Sprite); Vector<bool> includeImportFlags = BuiltinResourcesHelper::generateImportFlags( skinJSON, EditorRawSkinFolder, lastUpdateTime, forceImport); BuiltinResourcesHelper::importAssets( skinJSON, includeImportFlags, EditorRawSkinFolder, EditorSkinFolder, mResourceManifest, BuiltinResourcesHelper::AssetType::Sprite); } // Update shader dependencies JSON { String jsonString = shaderDependenciesJSON.dump(4).c_str(); dataListStream = FileSystem::createAndOpenFile(shaderDependenciesFile); dataListStream->writeString(jsonString); dataListStream->close(); } // Import fonts BuiltinResourcesHelper::importFont( BuiltinRawDataFolder + DefaultFontFilename, DefaultFontFilename, BuiltinDataFolder, { DefaultFontSize }, true, UUID("6ce69053-00d7-4c60-a229-249b8d8fd60e"), mResourceManifest); BuiltinResourcesHelper::importFont( BuiltinRawDataFolder + DefaultFontFilename, DefaultAAFontFilename, BuiltinDataFolder, { TitleFontSize }, true, UUID("10999b74-d976-4116-9f72-21e489a7a8e4"), mResourceManifest); // Import splash screen { Path inputPath = BuiltinRawDataFolder + String(SplashScreenName); Path outputPath = BuiltinDataFolder + (String(SplashScreenName) + ".asset"); auto textureIO = gImporter().createImportOptions<TextureImportOptions>(inputPath); textureIO->setCPUCached(true); textureIO->setGenerateMipmaps(false); HTexture splashTexture = gImporter().import<Texture>(inputPath, textureIO); SPtr<PixelData> splashPixelData = splashTexture->getProperties().allocBuffer(0, 0); splashTexture->readCachedData(*splashPixelData); FileEncoder fe(outputPath); fe.encode(splashPixelData.get()); } // Generate & save GUI skin { SPtr<GUISkin> skin = generateGUISkin(); Path outputPath = BuiltinDataFolder + (GUISkinFile + ".asset"); HResource skinResource = gResources()._createResourceHandle(skin, UUID("ec0ea68d-efa5-4a3b-a6fc-b15aaec9689f")); gResources().save(skinResource, outputPath, true); mResourceManifest->registerResource(skinResource.getUUID(), outputPath); } Resources::instance().unloadAllUnused(); }