How does Asset Injection work?

Discuss modding questions and implementation details.
User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

How does Asset Injection work?

Post by Daniel87 »

Hi,

I would need to replace the Tile Textures of DFU with my custom Texture2DArrays, (TEXTURE.302) by example.
How would I got about this with
A: Lose files or
B: as a dfmod bundle?

Do I just have to place the files into StreamingAssets/Texture ?
If not, where do these files have to be placed to automatically replace the original tile textures?
Can I use both methods at the same time? (everything inside a dfmod file, but also lose texture files placed in StreamingAssets/Textures)
In Julianos we Trust.

User avatar
King of Worms
Posts: 4752
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: How does Asset Injection work?

Post by King of Worms »

I do it using dfmod. I guess more info should be given by Lacus or someone who understands it better.

Most likely u can use both methods but not sure which has priority. I think loose files overwrite dfmods.

Id go with dfmod honestly.

User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

Re: How does Asset Injection work?

Post by Daniel87 »

King of Worms wrote: Thu May 27, 2021 1:05 pm I do it using dfmod. I guess more info should be given by Lacus or someone who understands it better.

Most likely u can use both methods but not sure which has priority. I think loose files overwrite dfmods.

Id go with dfmod honestly.
Can you be more specific about how you do it?
I checked TheLacus' tutorials and documentation but it lacks specific examples, paths, etc. Where do I place the Texture2DArrays? Or do I have to break them apart again and place the single textures in a folder before building my mod?
No idea where the original files are located within the DFU folder structure. My mod is at

Code: Select all

Assets/Game/Mods/WildernessOverhaul
.
Where do I have to place the TEXTURE.302 for it to be loaded rather than the ones from the old daggerfall game files?

And does anyone know where the Enable Texture Array Setting is supposed to be in DFU? I want to make sure, that I'm having it enabled.
Last edited by Daniel87 on Thu May 27, 2021 4:45 pm, edited 1 time in total.
In Julianos we Trust.

User avatar
TheLacus
Posts: 1305
Joined: Wed Sep 14, 2016 6:22 pm

Re: How does Asset Injection work?

Post by TheLacus »

You can provide individual textures (302_record-0.png) or a pre-built texture array named 302-TexArray and bundle them with the mod (path is not important). Individual textures can alse be placed inside StreamingAssets/Textures.

Classic daggerfall files (TEXTURE.XXX) use their own format, you can't override them directly.

User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

Re: How does Asset Injection work?

Post by Daniel87 »

TheLacus wrote: Thu May 27, 2021 3:00 pm You can provide individual textures (302_record-0.png) or a pre-built texture array named 302-TexArray and bundle them with the mod (path is not important). Individual textures can alse be placed inside StreamingAssets/Textures.

Classic daggerfall files (TEXTURE.XXX) use their own format, you can't override them directly.
Thanks for the info!

EDIT: I get the error

Code: Select all

302-TexArray: expected depth 56 but got 64.
Is the array.depth for tile texture 2d arrays hardcoded to 56? There are 64 possible tile texture indices, why limit it to 56?

Could this small line of code in daggerfall-unity/Assets/Scripts/Utility/AssetInjection/TextureReplacement.cs get changed to

Code: Select all

if ((textureArray = texture as Texture2DArray).depth >= 56 && (textureArray = texture as Texture2DArray).depth <= 64)
It would allow Texture2DArrays of 56 - 64 textures rather than limiting it to 56. The Byte format allowes up to 64 textures, so it would be nice if DFU also supports larger arrays than the one supplied by original DF.

Could anyone smarter than me create a PR of this line of code for me? GitHub hates me and I hate GitHub.

This would solve my issue and shouldn't cause normal DFU any problems.
In Julianos we Trust.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: How does Asset Injection work?

Post by l3lessed »

If you need a quick texture loading method, here you go. I use this for all my mods to load individual textures from streaming assets/textures. I'll be loading this up into a DFU scripting tool class I'll be putting together for my mods and releasing to everyone, but until then, here you go.

Code: Select all

        #region TextureLoader
        //texture loading method. Grabs the string path the developer inputs, finds the file, if exists, loads it,
        //then resizes it for use. If not, outputs error message.
        public Texture2D LoadPNG(string filePath)
        {

            Texture2D tex = null;
            byte[] fileData;

            if (File.Exists(filePath))
            {
                fileData = File.ReadAllBytes(filePath);
                tex = new Texture2D(2, 2);
                tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
            }
            else
                Debug.Log("FilePath Broken!");

            return tex;
        }
        #endregion
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

