Change a models texture live

Discuss modding questions and implementation details.
User avatar
Ralzar
Posts: 2211
Joined: Mon Oct 07, 2019 4:11 pm
Location: Norway

Change a models texture live

Post by Ralzar »

I am looking into making a small mod that simply checks all brick walls in a dungeon upon entering and then differentiates the actual walls from the teleporters. So it is possible to do a texture replacement for the teleporters that does not also make what is supposed to be just walls into a portal texture or whatever.

I can find all the red brick models and I can differentiate that based on if they have an action or not. However, I can not figure out how to edit the texture of the model. My Silly-but-works solution at the moment is to simply create a small grey wall texture from vanilla and matching its rotation and position so it matches the red brick wall I want to stay a wall.

However, I would prefer if it was possible to just switch out the texture on the existing model.

Anyone have any ideas how to do this?

Code: Select all

foreach (MeshCollider wall in brickWalls)
        {
            if (wall.name == "DaggerfallMesh [ID=72100]")
            {
                wallObj = wall.transform.gameObject;
                if (wallObj.GetComponent<DaggerfallAction>().ActionFlag == DFBlock.RdbActionFlags.Teleport)
                {
                    //Teleporter
                }
                else
                {
                    //Not Teleporter
                    //Code for switching out the red brick wall texture goes here.
                }    
            }
        }

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: Change a models texture live

Post by BadLuckBurt »

I just wrote this free-hand but there's a good chance it'll work off the bat. If you need to replace more than one material just remove the break in the for-loop and let it run through all the slots and assign the updated materials array outside the for-loop. Don't try to change the wallMR.materials array directly, that won't work, you need to change the copy and then reassign it.

Code: Select all

foreach (MeshCollider wall in brickWalls)
        {
            if (wall.name == "DaggerfallMesh [ID=72100]")
            {
                wallObj = wall.transform.gameObject;
                if (wallObj.GetComponent<DaggerfallAction>().ActionFlag == DFBlock.RdbActionFlags.Teleport)
                {
                    //Teleporter
                }
                else
                {
                    //Not Teleporter
                    //Code for switching out the red brick wall texture goes here.
                    //Just move this to wherever it is appropriate
                    string materialName = "TEXTURE.xxx [Index=x]"; //Replace this with the material name of the red brick
                    int archive = 0;
                    int record = 0;
                    
                    MeshRenderer wallMR = wallObj.GetComponent<MeshRenderer>();
                    Material[] materials = wallMR.materials;
                    //You will have to find the right material slot, sometimes there is more than one material. Loop through the materials array and check materials[i].name probably?
                    for(int i = 0; i < materials.Length; i++) 
                    {
                    	if (materials[i].name == materialName) {
                    		//When you found the material slot you need to replace, you can instantiate the new material using:
                    		Material newMaterial = DaggerfallUnity.Instance.MaterialReader.GetMaterial(archive, record);
                    		materials[i] = newMaterial;
		                wallMR.materials = materials;
                    		break;
                    	}
                    }
                }    
            }
        }
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

User avatar
Ralzar
Posts: 2211
Joined: Mon Oct 07, 2019 4:11 pm
Location: Norway

Re: Change a models texture live

Post by Ralzar »

BadLuckBurt wrote: Sat Jul 09, 2022 1:23 pm I just wrote this free-hand but there's a good chance it'll work off the bat. If you need to replace more than one material just remove the break in the for-loop and let it run through all the slots and assign the updated materials array outside the for-loop. Don't try to change the wallMR.materials array directly, that won't work, you need to change the copy and then reassign it.

Code: Select all

foreach (MeshCollider wall in brickWalls)
        {
            if (wall.name == "DaggerfallMesh [ID=72100]")
            {
                wallObj = wall.transform.gameObject;
                if (wallObj.GetComponent<DaggerfallAction>().ActionFlag == DFBlock.RdbActionFlags.Teleport)
                {
                    //Teleporter
                }
                else
                {
                    //Not Teleporter
                    //Code for switching out the red brick wall texture goes here.
                    //Just move this to wherever it is appropriate
                    string materialName = "TEXTURE.xxx [Index=x]"; //Replace this with the material name of the red brick
                    int archive = 0;
                    int record = 0;
                    
                    MeshRenderer wallMR = wallObj.GetComponent<MeshRenderer>();
                    Material[] materials = wallMR.materials;
                    //You will have to find the right material slot, sometimes there is more than one material. Loop through the materials array and check materials[i].name probably?
                    for(int i = 0; i < materials.Length; i++) 
                    {
                    	if (materials[i].name == materialName) {
                    		//When you found the material slot you need to replace, you can instantiate the new material using:
                    		Material newMaterial = DaggerfallUnity.Instance.MaterialReader.GetMaterial(archive, record);
                    		materials[i] = newMaterial;
		                wallMR.materials = materials;
                    		break;
                    	}
                    }
                }    
            }
        }
Thanks! That solved it. I was close before I gave up I see. I just could not figure out how to declare the Matrial[] materials so it could be used to replace the original material.
Screenshot 2022-07-09 233006.png
Screenshot 2022-07-09 233006.png (135.57 KiB) Viewed 18979 times

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: Change a models texture live

