Skip to content

Instantly share code, notes, and snippets.

@Deeheks
Last active October 31, 2019 03:51
Show Gist options
  • Save Deeheks/0cf973ed7cab098ce298edcc57c62026 to your computer and use it in GitHub Desktop.
Save Deeheks/0cf973ed7cab098ce298edcc57c62026 to your computer and use it in GitHub Desktop.
No need to create a new prop each time you want to reimport a decal. This is Boformer's Decal Script modified using parts of Ronyx RealTime mod code.
// Script based off @boformer script called "Large Decals"
// https://gist.github.com/boformer/624eef5ffc8686cb5f12377f1be855f9
// In addition to making the decal size and slope tolerance,
// this script looks for textures called decal_a.png or decal_d.png (etc)
// in the textures folder and replace them if they are found.
// Textures import code taken from the RealTime mod code (@Ronyx69).
// https://gist.github.com/ronyx69/9c0026648d26b1e1b09cb8ec8a831b17
// Warning: Do not save vehicles after running this script without a game restart!
// Size of decal in meters - width and length
// (texture width and height will be stretched to match this)
var size = new Vector2(16.0f, 16.0f);
// Tiling amount
var tile = new Vector3(1.0f, 1.0f);
// Box mesh height, leave at a negative value to calculate automatically
var slopeTolerance = 5.0f;
Debug.Log("Script created a " + size.x + "x" + size.y + "m decal with a " + slopeTolerance + "m slope tolerance");
if (slopeTolerance < 0)
{
slopeTolerance = Mathf.Clamp((size.x + size.y) / 4f, 2f, 32f);
}
var scale = new Vector4(size.x, slopeTolerance, size.y, 0);
var tiling = new Vector4(tile.x, 0, tile.y, 0);
var asset = ToolsModifierControl.toolController.m_editPrefabInfo as PropInfo;
var mesh = asset.m_mesh;
var vertices = mesh.vertices;
var vertexArray = new Vector3[vertices.Length];
vertices.CopyTo(vertexArray, 0);
for (int i = 0; i < vertices.Length; i++)
{
if (vertexArray[i].x > 0) vertexArray[i].x = scale.x / 2f; else vertexArray[i].x = -scale.x / 2f;
if (vertexArray[i].y > 0) vertexArray[i].y = scale.y / 2f; else vertexArray[i].y = -scale.y / 2f;
if (vertexArray[i].z > 0) vertexArray[i].z = scale.z / 2f; else vertexArray[i].z = -scale.z / 2f;
}
mesh.vertices = vertexArray;
mesh.RecalculateBounds();
asset.CalculateGeneratedInfo();
asset.m_material.shader = Shader.Find("Custom/Props/Decal/Blend");
asset.m_material.SetVector("_DecalSize", scale);
asset.m_material.SetVector("_DecalTiling", tiling);
asset.m_lodMesh = null;
asset.m_lodMaterial = null;
asset.m_lodRenderDistance = 1000;
typeof(PropInfo).GetField("m_UIEditorCategory", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(asset, "PropsResidentialGroundTiles");
asset.m_createRuining = false;
asset.m_useColorVariations = false;
// Tells the asset editor to save _DecalSize and _DecalTiling shader properties
var vectorProps= Type.GetType("ColossalFramework.Packaging.ShaderUtil, ColossalManaged").GetField("vectorProps").GetValue(null) as string[];
vectorProps[4]="_DecalSize";
vectorProps[5]="_DecalTiling";
// Textures must be placed in gamefolder/textures/
var assetSource = "textures/";
var assetname = "decal";
var assetMaterial = asset.m_material;
var texturePath = " ";
Texture2D providedTexture=null; Color px;
// Bools
bool _d, _a, _c, _i, _n, _s, aci, xys, gamma;
_d = _a = _c = _i = _n = _s = aci = xys = gamma = false;
// Defaults
var defaultA = 1f; var defaultC = 1f; var defaultI = 0f;
var defaultX = 0.5f; var defaultY = 0.5f; var defaultS = 0f;
// _d (Diffuse)
Texture2D textureD; textureD = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_d.png";
if (File.Exists(texturePath)) {
textureD.LoadImage(File.ReadAllBytes(texturePath));
_d=true;
}
if(_d) {assetMaterial.SetTexture("_MainTex", textureD); Debug.Log("Script replaced " + texturePath);}
// ACI START
// _a (Alpha)
Texture2D textureA; textureA = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_a.png";
if (File.Exists(texturePath)) {
textureA.LoadImage(File.ReadAllBytes(texturePath));
providedTexture=textureA; _a=true;
Debug.Log("Script replaced " + texturePath);
}
// _c (Color)
Texture2D textureC; textureC = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_c.png";
if (File.Exists(texturePath)) {
textureC.LoadImage(File.ReadAllBytes(texturePath));
providedTexture=textureC; _c=true;
Debug.Log("Script replaced " + texturePath);
}
// _i (Illumination)
Texture2D textureI; textureI = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_i.png";
if (File.Exists(texturePath)) {
textureI.LoadImage(File.ReadAllBytes(texturePath));
providedTexture=textureI; _i=true;
Debug.Log("Script replaced " + texturePath);
}
// previous ACI
if(assetMaterial.GetTexture("_ACIMap"))
{
var preACI = assetMaterial.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);
}
// ACI COMBINATION
if(providedTexture)
{
for (int i = 0; i < textureA.width; i++)
{
for (int j = 0; j < textureA.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=Mathf.LinearToGammaSpace(1-px.r);
if(_c) px.g=Mathf.LinearToGammaSpace(1-px.g);
if(_i) px.b=Mathf.LinearToGammaSpace(px.b);
providedTexture.SetPixel(i, j, px);
}
}
providedTexture.Apply(); providedTexture.name="replaced";
assetMaterial.SetTexture("_ACIMap", providedTexture);
}
// ACI END
// XYS START
providedTexture=null; gamma=false;
// _n (Normal)
Texture2D textureN; textureN = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_n.png";
if (File.Exists(texturePath)) {
textureN.LoadImage(File.ReadAllBytes(texturePath));
providedTexture=textureN; _n=true;
Debug.Log("Script replaced " + texturePath);
}
// _s (Specular)
Texture2D textureS; textureS = new Texture2D(1, 1);
texturePath = assetSource + assetname + "_s.png";
if (File.Exists(texturePath)) {
textureS.LoadImage(File.ReadAllBytes(texturePath));
providedTexture=textureS; _s=true;
Debug.Log("Script replaced " + texturePath);
}
// previous XYS
if(assetMaterial.GetTexture("_XYSMap"))
{
var preXYS = assetMaterial.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);
}
// 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||gamma) px.b=Mathf.LinearToGammaSpace(1-px.b);
providedTexture.SetPixel(i, j, px);
}
}
providedTexture.Apply(); providedTexture.name="replaced";
assetMaterial.SetTexture("_XYSMap", providedTexture);
}
// XYS END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment