Make picture frame properties relative and fix picture aspect ratio
Frame thickness, corner radius, padding, inner depth and picture depth are now normalized factors (scale with Size, no dead clamp zones). Picture aspect is computed inside-out so padding and frame thickness no longer distort the image. New Frame Inner.mat as inner default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
07aef0c7b2
commit
6a15a68a2e
4 files changed
+244
-35
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 Inner
|
||||||
|
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: 0.8805031, g: 0.8805031, b: 0.8805031, a: 1}
|
||||||
|
- _Color: {r: 0.8805031, g: 0.8805031, b: 0.8805031, 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: bc0ac45503ad5c44b8b966da0d0a40d3
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 2100000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -3,11 +3,13 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Chameleon.Components
|
namespace Chameleon.Components
|
||||||
{
|
{
|
||||||
// Procedural picture frame: a box-profile frame with a recessed inner floor (FrameInnerDepth) and a
|
// Procedural picture frame, generated live in the editor (and at runtime) from the inspector
|
||||||
// picture plane offset relative to it (PictureDepth: + sunken, - raised plinth), generated live in the
|
// parameters. Sizing is inside-out: the picture keeps the texture's aspect ratio EXACTLY and the
|
||||||
// editor (and at runtime) from the inspector parameters - resize via Size (width/height follow the
|
// outer frame grows around it by padding + thickness (Size = longer outer side) - insetting a
|
||||||
// picture texture's aspect ratio), NOT via transform scale, so the frame profile never stretches
|
// uniform border from an aspect-scaled outer rect would distort the picture. All shape parameters
|
||||||
// (9-slice behaviour). Four submeshes with their own
|
// are relative fractions (thickness/padding of the picture's longer side, radius of the maximum
|
||||||
|
// 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
|
// 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.
|
||||||
//
|
//
|
||||||
@@ -17,7 +19,11 @@ namespace Chameleon.Components
|
|||||||
//
|
//
|
||||||
// GenerateColliders maintains matching BoxColliders (corner radius ignored): 4 border bars, a slab
|
// GenerateColliders maintains matching BoxColliders (corner radius ignored): 4 border bars, a slab
|
||||||
// behind the inner floor, plus a plinth box when the picture is raised. Only colliders tracked in
|
// behind the inner floor, plus a plinth box when the picture is raised. Only colliders tracked in
|
||||||
// _colliders are touched - manually added ones are left alone.
|
// _colliders are touched - manually added ones are left alone. The boxes live on a dedicated
|
||||||
|
// "Colliders" child: adding/removing a component on the inspected GameObject itself would rebuild
|
||||||
|
// its inspector mid-drag and release the slider being held (Unity 6's UI Toolkit inspector never
|
||||||
|
// sets GUIUtility.hotControl, so the mouse state cannot be polled) - on a child they can appear
|
||||||
|
// and disappear live without ever disturbing the editing.
|
||||||
[ExecuteAlways]
|
[ExecuteAlways]
|
||||||
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
||||||
public sealed class PictureFrameBuilder : MonoBehaviour
|
public sealed class PictureFrameBuilder : MonoBehaviour
|
||||||
@@ -37,22 +43,22 @@ namespace Chameleon.Components
|
|||||||
[SerializeField] Vector2 _aspect = Vector2.one;
|
[SerializeField] Vector2 _aspect = Vector2.one;
|
||||||
|
|
||||||
[Header("Frame")]
|
[Header("Frame")]
|
||||||
[Tooltip("Border width of the frame profile in the picture plane.")]
|
[Tooltip("Border width of the frame as a fraction of the picture's longer side.")]
|
||||||
[SerializeField, Range(0.001f, 1.000f)] float _frameThickness = 0.08f;
|
[SerializeField, Range(0f, 1f)] float _frameThickness = 0.05f;
|
||||||
[Tooltip("Depth of the frame, front face to back face.")]
|
[Tooltip("Depth of the frame, front face to back face.")]
|
||||||
[SerializeField, Range(0.002f, 0.500f)] float _frameDepth = 0.12f;
|
[SerializeField, Range(0.002f, 0.500f)] float _frameDepth = 0.05f;
|
||||||
[Tooltip("Rounding radius of the outer frame edges; 0 = sharp box. Clamped to thickness / half depth.")]
|
[Tooltip("Rounding of the outer frame edges relative to the maximum possible radius (thickness / half depth); 0 = sharp box, 1 = fully rounded.")]
|
||||||
[SerializeField, Range(0.000f, 0.500f)] float _cornerRadius;
|
[SerializeField, Range(0f, 1f)] float _cornerRadius = 0.2f;
|
||||||
[Tooltip("Arc segments of the edge rounding.")]
|
[Tooltip("Arc segments of the edge rounding.")]
|
||||||
[SerializeField, Range(1, 8)] int _bevelSegments = 4;
|
[SerializeField, Range(1, 8)] int _bevelSegments = 4;
|
||||||
[Tooltip("How deep behind the front face the inner floor (padding ring) sits.")]
|
[Tooltip("Inner floor relative to the frame depth: -1 = fully sunken (on the back plate), 0 = flush with the front face, 1 = a full frame depth in front.")]
|
||||||
[SerializeField, Range(0.000f, 0.498f)] float _frameInnerDepth = 0.06f;
|
[SerializeField, Range(-1f, 1f)] float _frameInnerDepth = -0.1f;
|
||||||
|
|
||||||
[Header("Picture")]
|
[Header("Picture")]
|
||||||
[Tooltip("Gap between the frame's inner edge and the picture (visible inner-material ring).")]
|
[Tooltip("Gap between the frame's inner edge and the picture as a fraction of the picture's longer side.")]
|
||||||
[SerializeField, Range(0.000f, 1.000f)] float _padding = 0.02f;
|
[SerializeField, Range(0f, 1f)] float _padding = 0.01f;
|
||||||
[Tooltip("Picture plane relative to the inner floor: positive sinks it into the frame, negative raises it out like a plinth, 0 = flush.")]
|
[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(-0.500f, 0.500f)] float _pictureDepth;
|
[SerializeField, Range(-1f, 1f)] float _pictureDepth = 0.1f;
|
||||||
|
|
||||||
[Header("Materials")]
|
[Header("Materials")]
|
||||||
[SerializeField] Material _pictureMaterial;
|
[SerializeField] Material _pictureMaterial;
|
||||||
@@ -65,6 +71,7 @@ namespace Chameleon.Components
|
|||||||
[SerializeField] bool _generateColliders = true;
|
[SerializeField] bool _generateColliders = true;
|
||||||
// Ownership list so rebuilds never touch colliders the user added by hand.
|
// Ownership list so rebuilds never touch colliders the user added by hand.
|
||||||
[SerializeField, HideInInspector] List<BoxCollider> _colliders = new List<BoxCollider>();
|
[SerializeField, HideInInspector] List<BoxCollider> _colliders = new List<BoxCollider>();
|
||||||
|
[SerializeField, HideInInspector] Transform _colliderRoot;
|
||||||
|
|
||||||
readonly List<Vector3> _verts = new List<Vector3>();
|
readonly List<Vector3> _verts = new List<Vector3>();
|
||||||
readonly List<Vector3> _normals = new List<Vector3>();
|
readonly List<Vector3> _normals = new List<Vector3>();
|
||||||
@@ -117,19 +124,30 @@ namespace Chameleon.Components
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
ResolveAspect();
|
ResolveAspect();
|
||||||
#endif
|
#endif
|
||||||
float w = Mathf.Max(_size * _aspect.x, 0.01f);
|
// Inside-out sizing: the picture keeps the texture aspect exactly; thickness and padding
|
||||||
float h = Mathf.Max(_size * _aspect.y, 0.01f);
|
// are fractions of the picture's longer side, and Size stays the longer OUTER side:
|
||||||
float t = Mathf.Clamp(_frameThickness, 0.001f, Mathf.Min(w, h) * 0.5f - 0.001f);
|
// size = pLong + 2*(t + pad) = pLong * (1 + thickness + padding). No clamp dead zones -
|
||||||
|
// every 0..1 combination yields valid geometry.
|
||||||
float d = Mathf.Max(_frameDepth, 0.002f);
|
float d = Mathf.Max(_frameDepth, 0.002f);
|
||||||
float r = Mathf.Min(_cornerRadius, Mathf.Min(t, d * 0.5f) - 0.0005f);
|
float pLong = Mathf.Max(_size, 0.01f) / (1f + _frameThickness + _padding);
|
||||||
|
float t = Mathf.Max(_frameThickness * pLong * 0.5f, 0.001f);
|
||||||
|
float pad = _padding * pLong * 0.5f;
|
||||||
|
float pw = Mathf.Max(pLong * _aspect.x, 0.001f);
|
||||||
|
float ph = Mathf.Max(pLong * _aspect.y, 0.001f);
|
||||||
|
float ow = pw + 2f * pad;
|
||||||
|
float oh = ph + 2f * pad;
|
||||||
|
float w = ow + 2f * t;
|
||||||
|
float h = oh + 2f * t;
|
||||||
|
float r = _cornerRadius * Mathf.Max(Mathf.Min(t, d * 0.5f) - 0.0005f, 0f);
|
||||||
if (r < 1e-4f) r = 0f;
|
if (r < 1e-4f) r = 0f;
|
||||||
float ow = w - 2f * t;
|
// Depths are fractions of the frame depth. Inner floor: -1 = back plate .. +1 = a full
|
||||||
float oh = h - 2f * t;
|
// frame depth in front of the face. Picture: interpolates from the back plate (-1) over
|
||||||
float pad = Mathf.Max(0f, Mathf.Min(_padding, Mathf.Min(ow, oh) * 0.5f - 0.001f));
|
// the inner floor (0) to a full frame depth in front (+1) - endpoints are absolute so
|
||||||
float pw = Mathf.Max(ow - 2f * pad, 0.001f);
|
// the extremes always mean "all the way in/out" regardless of where the floor sits.
|
||||||
float ph = Mathf.Max(oh - 2f * pad, 0.001f);
|
float id = -_frameInnerDepth * d;
|
||||||
float id = Mathf.Clamp(_frameInnerDepth, 0f, d);
|
float pz = _pictureDepth < 0f
|
||||||
float pz = Mathf.Min(id + _pictureDepth, d);
|
? Mathf.Lerp(id, d, -_pictureDepth)
|
||||||
|
: Mathf.Lerp(id, -d, _pictureDepth);
|
||||||
|
|
||||||
_verts.Clear();
|
_verts.Clear();
|
||||||
_normals.Clear();
|
_normals.Clear();
|
||||||
@@ -148,9 +166,11 @@ namespace Chameleon.Components
|
|||||||
if (Mathf.Abs(pz - id) > 1e-4f)
|
if (Mathf.Abs(pz - id) > 1e-4f)
|
||||||
PerimeterWalls(SubInner, pw * 0.5f, ph * 0.5f, Mathf.Min(pz, id), Mathf.Max(pz, id), pz > id ? -1f : 1f);
|
PerimeterWalls(SubInner, pw * 0.5f, ph * 0.5f, Mathf.Min(pz, id), Mathf.Max(pz, id), pz > id ? -1f : 1f);
|
||||||
|
|
||||||
// Inner cavity: padding ring around the picture + recess walls from the opening down to it.
|
// Inner cavity: padding ring around the picture + walls between the front face and the
|
||||||
|
// inner floor (inward recess when sunken, outward block sides when it protrudes).
|
||||||
Ring(SubInner, ow * 0.5f, oh * 0.5f, pw * 0.5f, ph * 0.5f, id);
|
Ring(SubInner, ow * 0.5f, oh * 0.5f, pw * 0.5f, ph * 0.5f, id);
|
||||||
if (id > 1e-4f) PerimeterWalls(SubInner, ow * 0.5f, oh * 0.5f, 0f, id, -1f);
|
if (Mathf.Abs(id) > 1e-4f)
|
||||||
|
PerimeterWalls(SubInner, ow * 0.5f, oh * 0.5f, Mathf.Min(id, 0f), Mathf.Max(id, 0f), id > 0f ? -1f : 1f);
|
||||||
|
|
||||||
// Frame: mitred front ring (from the rounded-edge inset to the opening), outer sides, bevels.
|
// Frame: mitred front ring (from the rounded-edge inset to the opening), outer sides, bevels.
|
||||||
Ring(SubFrame, w * 0.5f - r, h * 0.5f - r, ow * 0.5f, oh * 0.5f, 0f);
|
Ring(SubFrame, w * 0.5f - r, h * 0.5f - r, ow * 0.5f, oh * 0.5f, 0f);
|
||||||
@@ -185,6 +205,22 @@ namespace Chameleon.Components
|
|||||||
void RebuildColliders(float w, float h, float t, float d, float ow, float oh, float pw, float ph, float id, float pz)
|
void RebuildColliders(float w, float h, float t, float d, float ow, float oh, float pw, float ph, float id, float pz)
|
||||||
{
|
{
|
||||||
_colliders.RemoveAll(c => !c);
|
_colliders.RemoveAll(c => !c);
|
||||||
|
|
||||||
|
// Migrate colliders older versions created directly on this GameObject: they must move to
|
||||||
|
// the child root, otherwise every structural change here would rebuild the inspector.
|
||||||
|
for (int i = _colliders.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (_colliderRoot && _colliders[i].transform == _colliderRoot) continue;
|
||||||
|
DestroyOwned(_colliders[i]);
|
||||||
|
_colliders.RemoveAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The root child is fully owned, so any box that slipped out of the list (undo, aborted
|
||||||
|
// rebuild) is adopted back instead of leaking as an orphan.
|
||||||
|
if (_colliderRoot)
|
||||||
|
foreach (var box in _colliderRoot.GetComponents<BoxCollider>())
|
||||||
|
if (!_colliders.Contains(box)) _colliders.Add(box);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (_generateColliders)
|
if (_generateColliders)
|
||||||
{
|
{
|
||||||
@@ -206,20 +242,48 @@ namespace Chameleon.Components
|
|||||||
{
|
{
|
||||||
var extra = _colliders[i];
|
var extra = _colliders[i];
|
||||||
_colliders.RemoveAt(i);
|
_colliders.RemoveAt(i);
|
||||||
if (!extra) continue;
|
if (extra) DestroyOwned(extra);
|
||||||
if (Application.isPlaying) Destroy(extra);
|
}
|
||||||
else DestroyImmediate(extra);
|
|
||||||
|
// Generation switched off: drop the root too, but only when nothing foreign lives on it.
|
||||||
|
if (!_generateColliders && _colliderRoot && _colliderRoot.childCount == 0 &&
|
||||||
|
_colliderRoot.GetComponents<Component>().Length == 1)
|
||||||
|
{
|
||||||
|
var go = _colliderRoot.gameObject;
|
||||||
|
_colliderRoot = null;
|
||||||
|
DestroyOwned(go);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBox(int index, Vector3 center, Vector3 size)
|
void SetBox(int index, Vector3 center, Vector3 size)
|
||||||
{
|
{
|
||||||
while (_colliders.Count <= index) _colliders.Add(gameObject.AddComponent<BoxCollider>());
|
while (_colliders.Count <= index)
|
||||||
|
_colliders.Add(EnsureColliderRoot().gameObject.AddComponent<BoxCollider>());
|
||||||
var box = _colliders[index];
|
var box = _colliders[index];
|
||||||
if (box.center != center) box.center = center;
|
if (box.center != center) box.center = center;
|
||||||
if (box.size != size) box.size = size;
|
if (box.size != size) box.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform EnsureColliderRoot()
|
||||||
|
{
|
||||||
|
if (_colliderRoot) return _colliderRoot;
|
||||||
|
var existing = transform.Find("Colliders");
|
||||||
|
if (existing) _colliderRoot = existing;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var go = new GameObject("Colliders") { layer = gameObject.layer };
|
||||||
|
go.transform.SetParent(transform, false);
|
||||||
|
_colliderRoot = go.transform;
|
||||||
|
}
|
||||||
|
return _colliderRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyOwned(Object o)
|
||||||
|
{
|
||||||
|
if (Application.isPlaying) Destroy(o);
|
||||||
|
else DestroyImmediate(o);
|
||||||
|
}
|
||||||
|
|
||||||
void EnsureMesh(MeshFilter filter)
|
void EnsureMesh(MeshFilter filter)
|
||||||
{
|
{
|
||||||
string meshName = "PictureFrame " + GetInstanceID();
|
string meshName = "PictureFrame " + GetInstanceID();
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ MonoImporter:
|
|||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences:
|
defaultReferences:
|
||||||
- _pictureMaterial: {instanceID: 0}
|
- _pictureMaterial: {instanceID: 0}
|
||||||
- _innerMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
- _innerMaterial: {fileID: 2100000, guid: bc0ac45503ad5c44b8b966da0d0a40d3, type: 2}
|
||||||
- _frameMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
- _frameMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
||||||
- _backMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
- _backMaterial: {fileID: 2100000, guid: a7794896ef878a64399cca929db5c43c, type: 2}
|
||||||
|
- _colliderRoot: {instanceID: 0}
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
icon: {instanceID: 0}
|
icon: {instanceID: 0}
|
||||||
userData:
|
userData:
|
||||||
|
|||||||
Reference in new issue
Block a user