Post by BadLuckBurt »

Ralzar wrote: Sat Jul 09, 2022 9:32 pm Thanks! That solved it. I was close before I gave up I see. I just could not figure out how to declare the Matrial[] materials so it could be used to replace the original material.
No problem, happy to hear that worked. I read about material properties a few weeks ago for the skybox and remembered that bit about the materials array.
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

User avatar
Ralzar
Posts: 2211
Joined: Mon Oct 07, 2019 4:11 pm
Location: Norway

Re: Change a models texture live

Post by Ralzar »

BadLuckBurt wrote: Sun Jul 10, 2022 10:31 am
Ralzar wrote: Sat Jul 09, 2022 9:32 pm Thanks! That solved it. I was close before I gave up I see. I just could not figure out how to declare the Matrial[] materials so it could be used to replace the original material.
No problem, happy to hear that worked. I read about material properties a few weeks ago for the skybox and remembered that bit about the materials array.
Yup, already released the mod for it. Btw, you wouldn't happen to know how to add animation to a models texture. I messed about with it for a bit for the lava texture. I can add the animation component, but I am not figuring out how to make DFU set up the frames based on the record variants of the texture.

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: Change a models texture live

Post by BadLuckBurt »

Ralzar wrote: Sun Jul 10, 2022 10:46 am Yup, already released the mod for it. Btw, you wouldn't happen to know how to add animation to a models texture. I messed about with it for a bit for the lava texture. I can add the animation component, but I am not figuring out how to make DFU set up the frames based on the record variants of the texture.
I'm not sure I understand. Normally the animation is loaded automatically if the frames exist right? But that might just be the billboards and mobile characters, I'm not sure how it would work on a model, none of the vanilla models have animated textures or do they?
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

User avatar
Ralzar
Posts: 2211
Joined: Mon Oct 07, 2019 4:11 pm
Location: Norway

Re: Change a models texture live

Post by Ralzar »

BadLuckBurt wrote: Sun Jul 10, 2022 11:22 am
Ralzar wrote: Sun Jul 10, 2022 10:46 am Yup, already released the mod for it. Btw, you wouldn't happen to know how to add animation to a models texture. I messed about with it for a bit for the lava texture. I can add the animation component, but I am not figuring out how to make DFU set up the frames based on the record variants of the texture.
I'm not sure I understand. Normally the animation is loaded automatically if the frames exist right? But that might just be the billboards and mobile characters, I'm not sure how it would work on a model, none of the vanilla models have animated textures or do they?
Easiest model to compare it to is a fireplace in a tavern. The fireplace model has an animation component that purely static textured models lack.

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: Change a models texture live

Post by BadLuckBurt »

Have you tried loading a fireplace into the scene using the Importer in the DaggerfallUnity object? ModelID 41116 is the normal rectangular fireplace.

You can see how the script is set up in the Inspector when you select the model. There's also AssignAnimatedMaterialComponent in the GameObjectHelper class that sets up the script through code.

I always figured that it would do the animation part automatically once it detected multiple frames, the code seems to support that but that's just an assumption.

What exactly are you trying to do, is this just making a prefab object that is instantiated through code later or altering the material at runtime like the red brick?
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

User avatar
Ralzar
Posts: 2211
Joined: Mon Oct 07, 2019 4:11 pm
Location: Norway

Re: Change a models texture live

Post by Ralzar »

Yeah, I also honestly expected DFU to just handle the animation. But when I tried setting the lava texture (archive 356_0-0) as the material of the red brick wall, it just sets the exact frame I specify.

At the moment I only wonder because the lava texture looks better if it uses the animation and just in general because I ran into it.

User avatar
BadLuckBurt
Posts: 948
Joined: Sun Nov 05, 2017 8:30 pm

Re: Change a models texture live

Post by BadLuckBurt »

Ralzar wrote: Sun Jul 10, 2022 4:04 pm Yeah, I also honestly expected DFU to just handle the animation. But when I tried setting the lava texture (archive 356_0-0) as the material of the red brick wall, it just sets the exact frame I specify.

At the moment I only wonder because the lava texture looks better if it uses the animation and just in general because I ran into it.
So that's through scripting. You would have to add that AnimatedMaterial script component to the game object and then set it up like the code in GameObjectHelper.AssignAnimatedMaterialComponent does. You can probably call that AssignAnimatedMaterialComponent method directly from your code as long as you supply it with an array that at least has the cached version of the animated material.

Something like this might work, I haven't tested it:

Code: Select all

                CachedMaterial cachedMaterial;
                dfUnity.MaterialReader.GetCachedMaterial(archive, record, 0, out cachedMaterial);
		CachedMaterial[] cachedMaterialsOut = new CachedMaterial[]{cachedMaterial};
		GameObjectHelper.AssignAnimatedMaterialComponent(cachedMaterialsOut, go);
It makes sense that DFU doesn't handle this case automatically since it is not even aware of you changing textures on the object, doing the call I described above changes that.

I bet if you have a separate model with the lava texture and instantiate that, it just works.
DFU on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
DFU Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

.

Post Reply