Skip to content

Instantly share code, notes, and snippets.

@ronyx69
Created August 26, 2017 19:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronyx69/be970ddcb2ce9f89a57e576313f46c7e to your computer and use it in GitHub Desktop.
Save ronyx69/be970ddcb2ce9f89a57e576313f46c7e to your computer and use it in GitHub Desktop.
Replaces textures/meshes for buildings/props/vehicles/trees ingame in realtime. (No User Interface)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICities;
using UnityEngine;
using ColossalFramework.IO;
using ObjUnity3D;
namespace Realtime
{
public class RealtimeMod : LoadingExtensionBase, IUserMod
{
public string Name => "Realtime";
public string Description => "Replace textures and meshes ingame.";
public enum TexturesReplacement { Diffuse, Alpha, Color, Illumination, Normal, Specular }
public override void OnLevelLoaded(LoadMode mode) { base.OnLevelLoaded(mode); }
public override void OnLevelUnloading() { base.OnLevelUnloading(); }
public static void building(string filename, string assetname)
{
Debug.Log("building called");
var name = filename + "." + assetname + "_Data";
var asset = PrefabCollection<BuildingInfo>.FindLoaded(name);
if (asset != null)
{
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Diffuse);
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Alpha);
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Color);
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Illumination);
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Normal);
ReplaceTextures(asset.m_material, "building", filename, assetname, TexturesReplacement.Specular);
Mesh replacementMesh;
if (ReplaceMesh(out replacementMesh, filename, assetname)) asset.m_mesh = replacementMesh;
}
}
public static void prop(string filename, string assetname)
{
Debug.Log("prop called");
var name = filename + "." + assetname + "_Data";
var asset = PrefabCollection<PropInfo>.FindLoaded(name);
if (asset != null)
{
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Diffuse);
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Alpha);
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Color);
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Illumination);
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Normal);
ReplaceTextures(asset.m_material, "prop", filename, assetname, TexturesReplacement.Specular);
Mesh replacementMesh;
if (ReplaceMesh(out replacementMesh, filename, assetname)) asset.m_mesh = replacementMesh;
}
}
public static void vehicle(string filename, string assetname)
{
Debug.Log("vehicle called");
var name = filename + "." + assetname + "_Data";
var asset = PrefabCollection<VehicleInfo>.FindLoaded(name);
if (asset != null)
{
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Diffuse);
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Alpha);
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Color);
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Illumination);
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Normal);
ReplaceTextures(asset.m_material, "vehicle", filename, assetname, TexturesReplacement.Specular);
Mesh replacementMesh;
if (ReplaceMesh(out replacementMesh, filename, assetname)) asset.m_mesh = replacementMesh;
Color nc = new Color(0, 0, 255);
Vector3[] vertices = asset.m_mesh.vertices;
Color[] colors = new Color[vertices.Length];
for (int i = 0; i < vertices.Length; i++) colors[i] = nc;
asset.m_mesh.colors = colors;
}
}
public static void tree(string filename, string assetname)
{
Debug.Log("tree called");
var name = filename + "." + assetname + "_Data";
var asset = PrefabCollection<TreeInfo>.FindLoaded(name);
if (asset != null)
{
ReplaceTextures(asset.m_material, "tree", filename, assetname, TexturesReplacement.Diffuse);
ReplaceTextures(asset.m_renderMaterial, "tree", filename, assetname, TexturesReplacement.Diffuse);
ReplaceTextures(asset.m_material, "tree", filename, assetname, TexturesReplacement.Normal);
ReplaceTextures(asset.m_renderMaterial, "tree", filename, assetname, TexturesReplacement.Normal);
ReplaceTextures(asset.m_material, "tree", filename, assetname, TexturesReplacement.Color);
ReplaceTextures(asset.m_renderMaterial, "tree", filename, assetname, TexturesReplacement.Color);
ReplaceTextures(asset.m_material, "tree", filename, assetname, TexturesReplacement.Alpha);
ReplaceTextures(asset.m_renderMaterial, "tree", filename, assetname, TexturesReplacement.Alpha);
Mesh replacementMesh;
if (ReplaceMesh(out replacementMesh, filename, assetname)) asset.m_mesh = replacementMesh;
}
}
public static void ReplaceTextures(Material material, string type, string filename, string assetname, TexturesReplacement replace)
{
Texture2D textureD = null, textureA = null, textureC = null, textureI = null, textureN = null, textureS = null;
Texture2D providedTexture = null; Color px; var texturePath = " ";
bool _d, _a, _c, _i, _n, _s, aci, xys, xyca, gamma;
_d = _a = _c = _i = _n = _s = aci = xys = xyca = gamma = false;
var path = ColossalFramework.IO.DataLocation.addonsPath + "\\Import\\" + filename;
if (type == "tree")
{
var defaultX = 0.5f; var defaultY = 0.5f; var defaultC = 1f; var defaultA = 1f;
if (replace == TexturesReplacement.Diffuse) // _d (Diffuse)
{
textureD = new Texture2D(1, 1);
texturePath = path + "_d.png";
Debug.Log(texturePath);
if (File.Exists(texturePath))
{
textureD.LoadImage(File.ReadAllBytes(texturePath));
_d = true;
}
if (_d) material.SetTexture("_MainTex", textureD);
}
if (replace == TexturesReplacement.Normal) // _n (Normal)
{
textureN = new Texture2D(1, 1);
texturePath = path + "_n.png";
if (File.Exists(texturePath))
{
textureN.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureN; _n = true;
}
}
if (replace == TexturesReplacement.Color) // _c (Color)
{
textureC = new Texture2D(1, 1);
texturePath = path + "_c.png";
if (File.Exists(texturePath))
{
textureC.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureC; _c = true;
}
}
if (replace == TexturesReplacement.Alpha) // _a (Alpha)
{
textureA = new Texture2D(1, 1);
texturePath = path + "_a.png";
if (File.Exists(texturePath))
{
textureA.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureA; _a = true;
}
}
if (replace == TexturesReplacement.Normal || replace == TexturesReplacement.Color || replace == TexturesReplacement.Alpha) // previous XYCA
{
if (material.GetTexture("_XYCAMap"))
{
var preXYCA = material.GetTexture("_XYCAMap") as Texture2D;
if (providedTexture) providedTexture = new Texture2D(providedTexture.width, providedTexture.height);
else providedTexture = new Texture2D(preXYCA.width, preXYCA.height);
if (preXYCA.name != "replaced")
{
gamma = true;
}
providedTexture.SetPixels(preXYCA.GetPixels());
providedTexture.anisoLevel = preXYCA.anisoLevel;
providedTexture.filterMode = preXYCA.filterMode;
providedTexture.wrapMode = preXYCA.wrapMode;
providedTexture.Apply();
xyca = true; GameObject.Destroy(preXYCA);
}
}
if (replace == TexturesReplacement.Normal || replace == TexturesReplacement.Color || replace == TexturesReplacement.Alpha) // XYCA COMBINATION
{
if (providedTexture)
{
for (int i = 0; i < providedTexture.width; i++)
{
for (int j = 0; j < providedTexture.height; j++)
{
px = providedTexture.GetPixel(i, j);
if (_n)
{
px.r = textureN.GetPixel(i, j).r;
px.g = textureN.GetPixel(i, j).g;
}
else if (!xyca)
{
px.r = defaultX;
px.g = defaultY;
}
if (_c) px.b = textureC.GetPixel(i, j).r; else if (!xyca) px.b = defaultC;
if (_a) px.a = textureA.GetPixel(i, j).r; else if (!xyca) px.a = defaultA;
if (_n || gamma) px.r = Mathf.LinearToGammaSpace(px.r);
if (_n || gamma) px.g = Mathf.LinearToGammaSpace(px.g);
if (_c) px.b = 1 - px.b;
if (_c || gamma) px.b = Mathf.LinearToGammaSpace(px.b);
if (_a) px.a = 1 - px.a;
providedTexture.SetPixel(i, j, px);
}
}
providedTexture.Apply(); providedTexture.name = "replaced";
material.SetTexture("_XYCAMap", providedTexture);
}
}
}
else // if building/prop/vehicle
{
var defaultA = 1f; var defaultC = 1f; var defaultI = 0f;
var defaultX = 0.5f; var defaultY = 0.5f; var defaultS = 0f;
if (type == "building") defaultI = 0.75f;
if (type == "vehicle") defaultI = 0.5f;
if (replace == TexturesReplacement.Diffuse) // _d (Diffuse)
{
textureD = new Texture2D(1, 1);
texturePath = path + "_d.png";
Debug.Log(texturePath);
if (File.Exists(texturePath))
{
textureD.LoadImage(File.ReadAllBytes(texturePath));
_d = true;
}
if (_d) material.SetTexture("_MainTex", textureD);
}
// ACI START
if (replace == TexturesReplacement.Alpha) // _a (Alpha)
{
textureA = new Texture2D(1, 1);
texturePath = path + "_a.png";
if (File.Exists(texturePath))
{
textureA.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureA; _a = true;
}
}
if (replace == TexturesReplacement.Color) // _c (Color)
{
textureC = new Texture2D(1, 1);
texturePath = path + "_c.png";
if (File.Exists(texturePath))
{
textureC.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureC; _c = true;
}
}
if (replace == TexturesReplacement.Illumination) // _i (Illumination)
{
textureI = new Texture2D(1, 1);
texturePath = path + "_i.png";
if (File.Exists(texturePath))
{
textureI.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureI; _i = true;
}
}
if (replace == TexturesReplacement.Alpha || replace == TexturesReplacement.Color || replace == TexturesReplacement.Illumination) // previous ACI
{
if (material.GetTexture("_ACIMap"))
{
var preACI = material.GetTexture("_ACIMap") as Texture2D;
if (providedTexture) providedTexture = new Texture2D(providedTexture.width, providedTexture.height);
else providedTexture = new Texture2D(preACI.width, preACI.height);
if (preACI.name != "replaced")
{
gamma = true;
}
providedTexture.SetPixels(preACI.GetPixels());
providedTexture.anisoLevel = preACI.anisoLevel;
providedTexture.filterMode = preACI.filterMode;
providedTexture.wrapMode = preACI.wrapMode;
providedTexture.Apply();
aci = true; GameObject.Destroy(preACI);
}
}
if (replace == TexturesReplacement.Alpha || replace == TexturesReplacement.Color || replace == TexturesReplacement.Illumination) // ACI COMBINATION
{
if (providedTexture)
{
for (int i = 0; i < providedTexture.width; i++)
{
for (int j = 0; j < providedTexture.height; j++)
{
px = providedTexture.GetPixel(i, j);
if (_a) px.r = textureA.GetPixel(i, j).r;
else if (!aci) px.r = defaultA;
if (_c) px.g = textureC.GetPixel(i, j).g; else if (!aci) px.g = defaultC;
if (_i) px.b = textureI.GetPixel(i, j).b; else if (!aci) px.b = defaultI;
if (_a) px.r = 1 - px.r;
if (gamma || _a) px.r = Mathf.LinearToGammaSpace(px.r);
if (_c) px.g = 1 - px.g;
if (gamma || _c) px.g = Mathf.LinearToGammaSpace(px.g);
if (gamma || _i) px.b = Mathf.LinearToGammaSpace(px.b);
providedTexture.SetPixel(i, j, px);
}
}
providedTexture.Apply(); providedTexture.name = "replaced";
material.SetTexture("_ACIMap", providedTexture);
}
}
// XYS START
providedTexture = null; gamma = false;
if (replace == TexturesReplacement.Normal) // _n (Normal)
{
textureN = new Texture2D(1, 1);
texturePath = path + "_n.png";
if (File.Exists(texturePath))
{
textureN.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureN; _n = true;
}
}
if (replace == TexturesReplacement.Specular) // _s (Specular)
{
textureS = new Texture2D(1, 1);
texturePath = path + "_s.png";
if (File.Exists(texturePath))
{
textureS.LoadImage(File.ReadAllBytes(texturePath));
providedTexture = textureS; _s = true;
}
}
if (replace == TexturesReplacement.Normal || replace == TexturesReplacement.Specular) // previous XYS
{
if (material.GetTexture("_XYSMap"))
{
var preXYS = material.GetTexture("_XYSMap") as Texture2D;
if (providedTexture) providedTexture = new Texture2D(providedTexture.width, providedTexture.height);
else providedTexture = new Texture2D(preXYS.width, preXYS.height);
if (preXYS.name != "replaced")
{
gamma = true;
}
providedTexture.SetPixels(preXYS.GetPixels());
providedTexture.anisoLevel = preXYS.anisoLevel;
providedTexture.filterMode = preXYS.filterMode;
providedTexture.wrapMode = preXYS.wrapMode;
providedTexture.Apply();
xys = true; GameObject.Destroy(preXYS);
}
}
if (replace == TexturesReplacement.Normal || replace == TexturesReplacement.Specular) // XYS COMBINATION
{
if (providedTexture)
{
for (int i = 0; i < providedTexture.width; i++)
{
for (int j = 0; j < providedTexture.height; j++)
{
px = providedTexture.GetPixel(i, j);
if (_n)
{
px.r = textureN.GetPixel(i, j).r;
px.g = textureN.GetPixel(i, j).g;
}
else if (!xys)
{
px.r = defaultX;
px.g = defaultY;
}
if (_s) px.b = textureS.GetPixel(i, j).b; else if (!xys) px.b = defaultS;
if (_n || gamma) px.r = Mathf.LinearToGammaSpace(px.r);
if (_n || gamma) px.g = Mathf.LinearToGammaSpace(px.g);
if (_s) px.b = 1 - px.b;
if (_s || gamma) px.b = Mathf.LinearToGammaSpace(px.b);
providedTexture.SetPixel(i, j, px);
}
}
providedTexture.Apply(); providedTexture.name = "replaced";
material.SetTexture("_XYSMap", providedTexture);
}
}
}
}
public static bool ReplaceMesh(out Mesh newMesh, string filename, string assetname)
{
string path = "none";
if (File.Exists(ColossalFramework.IO.DataLocation.addonsPath + "\\Import\\" + filename + ".obj")) path = ColossalFramework.IO.DataLocation.addonsPath + "\\Import\\" + filename + ".obj";
else if (File.Exists(ColossalFramework.IO.DataLocation.addonsPath + "\\Import\\" + assetname + ".obj")) path = ColossalFramework.IO.DataLocation.addonsPath + "\\Import\\" + assetname + ".obj";
if (path != "none")
{
Mesh mesh = new Mesh();
using (FileStream fileStream = File.Open(path, FileMode.Open))
{
mesh.LoadOBJ(OBJLoader.LoadOBJ(fileStream));
}
newMesh = mesh;
return true;
}
newMesh = null;
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment