Skip to content

Commit fd3aff3

Browse files
committed
Update 2.0.12.4
2 parents 9c446e0 + 52551cd commit fd3aff3

File tree

2 files changed

+158
-59
lines changed

2 files changed

+158
-59
lines changed

xivModdingFramework/Materials/DataContainers/XivMtrl.cs

Lines changed: 145 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ public ShaderInfo GetShaderInfo()
309309
case "bg.shpk":
310310
info.Shader = MtrlShader.Furniture;
311311
break;
312+
case "bgcolorchange.shpk":
313+
info.Shader = MtrlShader.DyeableFurniture;
314+
break;
312315
default:
313316
info.Shader = MtrlShader.Other;
314317
break;
@@ -356,6 +359,9 @@ public void SetShaderInfo(ShaderInfo info)
356359
case MtrlShader.Furniture:
357360
Shader = "bg.shpk";
358361
break;
362+
case MtrlShader.DyeableFurniture:
363+
Shader = "bgcolorchange.shpk";
364+
break;
359365
default:
360366
// No change to the Shader for 'Other' type entries.
361367
break;
@@ -419,6 +425,11 @@ public MapInfo GetMapInfo(XivTexType MapType)
419425
mapIndex = (int) paramSet.TextureIndex;
420426
info.Format = GetFormat(paramSet.FileFormat);
421427
}
428+
else if (paramSet.TextureType == Mtrl.FurnitureTextureDescriptorValues[MapType])
429+
{
430+
mapIndex = (int)paramSet.TextureIndex;
431+
info.Format = GetFormat(paramSet.FileFormat);
432+
}
422433
}
423434

424435
if(mapIndex < 0)
@@ -472,7 +483,12 @@ public MapInfo GetMapInfo(string path)
472483
if(Mtrl.TextureDescriptorValues.ContainsValue(descriptor.TextureType))
473484
{
474485
info.Usage = Mtrl.TextureDescriptorValues.First(x => x.Value == descriptor.TextureType).Key;
475-
} else
486+
}
487+
else if (Mtrl.FurnitureTextureDescriptorValues.ContainsValue(descriptor.TextureType))
488+
{
489+
info.Usage = Mtrl.FurnitureTextureDescriptorValues.First(x => x.Value == descriptor.TextureType).Key;
490+
}
491+
else
476492
{
477493
info.Usage = XivTexType.Other;
478494
}
@@ -519,44 +535,34 @@ public void SetMapInfo(XivTexType MapType, MapInfo info)
519535
// Deleting existing info.
520536
if (info == null)
521537
{
522-
if(paramIdx < 0)
523-
{
524-
// Didn't exist to start, nothing to do.
525-
return;
526-
}
527538

528-
// Remove texture from path list if it exists.
529-
if (TexturePathList.Count > oldInfo.TextureIndex)
530-
{
531-
TexturePathList.RemoveAt((int)oldInfo.TextureIndex);
532-
TexturePathUnknownList.RemoveAt((int)oldInfo.TextureIndex);
533-
}
534539

535-
// Remove Parameter List
536-
TextureDescriptorList.RemoveAt(paramIdx);
537-
538-
// Update other texture offsets
539-
for(var i = 0; i < TextureDescriptorList.Count; i++)
540+
if (paramIdx >= 0)
540541
{
541-
var p = TextureDescriptorList[i];
542-
if(p.TextureIndex > oldInfo.TextureIndex)
542+
// Remove texture from path list if it exists.
543+
if (TexturePathList.Count > oldInfo.TextureIndex)
543544
{
544-
p.TextureIndex--;
545+
TexturePathList.RemoveAt((int)oldInfo.TextureIndex);
546+
TexturePathUnknownList.RemoveAt((int)oldInfo.TextureIndex);
545547
}
546-
TextureDescriptorList[i] = p;
547-
}
548548

549-
// Remove struct1 entry for the removed map type, if it exists.
550-
for(var i = 0; i < TextureUsageList.Count; i++)
551-
{
552-
var s = TextureUsageList[i];
553-
if(s.TextureType == Mtrl.TextureUsageValues[MapType].TextureType)
549+
// Remove Parameter List
550+
TextureDescriptorList.RemoveAt(paramIdx);
551+
552+
// Update other texture offsets
553+
for (var i = 0; i < TextureDescriptorList.Count; i++)
554554
{
555-
TextureUsageList.RemoveAt(i);
556-
break;
555+
var p = TextureDescriptorList[i];
556+
if (p.TextureIndex > oldInfo.TextureIndex)
557+
{
558+
p.TextureIndex--;
559+
}
560+
TextureDescriptorList[i] = p;
557561
}
558562
}
559563

564+
RegenerateTextureUsageList();
565+
560566
return;
561567

562568
}
@@ -608,31 +614,103 @@ public void SetMapInfo(XivTexType MapType, MapInfo info)
608614
TexturePathList[(int) raw.TextureIndex] = info.path;
609615
}
610616

