Deleting cached textures
The ITexture generated by calling Material() with a png/jpg file gets cached and can't be deleted afterwards. If I were to create an IMaterial object with a certain png file, then replace that png file with another one that has the same name, the ITexture will not be replaced upon recalling the Material() function. This will cause the material to have incorrect width and height, for example. A few things to note:
- This is not the case with vtf files, if any IMaterial objects have a vtf file as their texture and then the file gets replaced, then this IMaterial's width and height will be updated.
- Using SetUndefined on the generated IMaterial's $basetexture does not help, as calling the Material() function after that does not generate a new texture.
- Neither IMaterial:Recompute() nor ITexture:Download() help: after calling each of them, the width and height still have their old values.
First of all, I question what you are trying to do in the first place. If you are replacing the $basetexture of a loaded .png/.jpg file, why are you not just using CreateMaterial() instead? You really shouldn't be modifying those materials.
Secondly, I am unable to reproduce the issue you describe.
Please provide minimal code to reproduce the issue you describe.
As for the removal of cached textures, they are removed automatically when they are no longer used.
local mat = Material( "icon16/monkey.png" )
print(mat, mat:Width(), mat:Height() )
local ma2t = Material( "gm_construct/construct_concrete_ground" )
mat:SetTexture( "$basetexture", ma2t:GetTexture( "$basetexture" ) )
print(mat, mat:Width(), mat:Height() )
I am not replacing the $basetexture of materials loaded with Material(), I am in fact using CreateMaterial(). What I am trying to do in a nutshell is create a UI that allows users to save some png/vtf/jpg files in the data folder under a chosen name for later usage. The user can also delete existing files if he wants, which is where the problem comes in: if a player were to remove a file named "test.png", for instance, and then replace it with another "test.png" that has different contents, he will run into an issue. Here are the steps required to reproduce this issue:
- Create a .png file in any directory (data, for example) and call the Material() function using the file's path as the argument.
- Run the following code:
local mat=Material("../data/test.png") -- path to created file
hook.Add("PostDrawHUD","a",function()
surface.SetDrawColor(color_white)
surface.SetMaterial(mat)
surface.DrawTexturedRect(0,0,128,128)
end)
- Delete this .png file.
- Create a new .png file in the same directory under the same name (but with different contents and dimensions).
After following these steps, you will notice that the texture drawn in the top left corner has not been replaced with the new one, and obviously the :Width() and :Height() functions return values corresponding to the old texture. Calling :Recompute() on the IMaterial or :Download() on the ITexture do not change much, apart from maybe messing up the original texture a bit. Attempting to recreate the ITexture by calling Material() is not helpful since the texture has been cached. Removing the rendering hook for a while to make the cached texture automatically disappear (as it is no longer in use) doesn't work neither.
Update: Apparently replacing a file with the one that has the same name and extension does update the texture, but :Width() and :Height() will still return old values. In order to get the same issue as above, the old and new files should have the same name, but different extensions (test.jpg and test.png, for instance).