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
@@ -0,0 +1,136 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Frame Picture
|
||||
m_Shader: {fileID: 4800000, guid: 023c98a32f6cc00478e50479839530c5, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap:
|
||||
RenderType: Opaque
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AddPrecomputedVelocity: 0
|
||||
- _AlphaClip: 0
|
||||
- _AlphaToMask: 0
|
||||
- _Blend: 0
|
||||
- _BlendModePreserveSpecular: 1
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _DstBlendAlpha: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _SrcBlendAlpha: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _XRMotionVectorsPass: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &6905797306856702536
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||
version: 10
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c88ebf613f4b1c49af2bb5a621d2dee
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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