[정영민] 설비 겹침 정렬 기능 수정
26.03.11 설비 겹침 기능 수정
This commit is contained in:
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"visualstudiotoolsforunity.vstuc"
|
||||
]
|
||||
}
|
||||
10
.vscode/launch.json
vendored
Normal file
10
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to Unity",
|
||||
"type": "vstuc",
|
||||
"request": "attach"
|
||||
}
|
||||
]
|
||||
}
|
||||
71
.vscode/settings.json
vendored
Normal file
71
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"**/.DS_Store": true,
|
||||
"**/.git": true,
|
||||
"**/.vs": true,
|
||||
"**/.gitmodules": true,
|
||||
"**/.vsconfig": true,
|
||||
"**/*.booproj": true,
|
||||
"**/*.pidb": true,
|
||||
"**/*.suo": true,
|
||||
"**/*.user": true,
|
||||
"**/*.userprefs": true,
|
||||
"**/*.unityproj": true,
|
||||
"**/*.dll": true,
|
||||
"**/*.exe": true,
|
||||
"**/*.pdf": true,
|
||||
"**/*.mid": true,
|
||||
"**/*.midi": true,
|
||||
"**/*.wav": true,
|
||||
"**/*.gif": true,
|
||||
"**/*.ico": true,
|
||||
"**/*.jpg": true,
|
||||
"**/*.jpeg": true,
|
||||
"**/*.png": true,
|
||||
"**/*.psd": true,
|
||||
"**/*.tga": true,
|
||||
"**/*.tif": true,
|
||||
"**/*.tiff": true,
|
||||
"**/*.3ds": true,
|
||||
"**/*.3DS": true,
|
||||
"**/*.fbx": true,
|
||||
"**/*.FBX": true,
|
||||
"**/*.lxo": true,
|
||||
"**/*.LXO": true,
|
||||
"**/*.ma": true,
|
||||
"**/*.MA": true,
|
||||
"**/*.obj": true,
|
||||
"**/*.OBJ": true,
|
||||
"**/*.asset": true,
|
||||
"**/*.cubemap": true,
|
||||
"**/*.flare": true,
|
||||
"**/*.mat": true,
|
||||
"**/*.meta": true,
|
||||
"**/*.prefab": true,
|
||||
"**/*.unity": true,
|
||||
"build/": true,
|
||||
"Build/": true,
|
||||
"Library/": true,
|
||||
"library/": true,
|
||||
"obj/": true,
|
||||
"Obj/": true,
|
||||
"Logs/": true,
|
||||
"logs/": true,
|
||||
"ProjectSettings/": true,
|
||||
"UserSettings/": true,
|
||||
"temp/": true,
|
||||
"Temp/": true
|
||||
},
|
||||
"files.associations": {
|
||||
"*.asset": "yaml",
|
||||
"*.meta": "yaml",
|
||||
"*.prefab": "yaml",
|
||||
"*.unity": "yaml",
|
||||
},
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.sln": "*.csproj",
|
||||
"*.slnx": "*.csproj"
|
||||
},
|
||||
"dotnet.defaultSolution": "AZTECH_WB.slnx"
|
||||
}
|
||||
15
AZTECH_WB.slnx
Normal file
15
AZTECH_WB.slnx
Normal file
@@ -0,0 +1,15 @@
|
||||
<Solution>
|
||||
<Project Path="Assembly-CSharp.csproj" />
|
||||
<Project Path="com.Tivadar.Best.HTTP.csproj" />
|
||||
<Project Path="RenderHeads.AVProMovieCapture.Demos.csproj" />
|
||||
<Project Path="com.Tivadar.Best.MQTT.csproj" />
|
||||
<Project Path="RenderHeads.AVProMovieCapture.Runtime.csproj" />
|
||||
<Project Path="RenderHeads.AVProMovieCapture.Editor.csproj" />
|
||||
<Project Path="Assembly-CSharp-firstpass.csproj" />
|
||||
<Project Path="GLTFExporter.Runtime.csproj" />
|
||||
<Project Path="com.Tivadar.Best.WebSockets.csproj" />
|
||||
<Project Path="Assembly-CSharp-Editor.csproj" />
|
||||
<Project Path="SimpleFileBrowser.Runtime.csproj" />
|
||||
<Project Path="Assembly-CSharp-Editor-firstpass.csproj" />
|
||||
<Project Path="com.Tivadar.Best.HTTP.Profiler.Editor.csproj" />
|
||||
</Solution>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 527 B |
@@ -0,0 +1,117 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9074fab59981e24ea177f1361c7dd5f
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 527 B |
@@ -0,0 +1,117 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9458e5537061e7945a771b442a1d3413
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -496,15 +496,17 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
isInit: 0
|
||||
machineStatusItem: {fileID: 0}
|
||||
machines: []
|
||||
defaultNameHeight: 1.5
|
||||
originScale: {x: 1, y: 1, z: 1}
|
||||
activeIconEnable: 0
|
||||
minScale: 0.6
|
||||
maxScale: 1.2
|
||||
scaleClamp: 1
|
||||
uiElements: []
|
||||
worldOffset: {x: 0, y: 1.5, z: 0}
|
||||
verticalPadding: 0
|
||||
overlapThreshold: 2
|
||||
smoothSpeed: 50
|
||||
occlusionLayer:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
occlusionCheckInterval: 0.1
|
||||
minScale: 1.2
|
||||
maxScale: 1.4
|
||||
scaleSmoothing: 5
|
||||
--- !u!114 &69824778
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace AZTECHWB
|
||||
var moveVector = camera.transform.TransformDirection(x, y, -z);
|
||||
moveVector.y = 0;
|
||||
|
||||
//0.5 값은 카메라 속도 보정값
|
||||
//0.5 媛믪?? 移대찓?씪 ?냽?룄 蹂댁젙媛?
|
||||
moveVector *= (moveSpeed * 0.5f) * (currentDistance / maxDistance);
|
||||
nextPosition = cameraPivot.transform.position - moveVector;
|
||||
}
|
||||
@@ -303,10 +303,5 @@ namespace AZTECHWB
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetControllOptionValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ namespace AZTECHWB.Command
|
||||
var raycaster = AZTECHSceneMain.Instance.GetManager<Raycaster>();
|
||||
raycaster.SetInteractable(false);
|
||||
|
||||
//var building = AZTECHSceneMain.Instance.building;
|
||||
//building.ActiveRoof(true);
|
||||
|
||||
var machineStatusItemManager = AZTECHSceneMain.Instance.GetManager<MachineStatusItemManager>();
|
||||
machineStatusItemManager.SetActiveIcons(false);
|
||||
machineStatusItemManager.SetInteractableIcons(true);
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace AZTECHWB.Management
|
||||
machines = building.floors.SelectMany(f => f.machines).ToArray();
|
||||
foreach (var info in standardInfos)
|
||||
{
|
||||
var p = machines.Where(x => x.machineName.Equals(info.code)).FirstOrDefault();
|
||||
var p = machines.FirstOrDefault(x => x.machineName.Equals(info.code));
|
||||
if (p == null)
|
||||
continue;
|
||||
p.typeOptions = info.filterInfo;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using AZTECHWB.Command;
|
||||
using AZTECHWB.Constants;
|
||||
using AZTECHWB.Core;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
@@ -10,111 +10,50 @@ namespace AZTECHWB.Management
|
||||
{
|
||||
public class MachineStatusItemManager : Manager
|
||||
{
|
||||
public MachineStatusItem machineStatusItem;
|
||||
[Header("References")]
|
||||
private MachineStatusItem machineStatusItem;
|
||||
|
||||
private OrbitalController controller;
|
||||
private Building building;
|
||||
public Machine[] machines;
|
||||
private List<Machine> matchingMachines = new();
|
||||
[Header("Position Settings")]
|
||||
public Vector3 worldOffset = new Vector3(0, 1.5f, 0);
|
||||
public float verticalPadding = 5f;
|
||||
public float overlapThreshold = 2f;
|
||||
public float smoothSpeed = 10f;
|
||||
|
||||
[Header("Visibility Settings")]
|
||||
public LayerMask occlusionLayer;
|
||||
public float occlusionCheckInterval = 0.1f;
|
||||
|
||||
private Dictionary<MachineStatusItem, Vector2> smoothedPositions = new Dictionary<MachineStatusItem, Vector2>();
|
||||
private float occlusionTimer;
|
||||
|
||||
[Header("Scale Settings")]
|
||||
public float minScale = 0.5f; // 가장 멀 때 크기
|
||||
public float maxScale = 1.2f; // 가장 가까울 때 크기
|
||||
public float scaleSmoothing = 5f; // 스케일 변화 스무딩 속도
|
||||
private float maxDistance = 50f; // 스케일 계산 기준 최대 거리
|
||||
|
||||
private Dictionary<MachineStatusItem, float> smoothedScales = new Dictionary<MachineStatusItem, float>();
|
||||
private Dictionary<string, MachineStatusItem> machineIcons = new();
|
||||
private Dictionary<MachineStatusItem, Machine> iconToMachines = new();
|
||||
|
||||
public float defaultNameHeight;
|
||||
public Vector3 originScale;
|
||||
|
||||
public bool activeIconEnable;
|
||||
|
||||
[Range(0.1f, 0.8f)]
|
||||
public float minScale;
|
||||
[Range(0.5f, 1.5f)]
|
||||
public float maxScale;
|
||||
[Range(0.1f, 2f)]
|
||||
public float scaleClamp;
|
||||
private OrbitalController controller;
|
||||
private Machine[] machines;
|
||||
private bool activeIconEnable;
|
||||
|
||||
public override async UniTask Init()
|
||||
{
|
||||
controller = FindAnyObjectByType<OrbitalController>();
|
||||
machineStatusItem = Resources.Load<MachineStatusItem>($"{ResourceURL.uiPrefabFolderPath}{nameof(MachineStatusItem)}");
|
||||
|
||||
building = FindAnyObjectByType<Building>();
|
||||
controller = AZTECHAppMain.Instance.cameraController;
|
||||
machines = AZTECHSceneMain.Instance.building.floors.SelectMany(f => f.machines).ToArray();
|
||||
|
||||
maxDistance = controller.maxDistance;
|
||||
|
||||
await UniTask.CompletedTask;
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
uiElements.Clear();
|
||||
matchingMachines.Clear();
|
||||
iconToMachines.Clear();
|
||||
}
|
||||
public void SetMachineData(List<CompleteInfo> machineData)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (machines.Length <= 0)
|
||||
{
|
||||
machines = building.floors.SelectMany(f => f.machines).ToArray();
|
||||
}
|
||||
|
||||
foreach (var data in machineData)
|
||||
{
|
||||
var machine = FindMachineWithCode(data.worknm);
|
||||
|
||||
if (machine == null)
|
||||
continue;
|
||||
|
||||
if (machineIcons.ContainsKey(data.worknm))
|
||||
{
|
||||
machineIcons[data.worknm].SetData(data, machine.machineName);
|
||||
uiElements.Add(machineIcons[data.worknm].rectTransform);
|
||||
continue;
|
||||
}
|
||||
|
||||
var machineIcon = Instantiate(machineStatusItem, transform);
|
||||
machineIcon.Init(data.worknm);
|
||||
machineIcon.SetData(data, machine.machineName);
|
||||
machineIcon.onClickIcon += OnClickMachineKPI;
|
||||
|
||||
machineIcon.gameObject.SetActive(false);
|
||||
uiElements.Add(machineIcon.rectTransform);
|
||||
|
||||
machineIcons.Add(data.worknm, machineIcon);
|
||||
}
|
||||
|
||||
foreach (var machine in machines)
|
||||
{
|
||||
if (machineIcons.ContainsKey(machine.machineName))
|
||||
{
|
||||
machine.machineStatusItem = machineIcons[machine.machineName];
|
||||
matchingMachines.Add(machine);
|
||||
iconToMachines.Add(machine.machineStatusItem, machine);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Machine FindMachineWithCode(string worknm)
|
||||
{
|
||||
Machine machine = null;
|
||||
for (int i = 0; i < machines.Length; i++)
|
||||
{
|
||||
if (machines[i].machineName == worknm)
|
||||
{
|
||||
machine = machines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return machine;
|
||||
}
|
||||
private void OnClickMachineKPI(MachineStatusItem machineKPI)
|
||||
{
|
||||
machineKPI.transform.SetAsLastSibling();
|
||||
var currentMachine = iconToMachines[machineKPI];
|
||||
|
||||
new OpenMachineDetailDashboardPanelCommand(currentMachine, machineKPI.data).Execute();
|
||||
}
|
||||
|
||||
public void SetInteractableIcons(bool isActive)
|
||||
{
|
||||
foreach(var machineIcon in machineIcons.Values)
|
||||
foreach (var machineIcon in machineIcons.Values)
|
||||
{
|
||||
machineIcon.isInteractable = isActive;
|
||||
}
|
||||
@@ -129,148 +68,232 @@ namespace AZTECHWB.Management
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetMachineData(List<CompleteInfo> machineData)
|
||||
{
|
||||
foreach (var data in machineData)
|
||||
{
|
||||
var machine = FindMachineWithCode(data.worknm);
|
||||
|
||||
if (machine == null)
|
||||
continue;
|
||||
|
||||
if (machineIcons.ContainsKey(data.worknm))
|
||||
{
|
||||
machineIcons[data.worknm].SetData(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
var machineIcon = Instantiate(machineStatusItem, transform);
|
||||
machineIcon.Init(machine);
|
||||
machineIcon.SetData(data);
|
||||
machineIcon.onClickIcon += OnClickMachineKPI;
|
||||
|
||||
machineIcons.Add(data.worknm, machineIcon);
|
||||
machineIcon.gameObject.SetActive(false);
|
||||
|
||||
machine.machineStatusItem = machineIcon;
|
||||
iconToMachines.Add(machineIcon, machine);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClickMachineKPI(MachineStatusItem machineKPI)
|
||||
{
|
||||
machineKPI.transform.SetAsLastSibling();
|
||||
var currentMachine = iconToMachines[machineKPI];
|
||||
|
||||
new OpenMachineDetailDashboardPanelCommand(currentMachine, machineKPI.data).Execute();
|
||||
}
|
||||
|
||||
private Machine FindMachineWithCode(string worknm)
|
||||
{
|
||||
Machine machine = null;
|
||||
for (int i = 0; i < machines.Length; i++)
|
||||
{
|
||||
if (machines[i].machineName == worknm)
|
||||
{
|
||||
machine = machines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return machine;
|
||||
}
|
||||
private void LateUpdate()
|
||||
{
|
||||
GroupOverlappingUIElements();
|
||||
RangeDetection();
|
||||
if (machineIcons.Values.Count == 0 || controller.Camera == null)
|
||||
return;
|
||||
|
||||
List<MachineStatusItem> allLabels = new List<MachineStatusItem>(machineIcons.Values);
|
||||
|
||||
// 1단계: 전체 라벨 스크린 위치 & 거리 계산
|
||||
UpdateScreenData(allLabels);
|
||||
|
||||
// 2단계: 활성화 여부 판정 (화면 이탈 + 가려짐)
|
||||
occlusionTimer += Time.deltaTime;
|
||||
if (occlusionTimer >= occlusionCheckInterval)
|
||||
{
|
||||
UpdateVisibility(allLabels);
|
||||
occlusionTimer = 0f;
|
||||
}
|
||||
// 3단계: 활성화된 라벨만 카메라 거리순 정렬
|
||||
List<MachineStatusItem> visibleLabels = allLabels.FindAll(l => l.gameObject.activeSelf);
|
||||
visibleLabels.Sort((a, b) => a.distanceToCamera.CompareTo(b.distanceToCamera));
|
||||
|
||||
// 4단계: 거리에 따른 UI 크기 조정
|
||||
UpdateScales(visibleLabels);
|
||||
// 5단계: 겹침 해소 → 목표 위치 계산
|
||||
Dictionary<MachineStatusItem, Vector2> targetPositions = ResolveOverlaps(visibleLabels);
|
||||
// 6단계: 스무딩 적용 후 RectTransform에 반영
|
||||
ApplyPositions(targetPositions);
|
||||
}
|
||||
public List<RectTransform> uiElements = new List<RectTransform>();
|
||||
public List<List<RectTransform>> groupedElements = new List<List<RectTransform>>();
|
||||
|
||||
void GroupOverlappingUIElements()
|
||||
void UpdateScreenData(List<MachineStatusItem> labels)
|
||||
{
|
||||
foreach (var matchingMachine in matchingMachines)
|
||||
foreach (var label in labels)
|
||||
{
|
||||
var machinePos = matchingMachine.centerPos;
|
||||
var screenPos = controller.Camera.WorldToScreenPoint(new Vector3(machinePos.x, machinePos.y + defaultNameHeight, machinePos.z));
|
||||
if (label.targetTransform == null) continue;
|
||||
|
||||
matchingMachine.machineStatusItem.transform.position = screenPos;
|
||||
}
|
||||
groupedElements.Clear();
|
||||
var uncheckedElements = new List<RectTransform>(uiElements);
|
||||
Vector3 worldPos = label.targetTransform.position + worldOffset;
|
||||
Vector3 screenPos = controller.Camera.WorldToScreenPoint(worldPos);
|
||||
|
||||
while (uncheckedElements.Count > 0)
|
||||
{
|
||||
var currentElement = uncheckedElements[0];
|
||||
uncheckedElements.RemoveAt(0);
|
||||
var group = new List<RectTransform> { currentElement };
|
||||
|
||||
for (int i = uncheckedElements.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (AreRectanglesOverlapping(currentElement, uncheckedElements[i]))
|
||||
{
|
||||
group.Add(uncheckedElements[i]);
|
||||
uncheckedElements.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
groupedElements.Add(group);
|
||||
}
|
||||
|
||||
foreach (var group in groupedElements)
|
||||
{
|
||||
var centerPos = GroupCenterCalculate(group);
|
||||
|
||||
for (int i = 0; i < group.Count; i++)
|
||||
{
|
||||
var kpi = group[i];
|
||||
var newPos = new Vector3(centerPos.x, centerPos.y + kpi.rect.height * i * kpi.transform.localScale.y, centerPos.z);
|
||||
|
||||
kpi.transform.localPosition = newPos;
|
||||
}
|
||||
label.screenPosition = new Vector2(screenPos.x, screenPos.y);
|
||||
label.distanceToCamera = Vector3.Distance(controller.Camera.transform.position, label.targetTransform.position);
|
||||
}
|
||||
}
|
||||
private bool AreRectanglesOverlapping(RectTransform rectA, RectTransform rectB)
|
||||
{
|
||||
if (!rectB.gameObject.activeSelf)
|
||||
return false;
|
||||
|
||||
if (!rectA.gameObject.activeSelf)
|
||||
return false;
|
||||
|
||||
Rect rectAWorld = GetWorldRect(rectA);
|
||||
Rect rectBWorld = GetWorldRect(rectB);
|
||||
|
||||
return rectAWorld.Overlaps(rectBWorld);
|
||||
}
|
||||
private static Vector3[] worldCorners = new Vector3[4];
|
||||
private Rect GetWorldRect(RectTransform rectTransform)
|
||||
{
|
||||
rectTransform.GetWorldCorners(worldCorners);
|
||||
Vector2 min = worldCorners[0];
|
||||
Vector2 max = worldCorners[2];
|
||||
return new Rect(min, max - min);
|
||||
}
|
||||
private Vector3 GroupCenterCalculate(List<RectTransform> group)
|
||||
{
|
||||
var centerPos = Vector3.zero;
|
||||
group.Sort((a, b) => a.transform.localPosition.y.CompareTo(b.transform.localPosition.y));
|
||||
|
||||
foreach (var kpi in group)
|
||||
{
|
||||
centerPos += kpi.transform.localPosition;
|
||||
}
|
||||
centerPos /= group.Count;
|
||||
|
||||
return centerPos;
|
||||
}
|
||||
void RangeDetection()
|
||||
{
|
||||
var layerMask = LayerMask.GetMask("Camera", "Floor Wall");
|
||||
|
||||
float t = Mathf.InverseLerp(controller.maxDistance, 0f, controller.currentDistance);
|
||||
float scale = Mathf.Lerp(minScale, maxScale, t);
|
||||
var newScale = new Vector3(scale, scale, scale);
|
||||
|
||||
float expandScale = Mathf.Lerp(1.6f, 1f, t);
|
||||
var newExpandScale = new Vector3(expandScale, expandScale, expandScale);
|
||||
|
||||
foreach (var machine in matchingMachines)
|
||||
{
|
||||
MachineKPIsActive(machine, layerMask);
|
||||
var machineKPI = machine.machineStatusItem;
|
||||
machineKPI.transform.localScale = newScale;
|
||||
machineKPI.Expand_KPI.transform.localScale = newExpandScale;
|
||||
}
|
||||
}
|
||||
bool IsScreenRange(Machine machine)
|
||||
{
|
||||
Vector3 viewPos = controller.Camera.WorldToViewportPoint(machine.centerPos);
|
||||
|
||||
if (viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1 && viewPos.z > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void MachineKPIsActive(Machine machine, LayerMask layerMask)
|
||||
void UpdateVisibility(List<MachineStatusItem> labels)
|
||||
{
|
||||
if (!activeIconEnable) return;
|
||||
|
||||
var dir = (controller.Camera.transform.position - machine.centerPos).normalized;
|
||||
var radius = 1f;
|
||||
var ray = new Ray(machine.centerPos, dir);
|
||||
|
||||
if (Physics.SphereCast(ray, radius, out RaycastHit hit, Mathf.Infinity, layerMask))
|
||||
foreach (var label in labels)
|
||||
{
|
||||
var hitCameraLayer = hit.collider.gameObject.layer.Equals(LayerMask.NameToLayer("Camera"));
|
||||
// 카메라 뒤쪽 체크
|
||||
Vector3 screenPos = controller.Camera.WorldToScreenPoint(label.targetTransform.position + worldOffset);
|
||||
if (screenPos.z < 0)
|
||||
{
|
||||
label.gameObject.SetActive(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hitCameraLayer)
|
||||
// 화면 이탈 체크
|
||||
if (!IsOnScreen(label.screenPosition))
|
||||
{
|
||||
if (!IsScreenRange(machine))
|
||||
{
|
||||
machine.machineStatusItem.Deactive();
|
||||
}
|
||||
else
|
||||
{
|
||||
machine.machineStatusItem.Active();
|
||||
}
|
||||
label.gameObject.SetActive(false);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
// 특정 레이어에 가려짐 체크
|
||||
if (IsOccluded(label.targetTransform.position))
|
||||
{
|
||||
machine.machineStatusItem.Deactive();
|
||||
label.gameObject.SetActive(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
label.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOnScreen(Vector2 screenPos)
|
||||
{
|
||||
return screenPos.x >= 0 && screenPos.x <= Screen.width && screenPos.y >= 0 && screenPos.y <= Screen.height;
|
||||
}
|
||||
|
||||
bool IsOccluded(Vector3 targetWorldPos)
|
||||
{
|
||||
Vector3 camPos = controller.Camera.transform.position;
|
||||
Vector3 direction = targetWorldPos - camPos;
|
||||
float distance = direction.magnitude;
|
||||
|
||||
return Physics.Raycast(camPos, direction.normalized, distance - 0.1f, occlusionLayer);
|
||||
}
|
||||
|
||||
Dictionary<MachineStatusItem, Vector2> ResolveOverlaps(List<MachineStatusItem> visibleLabels)
|
||||
{
|
||||
Dictionary<MachineStatusItem, Vector2> targetPositions = new Dictionary<MachineStatusItem, Vector2>();
|
||||
List<Rect> placedRects = new List<Rect>();
|
||||
|
||||
foreach (var label in visibleLabels)
|
||||
{
|
||||
Vector2 size = label.GetSize();
|
||||
Vector2 targetPos = label.screenPosition;
|
||||
|
||||
bool overlapping = true;
|
||||
int maxIterations = 20;
|
||||
|
||||
while (overlapping && maxIterations-- > 0)
|
||||
{
|
||||
overlapping = false;
|
||||
Rect currentRect = GetRect(targetPos, size);
|
||||
|
||||
foreach (Rect placed in placedRects)
|
||||
{
|
||||
if (IsOverlapping(currentRect, placed))
|
||||
{
|
||||
// X는 겹친 라벨의 X로 고정, Y만 위로 밀어올림
|
||||
targetPos.x = placed.center.x;
|
||||
targetPos.y = placed.yMax + verticalPadding + size.y * 0.5f;
|
||||
overlapping = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetPositions[label] = targetPos;
|
||||
placedRects.Add(GetRect(targetPos, size));
|
||||
}
|
||||
|
||||
return targetPositions;
|
||||
}
|
||||
|
||||
void ApplyPositions(Dictionary<MachineStatusItem, Vector2> targetPositions)
|
||||
{
|
||||
foreach (var kvp in targetPositions)
|
||||
{
|
||||
MachineStatusItem label = kvp.Key;
|
||||
Vector2 target = kvp.Value;
|
||||
|
||||
if (!smoothedPositions.ContainsKey(label))
|
||||
smoothedPositions[label] = target;
|
||||
|
||||
smoothedPositions[label] = Vector2.Lerp(smoothedPositions[label],target,Time.deltaTime * smoothSpeed);
|
||||
|
||||
// Manager가 직접 RectTransform 조작
|
||||
label.rectTransform.position = new Vector3(smoothedPositions[label].x, smoothedPositions[label].y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateScales(List<MachineStatusItem> visibleLabels)
|
||||
{
|
||||
foreach (var label in visibleLabels)
|
||||
{
|
||||
// 거리 비율 → 목표 스케일 계산 (원본과 동일한 방식)
|
||||
float t = Mathf.InverseLerp(maxDistance, 0f, label.distanceToCamera);
|
||||
float targetScale = Mathf.Lerp(minScale, maxScale, t);
|
||||
|
||||
// 스무딩 초기값 설정
|
||||
if (!smoothedScales.ContainsKey(label))
|
||||
smoothedScales[label] = targetScale;
|
||||
|
||||
// Lerp로 부드럽게 스케일 변화
|
||||
smoothedScales[label] = Mathf.Lerp(
|
||||
smoothedScales[label],
|
||||
targetScale,
|
||||
Time.deltaTime * scaleSmoothing
|
||||
);
|
||||
|
||||
label.transform.localScale = Vector3.one * smoothedScales[label];
|
||||
}
|
||||
}
|
||||
|
||||
Rect GetRect(Vector2 centerPos, Vector2 size)
|
||||
{
|
||||
return new Rect(centerPos.x - size.x * 0.5f, centerPos.y - size.y * 0.5f, size.x, size.y);
|
||||
}
|
||||
|
||||
bool IsOverlapping(Rect a, Rect b)
|
||||
{
|
||||
return a.xMin < b.xMax - overlapThreshold && a.xMax > b.xMin + overlapThreshold &&
|
||||
a.yMin < b.yMax - overlapThreshold && a.yMax > b.yMin + overlapThreshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ namespace AZTECHWB.UI
|
||||
{
|
||||
var building = AZTECHSceneMain.Instance.building;
|
||||
var machines = building.floors.SelectMany(f => f.machines);
|
||||
var selectedMachine = machines.Where(m => m.machineName == alarmInfo.completeInfo.worknm).FirstOrDefault();
|
||||
var selectedMachine = machines.FirstOrDefault(m => m.machineName == alarmInfo.completeInfo.worknm);
|
||||
|
||||
new SelectedMachineCommand(selectedMachine, false).Execute();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace AZTECHWB.UI
|
||||
public Button Button_Close;
|
||||
|
||||
private LayerPanel layerPanel;
|
||||
public Action<bool> isClickUI;
|
||||
|
||||
public override async UniTask Init()
|
||||
{
|
||||
@@ -32,13 +31,11 @@ namespace AZTECHWB.UI
|
||||
gameObject.SetActive(true);
|
||||
layerPanel.Open();
|
||||
gameObject.transform.SetAsLastSibling();
|
||||
isClickUI?.Invoke(true);
|
||||
}
|
||||
public override void Close()
|
||||
{
|
||||
layerPanel.Close();
|
||||
gameObject.SetActive(false);
|
||||
isClickUI?.Invoke(false);
|
||||
}
|
||||
private void OnClickExitButton()
|
||||
{
|
||||
|
||||
@@ -99,6 +99,16 @@ namespace AZTECHWB.UI
|
||||
null,
|
||||
"설비 요약 정보 UI를 활성화/비활성화 합니다.");
|
||||
|
||||
toolbarModel.AddToggleButton("button_floor_control", true,
|
||||
"Prefabs/UI/Toolbar/images/ic_floor_active",
|
||||
"Prefabs/UI/Toolbar/images/ic_floor_deactive",
|
||||
(isSelected) =>
|
||||
{
|
||||
//AZTECHSceneMain.Instance.building.ActiveRoof(isSelected);
|
||||
},
|
||||
null,
|
||||
"설비가 없는 층을 활성화/비활성화 합니다.");
|
||||
|
||||
// --- 툴바 모델 구성 끝 ---
|
||||
toolbar.SetData(toolbarModel);
|
||||
toolbar.Initialize();
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace AZTECHWB.UI
|
||||
private TextMeshProUGUI Text_Selected;
|
||||
private TextMeshProUGUI Text_Deselected;
|
||||
|
||||
public Color selectColor;
|
||||
public Color origingColor;
|
||||
|
||||
public void SettingButton(string labelName)
|
||||
{
|
||||
transform.TryGetComponentInChildren(nameof(Text_Selected), out Text_Selected);
|
||||
@@ -24,8 +21,6 @@ namespace AZTECHWB.UI
|
||||
|
||||
var button = transform.GetComponentInChildren<Button>();
|
||||
button.onClick.AddListener(OnClickButton);
|
||||
|
||||
origingColor = button.image.color;
|
||||
}
|
||||
|
||||
private void OnClickButton()
|
||||
|
||||
@@ -14,8 +14,6 @@ namespace AZTECHWB
|
||||
{
|
||||
public RectTransform rectTransform;
|
||||
public CompleteInfo data;
|
||||
private List<CompleteInfo> alarmInfos = new();
|
||||
|
||||
public RectTransform Default_KPI;
|
||||
public RectTransform Expand_KPI;
|
||||
|
||||
@@ -38,12 +36,17 @@ namespace AZTECHWB
|
||||
public bool isInteractable;
|
||||
public bool isExpand;
|
||||
|
||||
[HideInInspector] public Transform targetTransform;
|
||||
[HideInInspector] public Vector2 screenPosition;
|
||||
[HideInInspector] public float distanceToCamera;
|
||||
|
||||
public Action<MachineStatusItem> onClickIcon;
|
||||
|
||||
public void Init(string itemName)
|
||||
public void Init(Machine machine)
|
||||
{
|
||||
isInteractable = true;
|
||||
gameObject.name = itemName;
|
||||
gameObject.name = machine.machineName;
|
||||
targetTransform = machine.transform;
|
||||
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
transform.TryGetComponentInChildren(nameof(Default_KPI), out Default_KPI);
|
||||
@@ -57,29 +60,25 @@ namespace AZTECHWB
|
||||
transform.TryGetComponentInChildren(nameof(Default_Alarm), out Default_Alarm);
|
||||
transform.TryGetComponentInChildren(nameof(Expand_Alarm), out Expand_Alarm);
|
||||
|
||||
//eorate
|
||||
transform.TryGetComponentInChildren(nameof(pvp), out pvp);
|
||||
transform.TryGetComponentInChildren(nameof(workcd), out workcd);
|
||||
//porate
|
||||
transform.TryGetComponentInChildren(nameof(goodqtyrate), out goodqtyrate);
|
||||
transform.TryGetComponentInChildren(nameof(workdt), out workdt);
|
||||
transform.TryGetComponentInChildren(nameof(wordno), out wordno);
|
||||
}
|
||||
|
||||
public void SetData(CompleteInfo data, string machineName)
|
||||
public void SetData(CompleteInfo data)
|
||||
{
|
||||
this.data = data;
|
||||
|
||||
//eorate.SetText(PercentCalculate(data.eorate).ToString() + "%");
|
||||
pvp.SetText(PercentCalculate(data.pvp).ToString() + "%");
|
||||
workcd.SetText(SetTextData(data.workcd));
|
||||
goodqtyrate.SetText(DecimalPointPercentCalculate(data.goodqtyrate).ToString() + "%");
|
||||
//porate.SetText(PercentCalculate(data.porate).ToString() + "%");
|
||||
workdt.SetText(CorrectionTime(data.workdt, "yyyy-MM-dd"));
|
||||
wordno.SetText(SetTextData(data.wordno));
|
||||
|
||||
DefaultMachineName.SetText(SetNameData(data.worknm, machineName));
|
||||
ExpandMachineName.SetText(SetNameData(data.worknm, machineName));
|
||||
DefaultMachineName.SetText(SetNameData(data.worknm));
|
||||
ExpandMachineName.SetText(SetNameData(data.worknm));
|
||||
|
||||
Default_Status.color = SetStatusColor(data.statusnm);
|
||||
Expand_Status.color = SetStatusColor(data.statusnm);
|
||||
@@ -87,27 +86,11 @@ namespace AZTECHWB
|
||||
DefaultMachineName.color = SetStatusColor(data.statusnm) == Color.gray ? Color.gray : DefaultMachineName.color;
|
||||
ExpandMachineName.color = SetStatusColor(data.statusnm) == Color.gray ? Color.gray : ExpandMachineName.color;
|
||||
}
|
||||
//public void SetAlarmData(List<CompleteInfo> alarmInfos)
|
||||
//{
|
||||
// if (alarmInfos != null || alarmInfos.Count != 0)
|
||||
// {
|
||||
// this.alarmInfos = alarmInfos;
|
||||
// var isAlarm = alarmInfos.Any(a => a.state.Trim().Equals("SET", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
// Default_Alarm.gameObject.SetActive(isAlarm);
|
||||
// Expand_Alarm.gameObject.SetActive(isAlarm);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Default_Alarm.gameObject.SetActive(false);
|
||||
// Expand_Alarm.gameObject.SetActive(false);
|
||||
// }
|
||||
//}
|
||||
private string SetNameData(string value, string machineName)
|
||||
private string SetNameData(string value)
|
||||
{
|
||||
if (!CheckDataExists(value))
|
||||
{
|
||||
return machineName;
|
||||
return gameObject.name;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -224,6 +207,13 @@ namespace AZTECHWB
|
||||
isExpand = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 GetSize()
|
||||
{
|
||||
Vector2 baseSize = rectTransform.sizeDelta;
|
||||
float scale = transform.localScale.x; // UpdateScales에서 적용한 스케일
|
||||
return baseSize * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ MonoBehaviour:
|
||||
m_ReflectionProbeBlending: 1
|
||||
m_ReflectionProbeBoxProjection: 1
|
||||
m_ReflectionProbeAtlas: 1
|
||||
m_ShadowDistance: 50
|
||||
m_ShadowDistance: 0
|
||||
m_ShadowCascadeCount: 4
|
||||
m_Cascade2Split: 0.25
|
||||
m_Cascade3Split: {x: 0.1, y: 0.3}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Resolution=1600x900
|
||||
ScreenMode=0
|
||||
Texture=0
|
||||
Shadow=1
|
||||
Shadow=0
|
||||
AA=2
|
||||
VSync=1
|
||||
AF=0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"com.unity.2d.sprite": "1.0.0",
|
||||
"com.unity.ai.navigation": "2.0.9",
|
||||
"com.unity.cloud.gltfast": "6.16.0",
|
||||
"com.unity.collab-proxy": "2.10.1",
|
||||
"com.unity.collab-proxy": "2.10.2",
|
||||
"com.unity.ide.rider": "3.0.38",
|
||||
"com.unity.ide.visualstudio": "2.0.25",
|
||||
"com.unity.inputsystem": "1.14.2",
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.collab-proxy": {
|
||||
"version": "2.10.1",
|
||||
"version": "2.10.2",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {},
|
||||
|
||||
Reference in New Issue
Block a user