Files
XRLib/Assets/Scripts/Simulator/PropertyWindow/ProcessorProperty.cs

939 lines
38 KiB
C#
Raw Normal View History

2025-12-24 17:36:01 +09:00
using Simulator.Data;
2026-01-16 11:36:54 +09:00
using System;
2025-12-24 17:36:01 +09:00
using System.Collections.Generic;
using UnityEngine;
using UVC.UI.Window.PropertyWindow;
2026-01-16 11:36:54 +09:00
using static Unity.VisualScripting.Member;
2025-12-24 17:36:01 +09:00
public class ProcessorProperty : MonoBehaviour
{
[SerializeField]
private PropertyWindow propertyWindow;
2026-01-16 11:36:54 +09:00
ProcessorDataClass processor;
2025-12-24 17:36:01 +09:00
private void Awake()
{
propertyWindow.PropertyValueChanged += OnPropertyValueChanged;
}
public void SetProertyWindow(ComponentType type, ComponentDataBase data)
{
Debug.Log(data);
switch (type)
{
case ComponentType.Processor:
2026-01-16 11:36:54 +09:00
processor = data as ProcessorDataClass;
2025-12-24 17:36:01 +09:00
InitSourceProperty(data as ProcessorDataClass);
break;
}
}
void SaveChange(object source, object value, string name)
{
var path = PathIndexer.GetNodePath(source);
Patch updateData = new Patch();
updateData.value = value;
UpdateValueStack.AddPatch($"{path}.{name}", value);
}
public void InitSourceProperty(ProcessorDataClass processor)
{
2026-01-16 11:36:54 +09:00
var entries = new List<IPropertyEntry>();
entries.Add(new StringProperty("name", "이름", processor.name) { IsReadOnly = true });
entries.Add(
new StringProperty("label", "라벨", processor.label) { IsReadOnly = false }
.Bind(setter: v => { processor.label = v; SaveChange(processor, v, "label"); })
);
entries.Add(
new Vector2Property("Position", "X,Y 좌표(m)",
new Vector2(processor.physical.position.x, processor.physical.position.z))
{ IsReadOnly = false }
.Bind(setter: v => { processor.physical.position.x = v.x; processor.physical.position.z = v.y; SaveChange(processor, v, "physical.position"); })
);
entries.Add(
new ListProperty("processing_type", "처리 유형",
new List<string>() { "combine", "seperate", "transform" }, processor.processor_type)
{ IsReadOnly = false }
.Bind(setter: v => { processor.processor_type = v; SaveChange(processor, v, "processing_type"); })
);
entries.Add(
new ListProperty("input_selection_policy", "투입 정책",
new List<string>() { "round_robin", "random" }, processor.input_selection_policy)
{ IsReadOnly = false }
.Bind(setter: v => { processor.input_selection_policy = v; SaveChange(processor, v, "input_selection_policy"); })
);
entries.Add(CreateInputPrefabToggleGroup(processor));
foreach (var prefab in PrefabManager.Instance.prefabDict.Keys)
entries.Add(CreateInputPrefabDetailGroup(processor, prefab));
entries.Add(
new ListProperty("output_selection_policy", "출고 정책",
new List<string>() { "round_robin", "random" }, processor.output_selection_policy)
{ IsReadOnly = false }
.Bind(setter: v => { processor.output_selection_policy = v; SaveChange(processor, v, "output_selection_policy"); })
);
entries.Add(CreateOutputPrefabToggleGroup(processor));
foreach (var prefab in PrefabManager.Instance.prefabDict.Keys)
entries.Add(CreateOutputPrefabDetailGroup(processor, prefab));
entries.Add(new EnumProperty("display_mode_ProcessingTimePolicy", "처리 시간 정책", processor.processing_time_policy.policy).Bind(
setter: v =>
{
processor.processing_time_policy = PolicyFactory.Create(v.ToString()); SaveChange(processor, v.ToString(), "processing_time_policy.type");
}));
entries.Add(CreateProcessingTimePolicy_Constant(processor));
entries.Add(CreateProcessingTimePolicy_Normal(processor));
entries.Add(CreateProcessingTimePolicy_Uniform(processor));
entries.Add(CreateProcessingTimePolicy_Exponential(processor));
entries.Add(CreateProcessingTimePolicy_Triangular(processor));
entries.Add(new EnumProperty("display_mode_ReadyTimePolicy", "준비 시간 정책", processor.ready_time_policy.policy).Bind(
setter: v => {
processor.ready_time_policy = PolicyFactory.Create(v.ToString()); SaveChange(processor, v.ToString(), "ready_time_policy.type");
}));
entries.Add(CreateReadyTimePolicy_Constant(processor));
entries.Add(CreateReadyTimePolicy_Normal(processor));
entries.Add(CreateReadyTimePolicy_Uniform(processor));
entries.Add(CreateReadyTimePolicy_Exponential(processor));
entries.Add(CreateReadyTimePolicy_Triangular(processor));
entries.Add(new EnumProperty("display_mode_DefectTimePolicy", "불량률 정책", processor.defect_rate_policy.policy).Bind(
setter: v => {
processor.defect_rate_policy = PolicyFactory.Create(v.ToString()); SaveChange(processor, v.ToString(), "defect_rate_policy.type");
}));
entries.Add(CreateDefectRatePolicy_Constant(processor));
entries.Add(CreateDefectRatePolicy_Normal(processor));
entries.Add(CreateDefectRatePolicy_Uniform(processor));
entries.Add(CreateDefectRatePolicy_Exponential(processor));
entries.Add(CreateDefectRatePolicy_Triangular(processor));
entries.Add(CreateRequireResourceGroup(processor));
entries.Add(new BoolProperty("fms_input_enabled", "입력에 FMS 사용", processor.fms_input_enabled) { IsReadOnly = true });
entries.Add(new BoolProperty("fms_output_enabled", "출력에 FMS 사용", processor.fms_output_enabled) { IsReadOnly = true });
propertyWindow.LoadMixedProperties(entries);
HandleDisplayModeChanged_ProcessingTimePolicy(processor.processing_time_policy.policy.ToString());
HandleDisplayModeChanged_ReadyTimePolicy(processor.ready_time_policy.policy.ToString());
HandleDisplayModeChanged_DefectRatePolicy(processor.defect_rate_policy.policy.ToString());
SyncInputPrefabDetailVisibility(processor);
SyncOutputPrefabDetailVisibility(processor);
}
private void OnPropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
{
Debug.Log($"[PropertyChanged] Id:{e.PropertyId}, Type:{e.PropertyType}, Value:{e.NewValue}");
// 동적 그룹 표시/비표시 테스트
if (e.PropertyId == "display_mode_ProcessingTimePolicy")
{
string selectedMode = e.NewValue.ToString();
HandleDisplayModeChanged_ProcessingTimePolicy(selectedMode);
}
if (e.PropertyId == "display_mode_ReadyTimePolicy")
{
string selectedMode = e.NewValue.ToString();
HandleDisplayModeChanged_ReadyTimePolicy(selectedMode);
}
if (e.PropertyId == "display_mode_DefectPolicy")
{
string selectedMode = e.NewValue.ToString();
HandleDisplayModeChanged_DefectRatePolicy(selectedMode);
}
if (e.PropertyId == "input_selection_policy")
{
SyncInputPrefabDetailVisibility(processor);
}
if (e.PropertyId == "output_selection_policy")
{
SyncOutputPrefabDetailVisibility(processor);
}
}
#region
private PropertyGroup CreateInputPrefabToggleGroup(ProcessorDataClass processor)
{
var group = new PropertyGroup("InputPrefab", "투입 개체", isExpanded: true);
foreach (var prefab in PrefabManager.Instance.prefabDict.Keys)
{
bool enabled = processor.inputs != null && processor.inputs.Exists(x => x.prefab == prefab);
string itemId = $"input_prefab.toggle.{prefab}";
string detailGroupId = GetInputPrefabDetailGroupId(prefab);
var toggle = new BoolProperty($"input_{itemId}", prefab, enabled)
.Bind(setter: v =>
{
if (v) EnsureInputPrefab(processor, prefab);
else RemoveInputPrefab(processor, prefab);
SyncInputPrefabDetailVisibility(processor);
});
group.AddItem(toggle);
}
return group;
}
private static string GetInputPrefabDetailGroupId(string prefabKey)
=> $"InputPrefabDetail.{prefabKey}";
private PropertyGroup CreateInputPrefabDetailGroup(ProcessorDataClass processor, string prefabKey)
{
string groupId = GetInputPrefabDetailGroupId(prefabKey);
var group = new PropertyGroup(groupId, $"{prefabKey} 연결", isExpanded: true);
var entry = GetInputEntry(processor, prefabKey);
if (entry == null)
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
group.AddItem(new StringProperty($"{groupId}.empty", "연결", "투입 개체가 선택되지 않았습니다.")
2025-12-24 17:36:01 +09:00
{
IsReadOnly = true
2026-01-16 11:36:54 +09:00
});
return group;
}
entry.locations ??= new List<Prefab_location>();
string totalId = $"{groupId}.total_count";
var totalProp = new IntProperty(
totalId,
"총 개수",
Mathf.Max(0, entry.total_count),
isSlider: false,
minValue: 0,
maxValue: 9999
)
.Bind(setter: v =>
{
entry.total_count = Mathf.Max(0, v);
SaveChange(processor, entry.total_count, $"inputs[{prefabKey}].total_count");
});
group.AddItem(totalProp);
if (entry.locations.Count == 0)
{
group.AddItem(new StringProperty($"{groupId}.no_locs", "연결", "연결된 항목이 없습니다.")
{
IsReadOnly = true
});
return group;
}
foreach (var loc in entry.locations)
{
string locId = $"{groupId}.count.{loc.target}";
var countProp = new IntProperty(
locId,
loc.target,
Mathf.Max(0, loc.count),
isSlider: false,
minValue: 0,
maxValue: 9999
)
.Bind(setter: v =>
{
loc.count = Mathf.Max(0, v);
SaveChange(processor, loc.count, $"inputs[{prefabKey}].locations[target={loc.target}].count");
});
group.AddItem(countProp);
}
return group;
}
private void EnsureInputPrefab(ProcessorDataClass processor, string prefabKey)
{
processor.inputs ??= new List<Prefab_Data>();
if (processor.inputs.Exists(x => x.prefab == prefabKey))
return;
processor.inputs.Add(new Prefab_Data
{
prefab = prefabKey,
locations = new List<Prefab_location>(),
total_count = 0
});
}
private void RemoveInputPrefab(ProcessorDataClass processor, string prefabKey)
{
if (processor.inputs == null) return;
int idx = processor.inputs.FindIndex(x => x.prefab == prefabKey);
if (idx >= 0) processor.inputs.RemoveAt(idx);
}
private Prefab_Data GetInputEntry(ProcessorDataClass processor, string prefabKey)
{
if (processor.inputs == null) return null;
return processor.inputs.Find(x => x.prefab == prefabKey);
}
private void SyncInputPrefabDetailVisibility(ProcessorDataClass processor)
{
bool isRandom = string.Equals(processor.input_selection_policy, "random", StringComparison.OrdinalIgnoreCase);
foreach (var prefabKey in PrefabManager.Instance.prefabDict.Keys)
{
bool enabled = processor.inputs != null && processor.inputs.Exists(x => x != null && x.prefab == prefabKey);
string groupId = GetInputPrefabDetailGroupId(prefabKey);
propertyWindow.SetGroupVisibility(groupId, enabled);
if (!enabled)
continue;
var entry = GetInputEntry(processor, prefabKey);
string totalId = $"{groupId}.total_count";
if (propertyWindow.GetProperty(totalId) != null)
propertyWindow.SetPropertyVisibility(totalId, isRandom);
if (entry?.locations != null)
{
foreach (var loc in entry.locations)
{
string locId = $"{groupId}.count.{loc.target}";
if (propertyWindow.GetProperty(locId) != null)
propertyWindow.SetPropertyVisibility(locId, !isRandom);
}
}
}
}
#endregion
#region
private PropertyGroup CreateOutputPrefabToggleGroup(ProcessorDataClass processor)
{
var group = new PropertyGroup("OutputPrefab", "출고 개체", isExpanded: true);
foreach (var prefab in PrefabManager.Instance.prefabDict.Keys)
{
bool enabled = processor.outputs != null && processor.outputs.Exists(x => x.prefab == prefab);
string itemId = $"output_prefab.toggle.{prefab}";
string detailGroupId = GetOutputPrefabDetailGroupId(prefab);
var toggle = new BoolProperty($"output_{itemId}", prefab, enabled)
.Bind(setter: v =>
{
if (v) EnsureOutputPrefab(processor, prefab);
else RemoveOutputPrefab(processor, prefab);
SyncOutputPrefabDetailVisibility(processor);
});
group.AddItem(toggle);
}
return group;
}
private static string GetOutputPrefabDetailGroupId(string prefabKey)
=> $"OutputPrefabDetail.{prefabKey}";
private PropertyGroup CreateOutputPrefabDetailGroup(ProcessorDataClass processor, string prefabKey)
{
string groupId = GetOutputPrefabDetailGroupId(prefabKey);
var group = new PropertyGroup(groupId, $"{prefabKey} 연결", isExpanded: true);
var entry = GetInputEntry(processor, prefabKey);
if (entry == null)
{
group.AddItem(new StringProperty($"{groupId}.empty", "연결", "투입 개체가 선택되지 않았습니다.")
{
IsReadOnly = true
});
return group;
}
entry.locations ??= new List<Prefab_location>();
string totalId = $"{groupId}.total_count";
var totalProp = new IntProperty(
totalId,
"총 개수",
Mathf.Max(0, entry.total_count),
isSlider: false,
minValue: 0,
maxValue: 9999
)
.Bind(setter: v =>
{
entry.total_count = Mathf.Max(0, v);
SaveChange(processor, entry.total_count, $"outputs[{prefabKey}].total_count");
});
group.AddItem(totalProp);
if (entry.locations.Count == 0)
{
group.AddItem(new StringProperty($"{groupId}.no_locs", "연결", "연결된 항목이 없습니다.")
{
IsReadOnly = true
});
return group;
}
foreach (var loc in entry.locations)
{
string locId = $"{groupId}.count.{loc.target}";
var countProp = new IntProperty(
locId,
loc.target,
Mathf.Max(0, loc.count),
isSlider: false,
minValue: 0,
maxValue: 9999
)
.Bind(setter: v =>
{
loc.count = Mathf.Max(0, v);
SaveChange(processor, loc.count, $"outputs[{prefabKey}].locations[target={loc.target}].count");
});
group.AddItem(countProp);
}
return group;
}
private void EnsureOutputPrefab(ProcessorDataClass processor, string prefabKey)
{
processor.outputs ??= new List<Prefab_Data>();
if (processor.outputs.Exists(x => x.prefab == prefabKey))
return;
processor.outputs.Add(new Prefab_Data
{
prefab = prefabKey,
locations = new List<Prefab_location>(),
total_count = 0
});
}
private void RemoveOutputPrefab(ProcessorDataClass processor, string prefabKey)
{
if (processor.outputs == null) return;
int idx = processor.outputs.FindIndex(x => x.prefab == prefabKey);
if (idx >= 0) processor.outputs.RemoveAt(idx);
}
private Prefab_Data GetOutputEntry(ProcessorDataClass processor, string prefabKey)
{
if (processor.outputs == null) return null;
return processor.outputs.Find(x => x.prefab == prefabKey);
}
private void SyncOutputPrefabDetailVisibility(ProcessorDataClass processor)
{
bool isRandom = string.Equals(processor.output_selection_policy, "random", StringComparison.OrdinalIgnoreCase);
foreach (var prefabKey in PrefabManager.Instance.prefabDict.Keys)
{
bool enabled = processor.outputs != null && processor.outputs.Exists(x => x != null && x.prefab == prefabKey);
string groupId = GetOutputPrefabDetailGroupId(prefabKey);
propertyWindow.SetGroupVisibility(groupId, enabled);
if (!enabled)
continue;
var entry = GetOutputEntry(processor, prefabKey);
string totalId = $"{groupId}.total_count";
if (propertyWindow.GetProperty(totalId) != null)
propertyWindow.SetPropertyVisibility(totalId, isRandom);
if (entry?.locations != null)
{
foreach (var loc in entry.locations)
{
string locId = $"{groupId}.count.{loc.target}";
if (propertyWindow.GetProperty(locId) != null)
propertyWindow.SetPropertyVisibility(locId, !isRandom);
}
}
}
}
private PropertyGroup CreateOutputPrefabConnectGroup(ProcessorDataClass processor)
{
var group = new PropertyGroup($"PrefabConnect", "", isExpanded: true);
int count = 0;
foreach (var prefab in PrefabManager.Instance.prefabDict)
{
var property = new BoolProperty($"prefab{count++}", prefab.Key, false);
group.AddItem(property);
}
return group;
}
#endregion
private PropertyGroup CreateRequireResourceGroup(ProcessorDataClass processor)
{
var group = new PropertyGroup("RequireResource", "자원 할당", isExpanded: true);
// 1) required_resources 인덱스화
var requiredIndex = BuildRequiredIndex(processor);
int count = 0;
foreach (var resource in ComponentsManager.logicDetailData.infrastructure.resources)
{
if (!string.Equals(resource.type, "worker"))
continue;
// 2) 매칭 키 결정: 여기서는 resource.name을 키로 쓴다고 가정
var key = resource.name; // ★ label 말고 name/id 권장
bool isRequired = key != null && requiredIndex.ContainsKey(key);
// 3) 초기값을 isRequired로
var property = new BoolProperty($"required_resource[{count++}]", resource.label, isRequired);
// 4) (선택) 변경 시 processor.required_resources 업데이트 + Patch 저장까지 Bind로 연결
property.Bind(setter: v =>
{
SetRequiredResource(processor, key, v);
// SaveChange(processor or sourceRoot, processorRequiredPath...) 형태로 패치 기록
});
group.AddItem(property);
}
return group;
}
private void SetRequiredResource(ProcessorDataClass processor, string resourceName, bool required)
{
if (string.IsNullOrEmpty(resourceName)) return;
processor.required_resources ??= new List<Required_Resources>();
int idx = processor.required_resources.FindIndex(x => x != null && x.name == resourceName);
if (required)
{
if (idx < 0)
{
processor.required_resources.Add(new Required_Resources
{
name = resourceName,
count = 1,
selection_policy = "random" // 기본값 정책은 규칙에 맞춰 결정
});
}
else
{
// 이미 있으면 유지 (필요 시 count/policy 기본 보정)
}
}
else
{
if (idx >= 0)
processor.required_resources.RemoveAt(idx);
}
}
#region
private PropertyGroup CreateProcessingTimePolicy_Constant(ProcessorDataClass processor)
{
var group = new PropertyGroup("ProcessingTimePolicy_Constant", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ProcessingTimePolicy_Constant_Value", "상수 값", (processor.processing_time_policy as Policy_Constant) ?.value ?? 0f)
2025-12-24 17:36:01 +09:00
{
}.Bind(
2026-01-16 11:36:54 +09:00
setter: v => {(processor.processing_time_policy as Policy_Constant).value = v;SaveChange(processor,v,"processing_time_policy.value"); }
2025-12-24 17:36:01 +09:00
),
2026-01-16 11:36:54 +09:00
});
return group;
}
private PropertyGroup CreateProcessingTimePolicy_Normal(ProcessorDataClass processor)
{
var group = new PropertyGroup("ProcessingTimePolicy_Normal", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ProcessingTimePolicy_Normal_Mean", "정규 분포 표준치", (processor.processing_time_policy as Policy_Normal) ?.mean ?? 0f)
2025-12-24 17:36:01 +09:00
{
}.Bind(
2026-01-16 11:36:54 +09:00
setter: v => {(processor.processing_time_policy as Policy_Normal).mean = v;SaveChange(processor,v,"processing_time_policy.mean"); }
2025-12-24 17:36:01 +09:00
),
2026-01-16 11:36:54 +09:00
new FloatProperty("ProcessingTimePolicy_Normal_Gap", "정규 분포 표준 편차", (processor.processing_time_policy as Policy_Normal) ?.stddev ?? 0f)
2025-12-24 17:36:01 +09:00
{
}.Bind(
2026-01-16 11:36:54 +09:00
setter: v => {(processor.processing_time_policy as Policy_Normal).stddev = v;SaveChange(processor,v,"processing_time_policy.stddev"); }
2025-12-24 17:36:01 +09:00
),
2026-01-16 11:36:54 +09:00
});
return group;
}
2025-12-24 17:36:01 +09:00
2026-01-16 11:36:54 +09:00
private PropertyGroup CreateProcessingTimePolicy_Uniform(ProcessorDataClass processor)
{
var group = new PropertyGroup("ProcessingTimePolicy_Uniform", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ProcessingTimePolicy_Uniform_Min", "균등 분포 최소값", (processor.processing_time_policy as Policy_Uniform) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Uniform).min_val = v;SaveChange(processor,v,"processing_time_policy.min_val"); }
),
new FloatProperty("ProcessingTimePolicy_Uniform_Max", "균등 분포 최대값", (processor.processing_time_policy as Policy_Uniform) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Uniform).max_val = v;SaveChange(processor,v,"processing_time_policy.max_val"); }
),
});
return group;
}
2025-12-24 17:36:01 +09:00
2026-01-16 11:36:54 +09:00
private PropertyGroup CreateProcessingTimePolicy_Exponential(ProcessorDataClass processor)
{
var group = new PropertyGroup("ProcessingTimePolicy_Exponential", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ProcessingTimePolicy_Exponential_Mean", "지수 분포 평균치", (processor.processing_time_policy as Policy_Exponential) ?.mean ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Exponential).mean = v;SaveChange(processor,v,"processing_time_policy.mean"); }
),
});
return group;
2025-12-24 17:36:01 +09:00
}
2026-01-16 11:36:54 +09:00
private PropertyGroup CreateProcessingTimePolicy_Triangular(ProcessorDataClass processor)
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
var group = new PropertyGroup("ProcessingTimePolicy_Triangular", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ProcessingTimePolicy_Triangular_Min", "지수 분포 최소값", (processor.processing_time_policy as Policy_Triangular) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Triangular).min_val = v;SaveChange(processor,v,"processing_time_policy.min_val"); }
),
new FloatProperty("ProcessingTimePolicy_Triangular_Mean", "지수 분포 최빈값", (processor.processing_time_policy as Policy_Triangular) ?.mode ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Triangular).mode = v;SaveChange(processor,v,"processing_time_policy.mode"); }
),
new FloatProperty("ProcessingTimePolicy_Triangular_Max", "지수 분포 최대값", (processor.processing_time_policy as Policy_Triangular) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.processing_time_policy as Policy_Triangular).max_val = v;SaveChange(processor,v,"processing_time_policy.max_val"); }
),
});
return group;
}
2025-12-24 17:36:01 +09:00
2026-01-16 11:36:54 +09:00
private void HandleDisplayModeChanged_ProcessingTimePolicy(string mode)
{
// 모든 조건부 그룹 숨김
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Constant", false);
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Normal", false);
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Uniform", false);
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Exponential", false);
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Triangular", false);
// 선택된 모드에 따라 해당 그룹만 표시
switch (mode)
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
case "Constant":
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Constant", true);
break;
case "Normal":
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Normal", true);
break;
case "Uniform":
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Uniform", true);
break;
case "Exponential":
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Exponential", true);
break;
case "Triangular":
propertyWindow.SetGroupVisibility("ProcessingTimePolicy_Triangular", true);
break;
2025-12-24 17:36:01 +09:00
}
2026-01-16 11:36:54 +09:00
}
#endregion
#region
private PropertyGroup CreateReadyTimePolicy_Constant(ProcessorDataClass processor)
{
var group = new PropertyGroup("ReadyTimePolicy_Constant", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
new FloatProperty("ReadyTimePolicy_Constant_Value", "상수 값", (processor.ready_time_policy as Policy_Constant) ?.value ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Constant).value = v;SaveChange(processor,v,"ready_time_policy.value"); }
),
});
return group;
}
private PropertyGroup CreateReadyTimePolicy_Normal(ProcessorDataClass processor)
{
var group = new PropertyGroup("ReadyTimePolicy_Normal", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ReadyTimePolicy_Normal_Mean", "정규 분포 표준치", (processor.ready_time_policy as Policy_Normal) ?.mean ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Normal).mean = v;SaveChange(processor,v,"ready_time_policy.mean"); }
),
new FloatProperty("ReadyTimePolicy_Normal_Gap", "정규 분포 표준 편차", (processor.ready_time_policy as Policy_Normal) ?.stddev ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Normal).stddev = v;SaveChange(processor,v,"ready_time_policy.stddev"); }
),
});
return group;
}
private PropertyGroup CreateReadyTimePolicy_Uniform(ProcessorDataClass processor)
{
var group = new PropertyGroup("ReadyTimePolicy_Uniform", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ReadyTimePolicy_Uniform_Min", "균등 분포 최소값", (processor.ready_time_policy as Policy_Uniform) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Uniform).min_val = v;SaveChange(processor,v,"ready_time_policy.min_val"); }
),
new FloatProperty("ReadyTimePolicy_Uniform_Max", "균등 분포 최대값", (processor.ready_time_policy as Policy_Uniform) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Uniform).max_val = v;SaveChange(processor,v,"ready_time_policy.max_val"); }
),
});
return group;
}
private PropertyGroup CreateReadyTimePolicy_Exponential(ProcessorDataClass processor)
{
var group = new PropertyGroup("ReadyTimePolicy_Exponential", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ReadyTimePolicy_Exponential_Mean", "지수 분포 평균치", (processor.ready_time_policy as Policy_Exponential) ?.mean ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Exponential).mean = v;SaveChange(processor,v,"ready_time_policy.mean"); }
),
});
return group;
}
private PropertyGroup CreateReadyTimePolicy_Triangular(ProcessorDataClass processor)
{
var group = new PropertyGroup("ReadyTimePolicy_Triangular", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("ReadyTimePolicy_Triangular_Min", "지수 분포 최소값", (processor.ready_time_policy as Policy_Triangular) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Triangular).min_val = v;SaveChange(processor,v,"ready_time_policy.min_val"); }
),
new FloatProperty("ReadyTimePolicy_Triangular_Mean", "지수 분포 최빈값", (processor.ready_time_policy as Policy_Triangular) ?.mode ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Triangular).mode = v;SaveChange(processor,v,"ready_time_policy.mode"); }
),
new FloatProperty("ReadyTimePolicy_Triangular_Max", "지수 분포 최대값", (processor.ready_time_policy as Policy_Triangular) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.ready_time_policy as Policy_Triangular).max_val = v;SaveChange(processor,v,"ready_time_policy.max_val"); }
),
});
return group;
}
private void HandleDisplayModeChanged_ReadyTimePolicy(string mode)
{
// 모든 조건부 그룹 숨김
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Constant", false);
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Normal", false);
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Uniform", false);
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Exponential", false);
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Triangular", false);
// 선택된 모드에 따라 해당 그룹만 표시
switch (mode)
{
case "Constant":
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Constant", true);
break;
case "Normal":
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Normal", true);
break;
case "Uniform":
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Uniform", true);
break;
case "Exponential":
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Exponential", true);
break;
case "Triangular":
propertyWindow.SetGroupVisibility("ReadyTimePolicy_Triangular", true);
break;
2025-12-24 17:36:01 +09:00
}
2026-01-16 11:36:54 +09:00
}
#endregion
#region
private PropertyGroup CreateDefectRatePolicy_Constant(ProcessorDataClass processor)
{
var group = new PropertyGroup("DefectRatePolicy_Constant", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
new FloatProperty("DefectRatePolicy_Constant_Value", "상수 값", (processor.defect_rate_policy as Policy_Constant) ?.value ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Constant).value = v;SaveChange(processor,v,"defect_rate_policy.value"); }
),
});
return group;
}
private PropertyGroup CreateDefectRatePolicy_Normal(ProcessorDataClass processor)
{
var group = new PropertyGroup("DefectRatePolicy_Normal", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("DefectRatePolicy_Normal_Mean", "정규 분포 표준치", (processor.defect_rate_policy as Policy_Normal) ?.mean ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Normal).mean = v;SaveChange(processor,v,"defect_rate_policy.mean"); }
),
new FloatProperty("DefectRatePolicy_Normal_Gap", "정규 분포 표준 편차", (processor.defect_rate_policy as Policy_Normal) ?.stddev ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Normal).stddev = v;SaveChange(processor,v,"defect_rate_policy.stddev"); }
),
});
return group;
}
private PropertyGroup CreateDefectRatePolicy_Uniform(ProcessorDataClass processor)
{
var group = new PropertyGroup("DefectRatePolicy_Uniform", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("DefectRatePolicy_Uniform_Min", "균등 분포 최소값", (processor.defect_rate_policy as Policy_Uniform) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Uniform).min_val = v;SaveChange(processor,v,"defect_rate_policy.min_val"); }
),
new FloatProperty("DefectRatePolicy_Uniform_Max", "균등 분포 최대값", (processor.defect_rate_policy as Policy_Uniform) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Uniform).max_val = v;SaveChange(processor,v,"defect_rate_policy.max_val"); }
),
});
return group;
}
private PropertyGroup CreateDefectRatePolicy_Exponential(ProcessorDataClass processor)
{
var group = new PropertyGroup("DefectRatePolicy_Exponential", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("DefectRatePolicy_Exponential_Mean", "지수 분포 평균치", (processor.defect_rate_policy as Policy_Exponential) ?.mean ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Exponential).mean = v;SaveChange(processor,v,"defect_rate_policy.mean"); }
),
});
return group;
}
private PropertyGroup CreateDefectRatePolicy_Triangular(ProcessorDataClass processor)
{
var group = new PropertyGroup("DefectRatePolicy_Triangular", "", isExpanded: true);
group.AddItems(new IPropertyItem[]
{
new FloatProperty("DefectRatePolicy_Triangular_Min", "지수 분포 최소값", (processor.defect_rate_policy as Policy_Triangular) ?.min_val ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Triangular).min_val = v;SaveChange(processor,v,"defect_rate_policy.min_val"); }
),
new FloatProperty("DefectRatePolicy_Triangular_Mean", "지수 분포 최빈값", (processor.defect_rate_policy as Policy_Triangular) ?.mode ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Triangular).mode = v;SaveChange(processor,v,"defect_rate_policy.mode"); }
),
new FloatProperty("DefectRatePolicy_Triangular_Max", "지수 분포 최대값", (processor.defect_rate_policy as Policy_Triangular) ?.max_val ?? 0f)
{
}.Bind(
setter: v => {(processor.defect_rate_policy as Policy_Triangular).max_val = v;SaveChange(processor,v,"defect_rate_policy.max_val"); }
),
});
return group;
}
private void HandleDisplayModeChanged_DefectRatePolicy(string mode)
{
// 모든 조건부 그룹 숨김
propertyWindow.SetGroupVisibility("DefectRatePolicy_Constant", false);
propertyWindow.SetGroupVisibility("DefectRatePolicy_Normal", false);
propertyWindow.SetGroupVisibility("DefectRatePolicy_Uniform", false);
propertyWindow.SetGroupVisibility("DefectRatePolicy_Exponential", false);
propertyWindow.SetGroupVisibility("DefectRatePolicy_Triangular", false);
// 선택된 모드에 따라 해당 그룹만 표시
switch (mode)
{
case "Constant":
propertyWindow.SetGroupVisibility("DefectRatePolicy_Constant", true);
break;
case "Normal":
propertyWindow.SetGroupVisibility("DefectRatePolicy_Normal", true);
break;
case "Uniform":
propertyWindow.SetGroupVisibility("DefectRatePolicy_Uniform", true);
break;
case "Exponential":
propertyWindow.SetGroupVisibility("DefectRatePolicy_Exponential", true);
break;
case "Triangular":
propertyWindow.SetGroupVisibility("DefectRatePolicy_Triangular", true);
break;
2025-12-24 17:36:01 +09:00
}
}
2026-01-16 11:36:54 +09:00
#endregion
2025-12-24 17:36:01 +09:00
2026-01-16 11:36:54 +09:00
private Dictionary<string, Required_Resources> BuildRequiredIndex(ProcessorDataClass processor)
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
var dict = new Dictionary<string, Required_Resources>(StringComparer.Ordinal);
if (processor.required_resources == null) return dict;
foreach (var rr in processor.required_resources)
2025-12-24 17:36:01 +09:00
{
2026-01-16 11:36:54 +09:00
if (rr?.name == null) continue;
dict[rr.name] = rr;
2025-12-24 17:36:01 +09:00
}
2026-01-16 11:36:54 +09:00
return dict;
2025-12-24 17:36:01 +09:00
}
2026-01-16 11:36:54 +09:00
}