Re: How does Asset Injection work?

Post by Daniel87 »

l3lessed wrote: Thu May 27, 2021 5:01 pm If you need a quick texture loading method, here you go. I use this for all my mods to load individual textures from streaming assets/textures. I'll be loading this up into a DFU scripting tool class I'll be putting together for my mods and releasing to everyone, but until then, here you go.
Spoiler!

Code: Select all

        #region TextureLoader
        //texture loading method. Grabs the string path the developer inputs, finds the file, if exists, loads it,
        //then resizes it for use. If not, outputs error message.
        public Texture2D LoadPNG(string filePath)
        {

            Texture2D tex = null;
            byte[] fileData;

            if (File.Exists(filePath))
            {
                fileData = File.ReadAllBytes(filePath);
                tex = new Texture2D(2, 2);
                tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
            }
            else
                Debug.Log("FilePath Broken!");

            return tex;
        }
        #endregion
Thank you!
The problem is, that I am utilizing the original lookupTable NativeArray<byte> for texturing the terrain, rather than using my self-cooked texturing solution from before to avoid convoluted code and better integrate my mod with original DFU.

But this comes with the problem, that DFU does not allow Texture2DArrays that have more or less than exactly 56 textures and is very hardcoded when it comes to that.
I consider this a bug, as the NativeArray<byte> format allows up to 64 texture indices but DF just happened to use 56 textures for terrains while leaving 8 indices unused.

Simply changing the one if condition my post before would solve the issue and allow a variety of different modded Texture Arrays with 65 - 64 textures being loaded natively by DFU.
Original DFU will suffer no impact from this at all.
In Julianos we Trust.

l3lessed
Posts: 1399
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: How does Asset Injection work?

Post by l3lessed »

I'll let hazel or some one else push the commit to the main branch, if lucas is cool with it. If they can't because they're busy, I can.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

User avatar
TheLacus
Posts: 1305
Joined: Wed Sep 14, 2016 6:22 pm

Re: How does Asset Injection work?

Post by TheLacus »

TryImportTextureArray(int archive, int depth, TextureMap textureMap, Color32? fallbackColor, out Texture2DArray textureArray) is not only for terrain. It ensures loaded texture array has the expected depth, which is 56 for terrain but can be different in other cases.

Aren't you implementing a terrain material provider? That allows you to customize material import and you should be able to provide a different expected depth.

@l3lessed You can also use TextureReplacement.TryImportTextureFromLooseFiles() which takes a relative path.

User avatar
Daniel87
Posts: 391
Joined: Thu Nov 28, 2019 6:25 pm

Re: How does Asset Injection work?

Post by Daniel87 »

TheLacus wrote: Thu May 27, 2021 5:24 pm Aren't you implementing a terrain material provider? That allows you to customize material import and you should be able to provide a different expected depth.
Yes, I was going with the TerrainMaterialProvider approach before, but it convoluted the code quite a bit and caused Hazels machine to throw tons of errors concerning the shader when we tried to build and run my mod.
So after messing for days and not being able to solve the error, I decided to take a step back and try and use the native way of texturing terrain as it is more elegant and requires much less changes - therefore less likeliness of failure/errors and problems.

I realized that I can actually achieve the exact same texturing result by filling the missing 8 indices with the missing mirrored textures that were not present in original DF and load it the same way, as the original texture arrays are loaded and spread across the terrain in the original iTerrainTexturing.cs. This would have been way more elegant, clean and natively integrated into DFU than my spaghettig-code mess with the Terrain Material Provider and custom shaders.

The only problem I hit, was the error message that the expected depth is not given.
So now I wonder: Does the tile texture array size have to be hardcorded to 56 or could it be widened to a range between 56 and 64?

This is my current implementation of the terrain texturing: Link

I think with the TerrainMaterialProvider alone, I cannot change the depth.
Last time I got it working, I messed heavily with this function here. I copied it over to the TerrainMaterialProvider and had to delte half of it, as I had no access to the MaterialProvider variables from there. That created a huge mess that kind of worked but caused many problems down the road.

Code: Select all

Material tileMaterial = DaggerfallUnity.Instance.MaterialReader.GetTerrainTextureArrayMaterial(GetGroundArchive(terrainMaterialData.WorldClimate));
It means I also have to create a custom TextureReader.cs and MaterialReader.cs.
The more of these files I create, the more likely problems will occure, if DFU updates and changes these files.
Last edited by Daniel87 on Thu May 27, 2021 6:30 pm, edited 2 times in total.
In Julianos we Trust.

Post Reply