Add Picture Texture field to PictureFrameBuilder
Assigned texture drives the picture material BaseMap via a per-frame material instance (asset untouched, frames sharing a material stay independent) and takes priority for aspect resolution. New default picture material Frame Picture.mat wired in the script defaults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d1f7b79013
commit
5dbdc0e6b2
4 files changed
+200
-9
No files matched your search
@@ -11,7 +11,9 @@ namespace Chameleon.Components
|
||||
// possible rounding, depths of the frame depth), so a frame keeps its proportions when resized via
|
||||
// Size - resize via Size, NOT via transform scale. Four submeshes with their own
|
||||
// material slots: 0 picture, 1 inner cavity (recess walls + padding ring), 2 frame (front ring, outer
|
||||
// sides, edge rounding), 3 back plate. Front faces -Z like Unity's built-in Quad.
|
||||
// sides, edge rounding), 3 back plate. Front faces -Z like Unity's built-in Quad. An assigned
|
||||
// PictureTexture becomes the picture material's base map via a per-frame DontSave material
|
||||
// instance (the shared material asset is never modified) and drives the aspect ratio.
|
||||
//
|
||||
// The generated mesh is a per-instance HideFlags.DontSave object (never saved into the scene file);
|
||||
// it is rebuilt on scene load / domain reload via OnEnable. Duplicated frames get their own mesh
|
||||
@@ -59,6 +61,8 @@ namespace Chameleon.Components
|
||||
[SerializeField, Range(0f, 1f)] float _padding = 0.01f;
|
||||
[Tooltip("Picture plane: -1 = fully inside (on the back plate), 0 = flush with the inner floor, 1 = a full frame depth in front of the frame.")]
|
||||
[SerializeField, Range(-1f, 1f)] float _pictureDepth = 0.1f;
|
||||
[Tooltip("Photo for this frame: applied as the picture material's base map via a per-frame material instance (the material asset itself is never modified) and drives the aspect ratio. Empty = the material's own base map is shown.")]
|
||||
[SerializeField] Texture _pictureTexture;
|
||||
|
||||
[Header("Materials")]
|
||||
[SerializeField] Material _pictureMaterial;
|
||||
@@ -82,6 +86,7 @@ namespace Chameleon.Components
|
||||
};
|
||||
|
||||
Mesh _mesh;
|
||||
Material _pictureMaterialInstance;
|
||||
bool _rebuildQueued;
|
||||
bool _rebuilding;
|
||||
|
||||
@@ -110,6 +115,11 @@ namespace Chameleon.Components
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (_pictureMaterialInstance)
|
||||
{
|
||||
DestroyOwned(_pictureMaterialInstance);
|
||||
_pictureMaterialInstance = null;
|
||||
}
|
||||
if (!_mesh) return;
|
||||
if (Application.isPlaying) Destroy(_mesh);
|
||||
else DestroyImmediate(_mesh);
|
||||
@@ -301,13 +311,49 @@ namespace Chameleon.Components
|
||||
|
||||
void ApplyMaterials()
|
||||
{
|
||||
var picture = ResolvePictureMaterial();
|
||||
var meshRenderer = GetComponent<MeshRenderer>();
|
||||
var current = meshRenderer.sharedMaterials;
|
||||
bool dirty = current.Length != 4
|
||||
|| current[0] != _pictureMaterial || current[1] != _innerMaterial
|
||||
|| current[0] != picture || current[1] != _innerMaterial
|
||||
|| current[2] != _frameMaterial || current[3] != _backMaterial;
|
||||
if (dirty)
|
||||
meshRenderer.sharedMaterials = new[] { _pictureMaterial, _innerMaterial, _frameMaterial, _backMaterial };
|
||||
meshRenderer.sharedMaterials = new[] { picture, _innerMaterial, _frameMaterial, _backMaterial };
|
||||
}
|
||||
|
||||
// With a picture texture assigned, the picture slot uses a per-frame DontSave material
|
||||
// instance whose base map is that texture - many frames can share ONE picture material asset
|
||||
// with different photos, and the asset is never mutated. Properties are re-copied from the
|
||||
// source material on every rebuild, so asset edits keep showing up on the instance. Like the
|
||||
// mesh, the instance is never saved and is recreated in OnEnable after scene load.
|
||||
Material ResolvePictureMaterial()
|
||||
{
|
||||
if (!_pictureTexture || !_pictureMaterial)
|
||||
{
|
||||
if (_pictureMaterialInstance)
|
||||
{
|
||||
DestroyOwned(_pictureMaterialInstance);
|
||||
_pictureMaterialInstance = null;
|
||||
}
|
||||
return _pictureMaterial;
|
||||
}
|
||||
|
||||
if (!_pictureMaterialInstance)
|
||||
{
|
||||
_pictureMaterialInstance = new Material(_pictureMaterial) { hideFlags = HideFlags.DontSave };
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_pictureMaterialInstance.shader != _pictureMaterial.shader)
|
||||
_pictureMaterialInstance.shader = _pictureMaterial.shader;
|
||||
_pictureMaterialInstance.CopyPropertiesFromMaterial(_pictureMaterial);
|
||||
}
|
||||
_pictureMaterialInstance.name = _pictureMaterial.name + " (Picture)";
|
||||
if (_pictureMaterialInstance.HasProperty("_BaseMap"))
|
||||
_pictureMaterialInstance.SetTexture("_BaseMap", _pictureTexture);
|
||||
else
|
||||
_pictureMaterialInstance.mainTexture = _pictureTexture;
|
||||
return _pictureMaterialInstance;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@@ -318,14 +364,14 @@ namespace Chameleon.Components
|
||||
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic
|
||||
| System.Reflection.BindingFlags.Instance);
|
||||
|
||||
// Editor-only: derive _aspect (longer side = 1) from the picture material's base map and
|
||||
// serialize it - the source image file is not available in a build. 1:1 whenever the
|
||||
// material -> base map -> texture chain breaks.
|
||||
// Editor-only: derive _aspect (longer side = 1) from the assigned picture texture (falling
|
||||
// back to the picture material's base map) and serialize it - the source image file is not
|
||||
// available in a build. 1:1 whenever the whole chain breaks.
|
||||
void ResolveAspect()
|
||||
{
|
||||
var aspect = Vector2.one;
|
||||
Texture tex = null;
|
||||
if (_pictureMaterial)
|
||||
Texture tex = _pictureTexture;
|
||||
if (!tex && _pictureMaterial)
|
||||
{
|
||||
if (_pictureMaterial.HasProperty("_BaseMap")) tex = _pictureMaterial.GetTexture("_BaseMap");
|
||||
if (!tex) tex = _pictureMaterial.mainTexture;
|
||||
|
||||
@@ -4,7 +4,8 @@ MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _pictureMaterial: {instanceID: 0}
|
||||
- _pictureTexture: {instanceID: 0}
|
||||
- _pictureMaterial: {fileID: 2100000, guid: 9c88ebf613f4b1c49af2bb5a621d2dee, type: 2}
|
||||
- _innerMaterial: {fileID: 2100000, guid: bc0ac45503ad5c44b8b966da0d0a40d3, type: 2}
|
||||
- _frameMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
||||
- _backMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
||||
|
||||
Reference in new issue
Block a user