#include "AdeptHeaders.hpp" #include "ResourceImagePool.hpp" #include "Application.hpp" #include "Tool.hpp" #include "VideoRenderer.hpp" #include #include using MidLevelRenderer::GOSImage; #define SUPPORT_TGA #define SUPPORT_PNG #if 1 #define TEXTURE_LOAD(string) LOG_BLOCK("Texture Load::" string) #else #define TEXTURE_LOAD(string) #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Compost::FetchTextureData(Compost::Feature_Texture *tex, int index, int type) { return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Compost::FetchTextureData(Compost::Feature_Texture *tex, const char *name, int type) { Verify(gos_GetCurrentHeap() == Heap); MString fname(name); fname += ".bid"; fname.ToLower(); FileStream hFile(fname); int size = tex->RecalculateSize(); tex->data = new BYTE [size]; tex->dataSize = size; if(size != hFile.GetBytesRemaining()) { STOP(("Length of BID-file %s incorrect", name)); } hFile.ReadBytes(tex->data, size); return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Compost::DestroyTextureData(Compost::Feature_Texture *tex) { delete [] tex->data; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DWORD ResourceImagePool::FindTexture( const char* tex_name, int hint ) { Check_Pointer(tex_name); TEXTURE_LOAD("Find Texture"); // //---------------------------------------------- // Put the texture directory on the texture name //---------------------------------------------- // MString file_name = "content\\textures\\"; file_name += tex_name; file_name += ".tga"; // //--------------------------------------------- // Loop through testing for each extension type //--------------------------------------------- // #if defined(SUPPORT_PNG) char* ext_pointer = static_cast(file_name) + file_name.GetLength()-3; do { #endif // //------------------------------------------------------------------- // If we can find a texture matching the name, check to see if it has // explicit mipmaps. If so, we need to secretly reroute to a texture // given by the bias //------------------------------------------------------------------- // bool exists; { Resource texture_stream(file_name); exists = texture_stream.DoesResourceExist(); } if (exists) { int hint_flags; Resource hint_stream(MString(file_name)+"{hint}"); Verify(hint_stream.DoesResourceExist()); hint_stream.LoadData(); hint_stream >> hint_flags; if (Environment.bitDepth == 32) hint_flags |= gosHint_Try32bpp; hint_stream.UnloadData(); if (hint_flags & gosHint_UserMipMaps) { int bias = hint_flags >> 24; bias = VideoRenderer::s_MipBias + bias; Min_Clamp(bias, 0); int len = strlen(file_name)-5; file_name[len] = static_cast(file_name[len] + bias); Max_Clamp(file_name[len], '5'); } char format = static_cast(hint_flags>>16); hint_flags &= 0xffff; DWORD texture_handle = gos_NewTextureFromFile( static_cast(format), file_name, hint_flags|hint ); // //-------------------------------------------- // If we want this in video memory, preload it //-------------------------------------------- // if ((hint_flags & (gosHint_AGPMemory|gosHint_VideoMemory)) == gosHint_VideoMemory) gos_PreloadTexture(texture_handle); return texture_handle; } // //-------------------------------------------------------------------- // We couldn't find the resource, so try the actual file. If the hint // says to use explicit mipmaps, bump the number by the bias //-------------------------------------------------------------------- // else { if (hint & gosHint_UserMipMaps) { int len = strlen(file_name)-5; Verify(file_name[len] == '0'); file_name[len] = static_cast(file_name[len] + VideoRenderer::s_MipBias); } // //----------------------------- // See if the file can be found //----------------------------- // if (gos_DoesFileExist(file_name)) { #ifdef LAB_ONLY PAUSE(("[%s] is NOT in resources but found on disc.", tex_name)); #endif if (FileStream::IsRedirected) { FileStream::IsRedirected = false; return gos_NewTextureFromFile( gos_Texture_Detect, FileStream::RedirectedName, hint ); } else { return gos_NewTextureFromFile( gos_Texture_Detect, file_name, hint ); } } #ifdef LAB_ONLY else { PAUSE(("[%s] is NOT in resources and NOT on disc.", tex_name)); } #endif Verify(!FileStream::IsRedirected); } // //---------------------------------------------------------------- // Stop the loop if the png doesn't exist or if we found our image //---------------------------------------------------------------- // #if defined(SUPPORT_PNG) if (ext_pointer[0]=='p') break; // //--------------------------- // roll to the next extension //--------------------------- // ext_pointer[0]='p'; ext_pointer[1]='n'; ext_pointer[2]='g'; Verify(!ext_pointer[3]); } while (true); #endif return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ResourceImagePool::LoadImageGOS(GOSImage *image, int hint) { // //---------------------------------------- // If the image is already loaded, we done //---------------------------------------- // TEXTURE_LOAD("Load Image"); if ( (image->flags & GOSImage::Loaded) != 0) return true; // //----------------------------------------------------------------- // if the image name starts with an underscore, it requires special // treatment. Two underscores mean no skin, so just remove the // first underscore //----------------------------------------------------------------- // const char* tex_name = image->imageName; if (tex_name[1] == g_SkinSignal) { if (*tex_name == g_SkinSignal) ++tex_name; // //------------------------------------------------------------------- // If we get here, then we must synthesize this new texture rather // than using something directly from the resources. We will have to // open up both the specified file and a skin file and mix them //------------------------------------------------------------------- // else { TEXTURE_LOAD("Load Image::Composite Skin"); static char skin[7] = "skin 0"; skin[4] = *tex_name; // //--------------------------------------------------------------- // We've got the names of both textures now, next we need to have // gos open them up for us //--------------------------------------------------------------- // DWORD skin_handle = FindTexture(skin, gosHint_DisableMipmap|gosHint_DontShrink); if(skin_handle==0) { STOP((0, "Skin: %s not found !", skin)); } DWORD detail_handle = FindTexture(tex_name+1, gosHint_DisableMipmap|gosHint_DontShrink); if(detail_handle==0) { STOP((0, "Skindetail: %s not found !", tex_name+1)); } image->imageHandle = SkinThis(tex_name, gos_Texture_Solid, skin_handle, detail_handle); gos_DestroyTexture(detail_handle); gos_DestroyTexture(skin_handle); image->flags |= (image->imageHandle ? GOSImage::Loaded : 0); return ( (image->flags & GOSImage::Loaded) != 0); } } // //-------------------------- // Just open the texture now //-------------------------- // image->imageHandle = FindTexture(tex_name, hint|gosHint_ReloadFromDisk); // //---------------------------------- // See if the image loaded correctly //---------------------------------- // image->flags |= (image->imageHandle ? GOSImage::Loaded : 0); return ( (image->flags & GOSImage::Loaded) != 0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ResourceImagePool::BuildTexturePool(NotationFile *hint_file) { // //------------------------------- // Open up the texture build file //------------------------------- // Check_Object(Tool::Instance); NotationFile::PageIterator *pages = hint_file->MakePageIterator(); Register_Object(pages); // //--------------------------------------------------------- // Go through the textures file and add each listed texture //--------------------------------------------------------- // Check_Object(Tool::Instance); Page *page; Verify(!Resource::ParentFileDependencies); while ((page = pages->ReadAndNext()) != NULL) { Check_Object(page); const char* texture = page->GetName(); if (!texture) continue; Check_Pointer(texture); // //------------------------------------------------------------ // See if the resource file is aliased, if so replace the name //------------------------------------------------------------ // page->GetEntry("alias", &texture); // //-------------------------------------------- // If we don't resourcify the texture, move on //-------------------------------------------- // bool resourcify = true; page->GetEntry("resourcify", &resourcify); if (!resourcify) continue; // //------------------------------------------------ // See if we can open up a resource with this name //------------------------------------------------ // MString file_name = "content\\textures\\"; file_name += texture; file_name += ".tga"; // //-------------------------- // Find the file on the path //-------------------------- // Verify(!FileStream::IsRedirected); #ifdef LAB_ONLY strcpy(MWGameInfo::g_LastFileOpenRequest, "BuildTexturePool: "); strcpy(MWGameInfo::g_LastFileOpenRequest + 20, file_name); #endif if (!gos_DoesFileExist(file_name)) { #if defined(SUPPORT_PNG) Verify(!FileStream::IsRedirected); char *extension = (char*)file_name + file_name.GetLength()-3; extension[0] = 'p'; extension[1] = 'n'; extension[2] = 'g'; Verify(!extension[3]); if (!gos_DoesFileExist(file_name)) #endif file_name = "content\\textures\\01AACA1.tga"; /* [editor degraded-mode] substitute placeholder for missing texture instead of fatal STOP, so downstream gets a valid handle (was: STOP("Texture %s could not be found!")) */ } // //-------------------------------------------------------- // If not, or it's not up to date, put it in the resources //-------------------------------------------------------- // Resource resource((FileStream::IsRedirected)?FileStream::RedirectedName:file_name); FileStream::IsRedirected = false; if (!resource.DoesResourceExist() || !resource.IsResourceUpToDate()) { // //-------------------- // Read the hint flags //-------------------- // int hints = ReadHint(page) & ~gosHint_ReloadFromDisk; // //------------------- // Read in the format //------------------- // const char* format; if (page->GetEntry("format", &format)) { if (!strcmp(format, "solid")) hints |= static_cast(gos_Texture_Solid) << 16; else if (!strcmp(format, "keyed")) hints |= static_cast(gos_Texture_Keyed) << 16; else if (!strcmp(format, "alpha")) hints |= static_cast(gos_Texture_Alpha) << 16; else if (!strcmp(format, "bump")) hints |= static_cast(gos_Texture_Bump) << 16; else if (!strcmp(format, "normal")) hints |= static_cast(gos_Texture_Normal) << 16; else hints |= static_cast(gos_Texture_Detect) << 16; } else hints |= static_cast(gos_Texture_Detect) << 16; // //-------------------------------------------------- // Look to see if we want a one level mip-bias delay //-------------------------------------------------- // int bias=0; page->GetEntry("bias", &bias); Clamp(bias, -5, 5); hints |= bias << 24; // //--------------------------------- // Open the file as a memory stream //--------------------------------- // FileStream texture_file(file_name); FileDependencies texture_dependencies; texture_dependencies.AddDependency(&texture_file); texture_dependencies.AddDependencies(hint_file->GetFileDependencies()); resource.Save(&texture_file, &texture_dependencies); // //--------------------------------- // Open the file as a memory stream //--------------------------------- // MString hint_name = resource.GetName(); hint_name += "{hint}"; Resource hint(hint_name); MemoryStream hint_stream(&hints, sizeof(hints)); hint.Save(&hint_stream, hint_file->GetFileDependencies()); } } Unregister_Object(pages); delete pages; }