611-
// Update struct1 entry with the appropriate entry if it's not already there.
612-
bool foundEntry = false;
613-
for (var i = 0; i < TextureUsageList.Count; i++)
617+
RegenerateTextureUsageList();
618+
}
619+
620+
/// <summary>
621+
/// Regenerates/Cleans up the texture usage list based on the
622+
/// Texture Maps that are set in the Texture Description Fields.
623+
/// </summary>
624+
private void RegenerateTextureUsageList()
625+
{
626+
var shaderInfo = GetShaderInfo();
627+
628+
// Furniture shaders do not use the texture usage list at all.
629+
if(shaderInfo.Shader == MtrlShader.Furniture || shaderInfo.Shader == MtrlShader.DyeableFurniture)
614630
{
615-
var s = TextureUsageList[i];
616-
if (s.TextureType == Mtrl.TextureUsageValues[MapType].TextureType)
617-
{
618-
foundEntry = true;
619-
break;
620-
}
631+
TextureUsageList.Clear();
632+
return;
621633
}
622634

623-
if(!foundEntry)
635+
// Everything (should) have a normal, so this is redundant.
636+
// bool hasNormal = GetMapInfo(XivTexType.Normal) != null;
637+
bool hasSpec = GetMapInfo(XivTexType.Specular) != null;
638+
bool hasDiffuse = GetMapInfo(XivTexType.Diffuse) != null;
639+
bool hasMulti = GetMapInfo(XivTexType.Multi) != null;
640+
641+
ClearTextureUsage(XivTexType.Normal);
642+
ClearTextureUsage(XivTexType.Diffuse);
643+
ClearTextureUsage(XivTexType.Specular);
644+
ClearTextureUsage(XivTexType.Multi);
645+
646+
// These need to be set in relatively specific order
647+
// in order to use the maps correctly
648+
649+
SetTextureUsage(XivTexType.Normal);
650+
651+
if (hasDiffuse)
624652
{
625-
var s1 = new TextureUsageStruct()
626-
{
627-
TextureType = Mtrl.TextureUsageValues[MapType].TextureType,
628-
Unknown = Mtrl.TextureUsageValues[MapType].Unknown
629-
};
653+
// Diffuse
654+
SetTextureUsage(XivTexType.Diffuse);
655+
}
630656

631-
TextureUsageList.Add(s1);
657+
if (hasSpec || hasMulti)
658+
{
659+
// Including both of these seems to guarantee best results,
660+
// vs including only one or the other.
661+
SetTextureUsage(XivTexType.Multi);
662+
SetTextureUsage(XivTexType.Specular);
632663
}
633664

634665
}
635666

