#nullable enable using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; /// /// UTKStyleGuideSample의 Input 카테고리 Initialize 메서드들 /// public partial class UTKStyleGuideSample { #region Input Initializers private void InitializeInputFieldSample(VisualElement root) { // Validation - Email var emailInput = root.Q("input-validation-email"); if (emailInput != null) { emailInput.ErrorMessage = "올바른 이메일 형식이 아닙니다."; emailInput.Validation = () => emailInput.Value.Contains("@") && emailInput.Value.Contains("."); } // Validation - Required var requiredInput = root.Q("input-validation-required"); if (requiredInput != null) { requiredInput.ErrorMessage = "이름은 필수 항목입니다."; requiredInput.Validation = () => !string.IsNullOrWhiteSpace(requiredInput.Value); } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var emailValid = emailInput?.Validate() ?? true; var nameValid = requiredInput?.Validate() ?? true; var allValid = emailValid && nameValid; Debug.Log($"Validation: {(allValid ? "All Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { emailInput?.ClearError(); requiredInput?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 입력 필드 var input = new UTKInputField(); input.label = ""이름""; // Unity TextField의 label 프로퍼티 (소문자) input.Placeholder = ""이름을 입력하세요""; input.OnValueChanged += (value) => Debug.Log($""입력값: {value}""); // 비밀번호 입력 필드 var password = new UTKInputField(); password.label = ""비밀번호""; password.isPasswordField = true; // 변형 스타일 input.Variant = UTKInputField.InputFieldVariant.Outlined; // 이벤트 input.OnFocused += () => Debug.Log(""포커스""); input.OnBlurred += () => Debug.Log(""포커스 해제""); input.OnSubmit += (value) => Debug.Log($""제출: {value}""); // ── Validation (입력 검증) ────────────────────── // 1) ErrorMessage + Validation 함수 설정 var emailInput = new UTKInputField(""이메일"", ""example@email.com""); emailInput.ErrorMessage = ""올바른 이메일 형식이 아닙니다.""; emailInput.Validation = () => emailInput.Value.Contains(""@""); // → Submit(Enter) 또는 FocusOut 시 자동 검증 // → 실패: 붉은 외곽선 + 에러 메시지 표시 // → 통과: 에러 상태 자동 해제 // 2) 필수 입력 검증 var nameInput = new UTKInputField(""이름""); nameInput.ErrorMessage = ""이름은 필수 항목입니다.""; nameInput.Validation = () => !string.IsNullOrWhiteSpace(nameInput.Value); // 3) 강제 검증 호출 (폼 제출 버튼 등에서 사용) bool isValid = nameInput.Validate(); // Validation 실행 + UI 업데이트 if (!isValid) return; // 4) 에러 수동 해제 nameInput.ClearError(); // 5) 에러 메시지 직접 설정 (Validation 없이, 서버 오류 등) input.ErrorMessage = ""서버 오류가 발생했습니다.""; input.ErrorMessage = """"; // 오류 제거 // 비활성화 / 읽기 전용 input.IsEnabled = false; input.isReadOnly = true; input.multiline = true; // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 input.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } private void InitializeIntegerFieldSample(VisualElement root) { // Validation - Range (1~150) var rangeField = root.Q("int-validation-range"); if (rangeField != null) { rangeField.ErrorMessage = "나이는 1~150 사이여야 합니다."; rangeField.Validation = () => rangeField.Value >= 1 && rangeField.Value <= 150; } // Validation - Positive Only var positiveField = root.Q("int-validation-positive"); if (positiveField != null) { positiveField.ErrorMessage = "수량은 0보다 커야 합니다."; positiveField.Validation = () => positiveField.Value > 0; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("int-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var rangeValid = rangeField?.Validate() ?? true; var positiveValid = positiveField?.Validate() ?? true; var allValid = rangeValid && positiveValid; Debug.Log($"IntegerField Validation: {(allValid ? "All Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { rangeField?.ClearError(); positiveField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 정수 필드 var intField = new UTKIntegerField(""나이""); intField.Value = 25; intField.OnValueChanged += (value) => Debug.Log($""나이: {value}""); // 비활성화 intField.IsEnabled = false; // ── Validation (입력 검증) ────────────────────── // 1) ErrorMessage + Validation 함수 설정 var ageField = new UTKIntegerField(""나이"", 0); ageField.ErrorMessage = ""나이는 1~150 사이여야 합니다.""; ageField.Validation = () => ageField.Value >= 1 && ageField.Value <= 150; // → FocusOut 또는 Enter 시 자동 검증 // → 실패: 붉은 외곽선 + 에러 메시지 표시 // → 통과: 에러 상태 자동 해제 // 2) 양수만 허용 var qtyField = new UTKIntegerField(""수량"", 0); qtyField.ErrorMessage = ""수량은 0보다 커야 합니다.""; qtyField.Validation = () => qtyField.Value > 0; // 3) 강제 검증 호출 (폼 제출 버튼 등에서 사용) bool isValid = ageField.Validate(); // Validation 실행 + UI 업데이트 if (!isValid) return; // 4) 에러 수동 해제 ageField.ClearError(); // 5) 에러 메시지 직접 설정 (Validation 없이, 서버 오류 등) intField.ErrorMessage = ""서버 오류가 발생했습니다.""; intField.ErrorMessage = """"; // 오류 제거 // ── Label Min-Width ────────────────────────── intField.LabelMinWidth = 120f; // label의 min-width 설정", uxmlCode: @" "); } private void InitializeLongFieldSample(VisualElement root) { // Validation - Range (0 ~ 1,000,000) var rangeField = root.Q("long-validation-range"); if (rangeField != null) { rangeField.ErrorMessage = "파일 크기는 0 ~ 1,000,000 사이여야 합니다."; rangeField.Validation = () => rangeField.Value >= 0 && rangeField.Value <= 1000000; } // Validation - Positive Only var positiveField = root.Q("long-validation-positive"); if (positiveField != null) { positiveField.ErrorMessage = "개수는 0보다 커야 합니다."; positiveField.Validation = () => positiveField.Value > 0; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("long-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var rangeValid = rangeField?.Validate() ?? true; var positiveValid = positiveField?.Validate() ?? true; var allValid = rangeValid && positiveValid; Debug.Log($"LongField Validation: {(allValid ? "All Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { rangeField?.ClearError(); positiveField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 Long 필드 var longField = new UTKLongField(""파일 크기""); longField.Value = 1073741824; // 1GB longField.OnValueChanged += (value) => Debug.Log($""크기: {value} bytes""); // 비활성화 longField.IsEnabled = false; // ── Validation (입력 검증) ────────────────────── // 1) ErrorMessage + Validation 함수 설정 var sizeField = new UTKLongField(""파일 크기"", 0); sizeField.ErrorMessage = ""파일 크기는 0 ~ 1,000,000 사이여야 합니다.""; sizeField.Validation = () => sizeField.Value >= 0 && sizeField.Value <= 1000000; // 2) 강제 검증 호출 bool isValid = sizeField.Validate(); // 3) 에러 수동 해제 sizeField.ClearError(); // ── Label Min-Width ────────────────────────── longField.LabelMinWidth = 120f; // label의 min-width 설정", uxmlCode: @" "); } private void InitializeFloatFieldSample(VisualElement root) { // Validation - Range (0 ~ 100) var rangeField = root.Q("float-validation-range"); if (rangeField != null) { rangeField.ErrorMessage = "속도는 0 ~ 100 사이여야 합니다."; rangeField.Validation = () => rangeField.Value >= 0f && rangeField.Value <= 100f; } // Validation - Positive Only var positiveField = root.Q("float-validation-positive"); if (positiveField != null) { positiveField.ErrorMessage = "무게는 0보다 커야 합니다."; positiveField.Validation = () => positiveField.Value > 0f; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("float-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var rangeValid = rangeField?.Validate() ?? true; var positiveValid = positiveField?.Validate() ?? true; var allValid = rangeValid && positiveValid; Debug.Log($"FloatField Validation: {(allValid ? "All Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { rangeField?.ClearError(); positiveField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 Float 필드 var floatField = new UTKFloatField(""속도""); floatField.Value = 9.8f; floatField.OnValueChanged += (value) => Debug.Log($""속도: {value}""); // 비활성화 floatField.IsEnabled = false; // ── Validation (입력 검증) ────────────────────── // 1) ErrorMessage + Validation 함수 설정 var speedField = new UTKFloatField(""속도"", 0f); speedField.ErrorMessage = ""속도는 0 ~ 100 사이여야 합니다.""; speedField.Validation = () => speedField.Value >= 0f && speedField.Value <= 100f; // → FocusOut 또는 Enter 시 자동 검증 // 2) 강제 검증 호출 bool isValid = speedField.Validate(); // 3) 에러 수동 해제 speedField.ClearError(); // ── Label Min-Width ────────────────────────── floatField.LabelMinWidth = 120f; // label의 min-width 설정", uxmlCode: @" "); } private void InitializeDoubleFieldSample(VisualElement root) { // Validation - Range (0.0 ~ 100.0) var rangeField = root.Q("double-validation-range"); if (rangeField != null) { rangeField.ErrorMessage = "값은 0.0 ~ 100.0 사이여야 합니다."; rangeField.Validation = () => rangeField.Value >= 0.0 && rangeField.Value <= 100.0; } // Validation - Positive Only var positiveField = root.Q("double-validation-positive"); if (positiveField != null) { positiveField.ErrorMessage = "거리는 0보다 커야 합니다."; positiveField.Validation = () => positiveField.Value > 0.0; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("double-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var rangeValid = rangeField?.Validate() ?? true; var positiveValid = positiveField?.Validate() ?? true; var allValid = rangeValid && positiveValid; Debug.Log($"DoubleField Validation: {(allValid ? "All Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { rangeField?.ClearError(); positiveField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 Double 필드 var doubleField = new UTKDoubleField(""정밀도""); doubleField.Value = 3.141592653589793; doubleField.OnValueChanged += (value) => Debug.Log($""값: {value}""); // 비활성화 doubleField.IsEnabled = false; // ── Validation (입력 검증) ────────────────────── // 1) ErrorMessage + Validation 함수 설정 var percentField = new UTKDoubleField(""퍼센트"", 0); percentField.ErrorMessage = ""값은 0.0 ~ 100.0 사이여야 합니다.""; percentField.Validation = () => percentField.Value >= 0.0 && percentField.Value <= 100.0; // → FocusOut 또는 Enter 시 자동 검증 // 2) 강제 검증 호출 bool isValid = percentField.Validate(); // 3) 에러 수동 해제 percentField.ClearError(); // ── Label Min-Width ────────────────────────── doubleField.LabelMinWidth = 120f; // label의 min-width 설정", uxmlCode: @" "); } private void InitializeNumberStepperSample(VisualElement root) { var disabledRow = root.Q("stepper-disabled-row"); if (disabledRow != null) { var stepper = new UTKIntStepper(0, 100, 30, 1); stepper.style.width = 150; stepper.SetEnabled(false); disabledRow.Add(stepper); } // Validation - Even Number Only UTKIntStepper? validationStepper = null; var validationRow = root.Q("stepper-validation-row"); if (validationRow != null) { validationStepper = new UTKIntStepper(0, 100, 1, 1); validationStepper.style.width = 150; validationStepper.ErrorMessage = "짝수만 입력 가능합니다."; validationStepper.Validation = () => validationStepper.Value % 2 == 0; validationRow.Add(validationStepper); validationStepper.Validate(); } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("stepper-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationStepper?.Validate() ?? true; Debug.Log($"IntStepper Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationStepper?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var stepper = new UTKIntStepper(minValue: 0, maxValue: 100, value: 50, step: 1); stepper.OnValueChanged += (newValue) => Debug.Log($""Value: {newValue}""); // Step 설정 var stepper5 = new UTKIntStepper(0, 100, 25, 5); // Step 5씩 증감 // Wrap Around (최소/최대값에서 순환) var wrapStepper = new UTKIntStepper(0, 100, 0, 10); wrapStepper.WrapAround = true; // 0 -> -10 시 100으로 순환 // 비활성화 var disabledStepper = new UTKIntStepper(0, 100, 30, 1); disabledStepper.SetEnabled(false); // 속성 변경 stepper.Value = 75; stepper.MinValue = 10; stepper.MaxValue = 90; stepper.Step = 2; // ── Validation (입력 검증) ────────────────────── var evenStepper = new UTKIntStepper(0, 100, 0, 1); evenStepper.ErrorMessage = ""짝수만 입력 가능합니다.""; evenStepper.Validation = () => evenStepper.Value % 2 == 0; bool isValid = evenStepper.Validate(); evenStepper.ClearError();", uxmlCode: @" "); } private void InitializeFloatStepperSample(VisualElement root) { var disabledRow = root.Q("float-stepper-disabled-row"); if (disabledRow != null) { var stepper = new UTKFloatStepper(0f, 10f, 3.5f, 0.1f); stepper.style.width = 150; stepper.SetEnabled(false); disabledRow.Add(stepper); } // Validation - Non-Zero UTKFloatStepper? validationStepper = null; var validationRow = root.Q("float-stepper-validation-row"); if (validationRow != null) { validationStepper = new UTKFloatStepper(0f, 10f, 0f, 0.1f); validationStepper.style.width = 150; validationStepper.ErrorMessage = "값은 0이 될 수 없습니다."; validationStepper.Validation = () => validationStepper.Value != 0f; validationRow.Add(validationStepper); validationStepper.Validate(); } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("float-stepper-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationStepper?.Validate() ?? true; Debug.Log($"FloatStepper Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationStepper?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var stepper = new UTKFloatStepper(minValue: 0f, maxValue: 10f, initialValue: 5.5f, step: 0.1f); stepper.OnValueChanged += (newValue) => Debug.Log($""Value: {newValue}""); // Step 설정 var stepper05 = new UTKFloatStepper(0f, 10f, 2.5f, 0.5f); // Step 0.5씩 증감 // Wrap Around (최소/최대값에서 순환) var wrapStepper = new UTKFloatStepper(0f, 1f, 0.5f, 0.1f); wrapStepper.WrapAround = true; // 0.0 -> -0.1 시 1.0으로 순환 // 비활성화 var disabledStepper = new UTKFloatStepper(0f, 10f, 3.5f, 0.1f); disabledStepper.SetEnabled(false); // 속성 변경 stepper.Value = 7.5f; stepper.MinValue = 1f; stepper.MaxValue = 9f; stepper.Step = 0.25f; // 프로그래밍 방식으로 값 변경 stepper.Increment(); // Step만큼 증가 stepper.Decrement(); // Step만큼 감소 stepper.SetValue(4.2f); // 직접 설정 // ── Validation (입력 검증) ────────────────────── var nonZeroStepper = new UTKFloatStepper(0f, 10f, 0f, 0.1f); nonZeroStepper.ErrorMessage = ""값은 0이 될 수 없습니다.""; nonZeroStepper.Validation = () => nonZeroStepper.Value != 0f; bool isValid = nonZeroStepper.Validate(); nonZeroStepper.ClearError();", uxmlCode: @" "); } private void InitializeVector2FieldSample(VisualElement root) { var field = root.Q("vec2-position"); if (field != null) { field.Value = new Vector2(100, 200); } // Validation - Non-Zero var validationField = root.Q("vec2-validation"); if (validationField != null) { validationField.ErrorMessage = "방향 벡터는 (0,0)이 될 수 없습니다."; validationField.Validation = () => validationField.Value != Vector2.zero; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("vec2-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationField?.Validate() ?? true; Debug.Log($"Vector2Field Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var positionField = new UTKVector2Field(""Position""); positionField.Value = new Vector2(100, 200); positionField.OnValueChanged += (newValue) => Debug.Log($""Position: {newValue}""); // 라벨 없이 var field = new UTKVector2Field(); field.label = """"; // 읽기 전용 var readOnlyField = new UTKVector2Field(""ReadOnly""); readOnlyField.SetEnabled(false); // ── Validation (입력 검증) ────────────────────── var dirField = new UTKVector2Field(""Direction""); dirField.ErrorMessage = ""방향 벡터는 (0,0)이 될 수 없습니다.""; dirField.Validation = () => dirField.Value != Vector2.zero; bool isValid = dirField.Validate(); dirField.ClearError(); // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 positionField.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } private void InitializeVector3FieldSample(VisualElement root) { var field = root.Q("vec3-position"); if (field != null) { field.Value = new Vector3(10, 20, 30); } // Validation - Non-Zero var validationField = root.Q("vec3-validation"); if (validationField != null) { validationField.ErrorMessage = "스케일 벡터는 (0,0,0)이 될 수 없습니다."; validationField.Validation = () => validationField.Value != Vector3.zero; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("vec3-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationField?.Validate() ?? true; Debug.Log($"Vector3Field Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var positionField = new UTKVector3Field(""Position""); positionField.Value = new Vector3(10, 20, 30); positionField.OnValueChanged += (newValue) => Debug.Log($""Position: {newValue}""); // 회전 벡터 var rotationField = new UTKVector3Field(""Rotation""); rotationField.Value = new Vector3(0, 90, 0); // 비활성화 var disabledField = new UTKVector3Field(""Disabled""); disabledField.SetEnabled(false); // ── Validation (입력 검증) ────────────────────── var scaleField = new UTKVector3Field(""Scale""); scaleField.ErrorMessage = ""스케일 벡터는 (0,0,0)이 될 수 없습니다.""; scaleField.Validation = () => scaleField.Value != Vector3.zero; bool isValid = scaleField.Validate(); scaleField.ClearError(); // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 positionField.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } private void InitializeVector4FieldSample(VisualElement root) { var field = root.Q("vec4-color"); if (field != null) { field.Value = new Vector4(1, 0.5f, 0.25f, 1); } // Validation - 0~1 Range (RGBA) var validationField = root.Q("vec4-validation"); if (validationField != null) { validationField.Value = new Vector4(1, 0.5f, 0.25f, 1); validationField.ErrorMessage = "RGBA 값은 모두 0~1 사이여야 합니다."; validationField.Validation = () => { var v = validationField.Value; return v.x >= 0f && v.x <= 1f && v.y >= 0f && v.y <= 1f && v.z >= 0f && v.z <= 1f && v.w >= 0f && v.w <= 1f; }; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("vec4-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationField?.Validate() ?? true; Debug.Log($"Vector4Field Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var colorField = new UTKVector4Field(""Color""); colorField.Value = new Vector4(1, 0.5f, 0.25f, 1); // RGBA colorField.OnValueChanged += (newValue) => Debug.Log($""Color: {newValue}""); // 쿼터니언 값 var quaternionField = new UTKVector4Field(""Quaternion""); var quat = Quaternion.identity; quaternionField.Value = new Vector4(quat.x, quat.y, quat.z, quat.w); // 비활성화 var disabledField = new UTKVector4Field(""Disabled""); disabledField.SetEnabled(false); // ── Validation (입력 검증) ────────────────────── var rgbaField = new UTKVector4Field(""RGBA""); rgbaField.ErrorMessage = ""RGBA 값은 모두 0~1 사이여야 합니다.""; rgbaField.Validation = () => { var v = rgbaField.Value; return v.x >= 0f && v.x <= 1f && v.y >= 0f && v.y <= 1f && v.z >= 0f && v.z <= 1f && v.w >= 0f && v.w <= 1f; }; bool isValid = rgbaField.Validate(); rgbaField.ClearError(); // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 colorField.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } private void InitializeRectFieldSample(VisualElement root) { var field = root.Q("rect-area"); if (field != null) { field.Value = new Rect(10, 20, 100, 50); } // Validation - Positive Size var validationField = root.Q("rect-validation"); if (validationField != null) { validationField.ErrorMessage = "Width와 Height는 0보다 커야 합니다."; validationField.Validation = () => validationField.Value.width > 0 && validationField.Value.height > 0; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("rect-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationField?.Validate() ?? true; Debug.Log($"RectField Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var areaField = new UTKRectField(""Area""); areaField.Value = new Rect(10, 20, 100, 50); // x, y, width, height areaField.OnValueChanged += (newValue) => Debug.Log($""Rect: {newValue}""); // 화면 영역 설정 var screenArea = new UTKRectField(""Screen Area""); screenArea.Value = new Rect(0, 0, Screen.width, Screen.height); // 비활성화 var disabledField = new UTKRectField(""Disabled""); disabledField.SetEnabled(false); // ── Validation (입력 검증) ────────────────────── var viewportField = new UTKRectField(""Viewport""); viewportField.ErrorMessage = ""Width와 Height는 0보다 커야 합니다.""; viewportField.Validation = () => viewportField.Value.width > 0 && viewportField.Value.height > 0; bool isValid = viewportField.Validate(); viewportField.ClearError(); // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 areaField.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } private void InitializeBoundsFieldSample(VisualElement root) { var field = root.Q("bounds-collision"); if (field != null) { field.Value = new Bounds(new Vector3(0, 1, 0), new Vector3(2, 2, 2)); } // Validation - Positive Extents var validationField = root.Q("bounds-validation"); if (validationField != null) { validationField.ErrorMessage = "Extents는 모두 0보다 커야 합니다."; validationField.Validation = () => { var ext = validationField.Value.extents; return ext.x > 0f && ext.y > 0f && ext.z > 0f; }; } // Validate All / Clear Errors 버튼 var buttonRow = root.Q("bounds-validation-button-row"); if (buttonRow != null) { var validateBtn = new UTKButton("Validate All", variant: UTKButton.ButtonVariant.Primary); validateBtn.OnClicked += () => { var isValid = validationField?.Validate() ?? true; Debug.Log($"BoundsField Validation: {(isValid ? "Passed" : "Has Errors")}"); }; buttonRow.Add(validateBtn); var clearBtn = new UTKButton("Clear Errors"); clearBtn.OnClicked += () => { validationField?.ClearError(); }; buttonRow.Add(clearBtn); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var boundsField = new UTKBoundsField(""Bounds""); var center = new Vector3(0, 1, 0); var size = new Vector3(2, 2, 2); boundsField.Value = new Bounds(center, size); boundsField.OnValueChanged += (newValue) => Debug.Log($""Bounds: {newValue}""); // 콜라이더 범위 설정 var collisionField = new UTKBoundsField(""Collision Bounds""); collisionField.Value = new Bounds(Vector3.zero, Vector3.one * 5); // 비활성화 var disabledField = new UTKBoundsField(""Disabled""); disabledField.SetEnabled(false); // ── Validation (입력 검증) ────────────────────── var colliderField = new UTKBoundsField(""Collider""); colliderField.ErrorMessage = ""Extents는 모두 0보다 커야 합니다.""; colliderField.Validation = () => { var ext = colliderField.Value.extents; return ext.x > 0f && ext.y > 0f && ext.z > 0f; }; bool isValid = colliderField.Validate(); colliderField.ClearError(); // ── Label Min-Width ────────────────────────── // label이 있을 때 .unity-label의 min-width를 설정 boundsField.LabelMinWidth = 120f; // 120px (-1이면 미설정)", uxmlCode: @" "); } #endregion #region Dropdown Initializers private void InitializeDropdownSample(VisualElement root) { var normalRow = root.Q("dropdown-normal-row"); if (normalRow != null) { var dropdown = new UTKDropdown("Select Option"); dropdown.SetOptions(new List { "Option 1", "Option 2", "Option 3", "Option 4" }); dropdown.SelectedIndex = 0; normalRow.Add(dropdown); } var disabledRow = root.Q("dropdown-disabled-row"); if (disabledRow != null) { var dropdown = new UTKDropdown("Disabled"); dropdown.SetOptions(new List { "Option 1", "Option 2" }); dropdown.SelectedIndex = 0; dropdown.IsEnabled = false; disabledRow.Add(dropdown); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var dropdown = new UTKDropdown(""Select Option""); dropdown.SetOptions(new List { ""Option 1"", ""Option 2"", ""Option 3"", ""Option 4"" }); dropdown.SelectedIndex = 0; // 선택 이벤트 (인덱스와 값 모두 전달) dropdown.OnSelectionChanged += (index, value) => { Debug.Log($""선택: [{index}] {value}""); }; // 생성자로 한 번에 설정 var sortDropdown = new UTKDropdown(""정렬"", new List { ""이름"", ""날짜"", ""크기"" }); // 선택된 값 가져오기 var selectedIndex = dropdown.SelectedIndex; var selectedValue = dropdown.SelectedValue; // 옵션 동적 변경 dropdown.SetOptions(new List { ""New 1"", ""New 2"", ""New 3"" }); // 프로그램으로 선택 (인덱스로) dropdown.SelectedIndex = 2; // 프로그램으로 선택 (값으로) dropdown.SetSelectedValue(""Option 2""); // 이벤트 없이 값 변경 (초기화 시 유용) sortDropdown.SetSelectedValue(""크기"", notify: false); // 동적으로 옵션 추가 dropdown.AddOption(""Option 5""); // Disabled var disabledDropdown = new UTKDropdown(""Disabled""); disabledDropdown.SetOptions(new List { ""Option 1"", ""Option 2"" }); disabledDropdown.SelectedIndex = 0; disabledDropdown.IsEnabled = false;", uxmlCode: @" "); } private enum SampleEnum { Option1, Option2, Option3 } private void InitializeEnumDropDownSample(VisualElement root) { var enumRow = root.Q("enum-dropdown-row"); if (enumRow != null) { var field = new UTKEnumDropDown("Choice", SampleEnum.Option1); enumRow.Add(field); } SetCodeSamples(root, csharpCode: @"// Enum 정의 public enum SampleEnum { Option1, Option2, Option3 } public enum Difficulty { Easy, Normal, Hard, Expert } // 기본 사용법 (생성자로 label과 기본값 지정) var enumField = new UTKEnumDropDown(""Choice"", SampleEnum.Option1); // 값 변경 이벤트 enumField.OnValueChanged += (newValue) => { Debug.Log($""선택된 값: {newValue}""); // Enum으로 캐스팅하여 사용 if (newValue is SampleEnum sample) { Debug.Log($""SampleEnum: {sample}""); } }; // 난이도 선택 예시 var difficultyDropdown = new UTKEnumDropDown(""난이도"", Difficulty.Normal); difficultyDropdown.OnValueChanged += (value) => { var difficulty = (Difficulty)value; Debug.Log($""난이도 변경: {difficulty}""); }; // 현재 선택된 값 가져오기 var currentValue = enumField.Value; if (currentValue is SampleEnum sample) { Debug.Log($""현재 값: {sample}""); } // 프로그램으로 값 변경 enumField.Value = SampleEnum.Option2; // 이벤트 없이 값 변경 enumField.SetValue(SampleEnum.Option3, notify: false); // Disabled enumField.IsEnabled = false;", uxmlCode: @" "); } private void InitializeMultiSelectDropdownSample(VisualElement root) { var normalRow = root.Q("multiselect-normal-row"); if (normalRow != null) { var dropdown = new UTKMultiSelectDropdown("Select Categories"); dropdown.SetOptions(new List { "Category 1", "Category 2", "Category 3", "Category 4", "Category 5" }); dropdown.SetSelectedIndices(new List { 0, 2 }); normalRow.Add(dropdown); } var disabledRow = root.Q("multiselect-disabled-row"); if (disabledRow != null) { var dropdown = new UTKMultiSelectDropdown("Disabled"); dropdown.SetOptions(new List { "Option 1", "Option 2", "Option 3" }); dropdown.SetSelectedIndices(new List { 0, 1 }); dropdown.IsEnabled = false; disabledRow.Add(dropdown); } SetCodeSamples(root, csharpCode: @"// 기본 사용법 var dropdown = new UTKMultiSelectDropdown(""Select Categories""); dropdown.SetOptions(new List { ""Category 1"", ""Category 2"", ""Category 3"", ""Category 4"", ""Category 5"" }); // 선택 이벤트 (인덱스 목록과 값 목록 모두 전달) dropdown.OnSelectionChanged += (indices, values) => { Debug.Log($""선택된 개수: {values.Count}""); Debug.Log($""선택 항목: {string.Join("", "", values)}""); Debug.Log($""인덱스: [{string.Join("", "", indices)}]""); }; // 생성자로 한 번에 설정 var categoryDropdown = new UTKMultiSelectDropdown( ""카테고리 선택"", new List { ""과일"", ""채소"", ""육류"", ""유제품"" } ); // 기본값 설정 (인덱스로) categoryDropdown.SetSelectedIndices(new List { 0, 2 }); // 기본값 설정 (값으로) categoryDropdown.SetSelectedValues(new List { ""과일"", ""육류"" }); // 이벤트 없이 선택 변경 (초기화 시 유용) categoryDropdown.SetSelectedIndices(new List { 1, 3 }, notify: false); // 선택된 값 가져오기 var selectedIndices = dropdown.SelectedIndices; var selectedValues = dropdown.SelectedValues; // 전체 선택 dropdown.SelectAll(); // 전체 해제 dropdown.ClearSelection(); // 옵션 동적 변경 dropdown.SetOptions(new List { ""New 1"", ""New 2"", ""New 3"" }); // Disabled var disabledDropdown = new UTKMultiSelectDropdown(""Disabled""); disabledDropdown.SetOptions(new List { ""Option 1"", ""Option 2"", ""Option 3"" }); disabledDropdown.SetSelectedIndices(new List { 0, 1 }); disabledDropdown.IsEnabled = false;", uxmlCode: @" "); } private void InitializeButtonDropdownSample(VisualElement root) { // 기본: Language 아이콘 + Text variant var defaultRow = root.Q("button-dropdown-default-row"); if (defaultRow != null) { var dropdown = new UTKButtonDropdown(); dropdown.SetOptions(new List { "한국어", "English", "日本語", "中文" }); dropdown.SetSelectedIndex(0, notify: false); defaultRow.Add(dropdown); } // SetButton으로 버튼 교체: Ghost variant var customRow = root.Q("button-dropdown-custom-row"); if (customRow != null) { var dropdown = new UTKButtonDropdown(); dropdown.SetOptions(new List { "한국어", "English", "日本語", "中文" }); dropdown.SetSelectedIndex(1, notify: false); var customBtn = new UTKButton( text: dropdown.SelectedValue ?? "English", icon: UTKMaterialIcons.Language, variant: UTKButton.ButtonVariant.Ghost ); dropdown.SetButton(customBtn); customRow.Add(dropdown); } // Disabled var disabledRow = root.Q("button-dropdown-disabled-row"); if (disabledRow != null) { var dropdown = new UTKButtonDropdown(); dropdown.SetOptions(new List { "한국어", "English", "日本語" }); dropdown.SetSelectedIndex(0, notify: false); dropdown.IsEnabled = false; disabledRow.Add(dropdown); } SetCodeSamples(root, csharpCode: @"// 기본 생성 (Language 아이콘 + Text variant) var dropdown = new UTKButtonDropdown(); dropdown.SetOptions(new List { ""한국어"", ""English"", ""日本語"", ""中文"" }); dropdown.SetSelectedIndex(0, notify: false); // 선택 이벤트 dropdown.OnSelectionChanged += (index, value) => { Debug.Log($""언어 변경: [{index}] {value}""); }; // TriggerButton getter로 직접 접근 dropdown.TriggerButton?.Size = UTKButton.ButtonSize.Small; // SetButton으로 트리거 버튼 교체 (기존 버튼 자동 Dispose) var myBtn = new UTKButton( text: dropdown.SelectedValue ?? ""Select"", icon: UTKMaterialIcons.Language, variant: UTKButton.ButtonVariant.Ghost ); dropdown.SetButton(myBtn); // 선택된 값 가져오기 var index = dropdown.SelectedIndex; var value = dropdown.SelectedValue; // 프로그램으로 선택 dropdown.SetSelectedIndex(2, notify: false); dropdown.SetSelectedValue(""English""); // 옵션 동적 변경 dropdown.SetOptions(new List { ""한국어"", ""English"" }); dropdown.AddOption(""Français""); // Disabled dropdown.IsEnabled = false;", uxmlCode: @" <\ui:UXML>"); } #endregion #region Slider Initializers private void InitializeSliderSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 슬라이더 var slider = new UTKSlider(); slider.label = ""볼륨""; // Unity Slider의 label 프로퍼티 (소문자) slider.lowValue = 0; slider.highValue = 100; slider.value = 50; slider.OnValueChanged += (value) => Debug.Log($""볼륨: {value}""); // 생성자로 생성 var volumeSlider = new UTKSlider(""볼륨"", 0, 100, 75); // 정수만 허용 slider.showInputField = true; // 비활성화 slider.IsEnabled = false;", uxmlCode: @" "); } private void InitializeSliderIntSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 정수 슬라이더 var slider = new UTKSliderInt(); slider.label = ""레벨""; // Unity SliderInt의 label 프로퍼티 (소문자) slider.lowValue = 1; slider.highValue = 10; slider.value = 5; slider.OnValueChanged += (value) => Debug.Log($""레벨: {value}""); // 생성자로 생성 var levelSlider = new UTKSliderInt(""레벨"", 1, 10, 5); // 수량 슬라이더 var quantitySlider = new UTKSliderInt(""수량"", 0, 100, 25); quantitySlider.OnValueChanged += (value) => Debug.Log($""수량: {value}""); // 페이지 선택 var pageSlider = new UTKSliderInt(""페이지"", 1, 100, 1); pageSlider.OnValueChanged += (page) => LoadPage(page); // 비활성화 slider.IsEnabled = false;", uxmlCode: @" "); } private void InitializeMinMaxSliderSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 MinMax 슬라이더 var minMaxSlider = new UTKMinMaxSlider(); minMaxSlider.label = ""가격 범위""; // Unity MinMaxSlider의 label 프로퍼티 minMaxSlider.lowLimit = 0; // 전체 범위 최소값 minMaxSlider.highLimit = 1000; // 전체 범위 최대값 minMaxSlider.MinValue = 100; // 선택 범위 최소값 minMaxSlider.MaxValue = 500; // 선택 범위 최대값 // 값 변경 이벤트 (Vector2로 반환됨) minMaxSlider.OnValueChanged += (range) => { Debug.Log($""범위: {range.x} ~ {range.y}""); }; // 생성자로 생성 (label, lowLimit, highLimit, minValue, maxValue) var rangeSlider = new UTKMinMaxSlider(""범위"", 0, 100, 20, 80); // 비활성화 minMaxSlider.IsEnabled = false;", uxmlCode: @" "); } private void InitializeProgressBarSample(VisualElement root) { SetCodeSamples(root, csharpCode: @"// 기본 프로그레스 바 var progressBar = new UTKProgressBar(); progressBar.title = ""다운로드""; // ProgressBar의 title 프로퍼티 progressBar.MinValue = 0; // 또는 lowValue 직접 사용 progressBar.MaxValue = 100; // 또는 highValue 직접 사용 progressBar.Value = 45; // 생성자로 생성 (title, minValue, maxValue, defaultValue) var downloadBar = new UTKProgressBar(""다운로드"", 0, 100, 75); // 진행률 업데이트 progressBar.Value = 75; // 퍼센트 표시 progressBar.ShowPercentage = true; // 색상 변형 progressBar.Variant = UTKProgressBar.ProgressBarVariant.Success; progressBar.Variant = UTKProgressBar.ProgressBarVariant.Warning; progressBar.Variant = UTKProgressBar.ProgressBarVariant.Danger; // 비동기 작업 진행률 표시 async UniTask LoadDataAsync() { for (int i = 0; i <= 100; i += 10) { progressBar.Value = i; await UniTask.Delay(100); } }", uxmlCode: @" "); } #endregion }