Created
August 26, 2017 19:07
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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