667+
/// <summary>
668+
/// Clears a texture usage value.
669+
/// </summary>
670+
/// <param name="usage"></param>
671+
private bool ClearTextureUsage(XivTexType usage)
672+
{
673+
var oldCount = TextureUsageList.Count;
674+
TextureUsageList = TextureUsageList.Where(x => x.TextureType != Mtrl.TextureUsageValues[usage].TextureType).ToList();
675+
return oldCount != TextureUsageList.Count;
676+
}
677+
678+
/// <summary>
679+
/// Adds or changes a texture usage value.
680+
/// </summary>
681+
/// <param name="usage"></param>
682+
/// <param name="unknownValue"></param>
683+
private void SetTextureUsage(XivTexType usage, uint? unknownValue = null)
684+
{
685+
if(unknownValue == null)
686+
{
687+
unknownValue = Mtrl.TextureUsageValues[usage].Unknown;
688+
}
689+
try
690+
{
691+
var val = TextureUsageList.First(x => x.TextureType == Mtrl.TextureUsageValues[usage].TextureType);
692+
if(val != null)
693+
{
694+
// Despite being named 'Struct' this is actually a class.
695+
val.Unknown = (uint) unknownValue;
696+
} else
697+
{
698+
TextureUsageList.Add(new TextureUsageStruct()
699+
{
700+
TextureType = Mtrl.TextureUsageValues[usage].TextureType,
701+
Unknown = (uint) unknownValue
702+
});
703+
}
704+
} catch(Exception ex)
705+
{
706+
TextureUsageList.Add(new TextureUsageStruct()
707+
{
708+
TextureType = Mtrl.TextureUsageValues[usage].TextureType,
709+
Unknown = (uint) unknownValue
710+
});
711+
}
712+
}
713+
636714
/// <summary>
637715
/// Retrieve all MapInfo structs for all textures associated with this MTRL,
638716
/// Including textures with unknown usage.
@@ -641,6 +719,7 @@ public void SetMapInfo(XivTexType MapType, MapInfo info)
641719
public List<MapInfo> GetAllMapInfos(bool tokenize = true)
642720
{
643721
var ret = new List<MapInfo>();
722+
var shaderInfo = GetShaderInfo();
644723
for(var i = 0; i < TexturePathList.Count; i++)
645724
{
646725
var info = new MapInfo();
@@ -661,7 +740,16 @@ public List<MapInfo> GetAllMapInfos(bool tokenize = true)
661740
return (x.Value == p.TextureType);
662741
}).Key;
663742
info.Usage = usage;
664-
} else
743+
} else if(Mtrl.FurnitureTextureDescriptorValues.ContainsValue(p.TextureType))
744+
{
745+
// Known parameter for the furniture shaders.
746+
var usage = Mtrl.FurnitureTextureDescriptorValues.First(x =>
747+
{
748+
return (x.Value == p.TextureType);
749+
}).Key;
750+
info.Usage = usage;
751+
752+
} else
665753
{
666754
info.Usage = XivTexType.Other;
667755
}
@@ -695,12 +783,13 @@ public List<TexTypePath> GetTextureTypePathList()
695783
TexTypePath ttp;
696784
foreach (var map in maps)
697785
{
698-
699-
700786
if (shaderInfo.Shader == MtrlShader.Skin && map.Usage == XivTexType.Multi)
701787
{
702788
ttp = new TexTypePath() { DataFile = GetDataFile(), Path = map.path, Type = XivTexType.Skin };
703789

790+
} else if (shaderInfo.Shader == MtrlShader.Furniture && map.path.Contains("dummy")) {
791+
// Dummy textures are skipped.
792+
continue;
704793
}
705794
else
706795
{
@@ -996,13 +1085,14 @@ public enum MtrlTextureDescriptorFormat
9961085
// Enum representation of the shader names used in mtrl files.
9971086
public enum MtrlShader
9981087
{
999-
Standard, // character.shpk
1000-
Glass, // characterglass.shpk
1001-
Skin, // skin.shpk
1002-
Hair, // hair.shpk
1003-
Iris, // iris.shpk
1004-
Furniture, // bg.shpk
1005-
Other // Unknown Shader
1088+
Standard, // character.shpk
1089+
Glass, // characterglass.shpk
1090+
Skin, // skin.shpk
1091+
Hair, // hair.shpk
1092+
Iris, // iris.shpk
1093+
Furniture, // bg.shpk
1094+
DyeableFurniture, //bgcolorchange.shpk
1095+
Other // Unknown Shader
10061096
}
10071097

10081098
/// <summary>

xivModdingFramework/Materials/FileTypes/Mtrl.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,20 @@ public XivDataFile DataFile
7474
{ XivTexType.Reflection, 4271961042 } // Used for the Catchlight texture in Iris Materials.
7575
};
7676

77+
public static Dictionary<XivTexType, uint> FurnitureTextureDescriptorValues = new Dictionary<XivTexType, uint>()
78+
{
79+
{ XivTexType.Normal, 2863978985 },
80+
{ XivTexType.Diffuse, 510652316 },
81+
{ XivTexType.Specular, 465317650 },
82+
{ XivTexType.Multi, 0 },
83+
{ XivTexType.Reflection, 0 }
84+
};
85+
7786
// MtrlParam constants for file compressions/formats.
7887
public static Dictionary<MtrlTextureDescriptorFormat, short> TextureDescriptorFormatValues = new Dictionary<MtrlTextureDescriptorFormat, short>()
7988
{
80-
{ MtrlTextureDescriptorFormat.UsesColorset, -32768 }, // There is some variation on these values, but it always occures in the last 6 bits, and doesn't seem
81-
{ MtrlTextureDescriptorFormat.NoColorset, -31936 } // To have an appreciable change (Either [000000] or [010101])
89+
{ MtrlTextureDescriptorFormat.UsesColorset, -32768 }, // There is some variation on these values, but it always occures in the last 6 bits, and doesn't seem
90+
{ MtrlTextureDescriptorFormat.NoColorset, -31936 }, // To have an appreciable change (Either [000000] or [010101])
8291
// Non-normal maps are always [WithoutAlpha]. Normal maps are always [WithAlpha],
8392
// with the exception that 8.8.8.8 ARGB normal maps use the WithoutAlpha flag (And do not pull a colorset).
8493

@@ -607,7 +616,7 @@ public async Task<int> ImportMtrl(XivMtrl xivMtrl, IItem item, string source)
607616
var path = mapInfo.path;
608617
var fileHash = HashGenerator.GetHash(Path.GetFileName(path));
609618
var pathHash = HashGenerator.GetHash(path.Substring(0, path.LastIndexOf("/", StringComparison.Ordinal)));
610-
var exists = await _index.FileExists(fileHash, pathHash, XivDataFile._04_Chara);
619+
var exists = await _index.FileExists(fileHash, pathHash, IOUtil.GetDataFileFromPath(path));
611620

612621
if(exists)
613622
{
@@ -619,7 +628,7 @@ public async Task<int> ImportMtrl(XivMtrl xivMtrl, IItem item, string source)
619628
var xivTex = new XivTex();
620629
xivTex.TextureTypeAndPath = new TexTypePath()
621630
{
622-
DataFile = XivDataFile._04_Chara, Path = path, Type = mapInfo.Usage
631+
DataFile = IOUtil.GetDataFileFromPath(path), Path = path, Type = mapInfo.Usage
623632
};
624633
xivTex.TextureFormat = format;
625634

0 commit comments

Comments
 (0)