feat: add Camera Work AI package

This commit is contained in:
KINDNICK
2026-08-03 04:42:44 +09:00
parent 26c578416f
commit 02d76bc87c
2187 changed files with 119610 additions and 1 deletions
@@ -0,0 +1,522 @@
.camera-generator-root {
flex-grow: 1;
background-color: #17191d;
color: #e7eaf0;
}
.main-scroll {
flex-grow: 1;
}
.page {
align-self: center;
max-width: 920px;
padding: 12px 16px 18px 16px;
width: 100%;
}
.hero {
background-color: #20242a;
border-color: #343941;
border-radius: 10px;
border-width: 1px;
margin-bottom: 8px;
padding: 14px 16px;
}
.hero-row,
.card-heading,
.button-row,
.field-pair,
.log-heading,
.status-footer,
.readiness-card,
.flow-strip {
flex-direction: row;
}
.hero-row,
.card-heading,
.log-heading,
.status-footer,
.readiness-card {
align-items: center;
}
.hero-copy,
.card-heading-copy,
.readiness-copy,
.status-copy {
flex-grow: 1;
flex-shrink: 1;
}
.eyebrow {
color: #67d5bd;
font-size: 10px;
letter-spacing: 1.6px;
-unity-font-style: bold;
}
.hero-title {
color: #ffffff;
font-size: 22px;
margin-top: 2px;
-unity-font-style: bold;
}
.hero-description {
color: #b8bec8;
font-size: 11px;
margin-top: 4px;
white-space: normal;
}
.backend-badge,
.recommended-badge {
background-color: #173d36;
border-color: #2b6c5f;
border-radius: 10px;
border-width: 1px;
color: #8ce9d3;
font-size: 10px;
margin-left: 12px;
padding: 5px 9px;
-unity-font-style: bold;
}
.flow-strip {
flex-wrap: nowrap;
margin-top: 11px;
}
.flow-item {
background-color: #181b20;
border-radius: 4px;
color: #aeb5c0;
flex-basis: 0;
flex-grow: 1;
font-size: 9px;
margin-right: 3px;
min-width: 0;
padding: 5px 3px;
-unity-text-align: middle-center;
}
.readiness-card {
background-color: #22262b;
border-color: #454b54;
border-radius: 7px;
border-width: 1px;
border-left-width: 3px;
margin-bottom: 8px;
padding: 8px 11px;
}
.readiness-dot {
background-color: #d5a84a;
border-radius: 5px;
height: 10px;
margin-right: 10px;
width: 10px;
}
.readiness-title {
color: #f2f4f7;
font-size: 12px;
-unity-font-style: bold;
}
.readiness-detail {
color: #a8afb9;
font-size: 10px;
margin-top: 2px;
white-space: normal;
}
.readiness--ready {
border-left-color: #4fba93;
}
.readiness--ready .readiness-dot {
background-color: #56d3a6;
}
.readiness--ready .readiness-detail {
display: none;
}
.readiness--running {
border-left-color: #5d9fe8;
}
.readiness--running .readiness-dot {
background-color: #69adf4;
}
.readiness--warning {
border-left-color: #d5a84a;
}
.workflow-card,
.utility-foldout {
background-color: #22252a;
border-color: #343941;
border-radius: 8px;
border-width: 1px;
margin-bottom: 8px;
padding: 11px 12px;
}
.generation-card {
border-color: #343941;
}
.refinement-card {
display: none;
}
.card-heading {
margin-bottom: 8px;
}
.step-badge {
background-color: #2a7968;
border-radius: 13px;
color: #ffffff;
font-size: 11px;
height: 26px;
margin-right: 10px;
width: 26px;
-unity-font-style: bold;
-unity-text-align: middle-center;
}
.card-title {
color: #f3f5f7;
font-size: 14px;
-unity-font-style: bold;
}
.card-description,
.foldout-description,
.inline-note {
color: #b0b7c1;
font-size: 11px;
white-space: normal;
}
.card-description {
margin-top: 2px;
}
.form-field,
.compact-field,
.summary-box,
.fresh-toggle,
.inline-note {
margin-bottom: 8px;
}
.camera-generator-root .unity-base-field__label {
color: #c6ccd5;
min-width: 112px;
}
.camera-generator-root .unity-base-field__input,
.camera-generator-root .unity-popup-field__input {
background-color: #17191d;
border-color: #3a4049;
color: #e7eaf0;
}
.field-pair {
flex-wrap: wrap;
}
.compact-field {
flex-grow: 1;
margin-right: 8px;
min-width: 210px;
}
.inner-foldout {
background-color: #1c1f23;
border-radius: 6px;
margin-bottom: 10px;
padding: 9px;
}
.inner-foldout > .unity-foldout__toggle,
.utility-foldout > .unity-foldout__toggle {
color: #e3e6eb;
-unity-font-style: bold;
}
.fresh-toggle {
margin-top: 4px;
}
.hidden-box,
.applied-seed-box,
.generation-stage,
.generation-progress,
.footer-action,
.cancel-action {
display: none;
}
.primary-action,
.secondary-action,
.quiet-action,
.danger-action,
.cancel-action,
.mini-action {
border-radius: 5px;
-unity-font-style: bold;
}
.primary-action {
background-color: #2b8a74;
border-color: #43a890;
color: #ffffff;
font-size: 13px;
height: 42px;
margin-top: 6px;
}
.primary-action:hover {
background-color: #329a82;
}
.secondary-action {
background-color: #315f87;
border-color: #477aa4;
color: #ffffff;
height: 34px;
}
.secondary-action:hover {
background-color: #3a6f9c;
}
.quiet-action {
background-color: #2a2e34;
border-color: #424851;
color: #d7dbe1;
min-height: 28px;
}
.quiet-action:hover {
background-color: #343941;
}
.danger-action,
.cancel-action {
background-color: #512d32;
border-color: #764049;
color: #f1c2c8;
height: 34px;
min-width: 130px;
}
.danger-action:hover,
.cancel-action:hover {
background-color: #66363d;
}
.button-row {
flex-wrap: wrap;
margin-top: 6px;
}
.button-row > Button {
margin-right: 6px;
margin-top: 4px;
}
.grow-action {
flex-grow: 1;
min-width: 185px;
}
.final-card .secondary-action {
height: 38px;
}
.utility-foldout {
margin-top: 4px;
}
.foldout-description {
margin-bottom: 10px;
margin-left: 18px;
margin-top: 7px;
}
.advanced-configuration-host {
background-color: #1a1c20;
border-radius: 5px;
margin: 8px 0 10px 18px;
padding: 8px;
}
.advanced-imgui {
min-height: 330px;
}
.subsection-title {
color: #dce0e6;
font-size: 11px;
margin-left: 18px;
margin-top: 8px;
-unity-font-style: bold;
}
.advanced-actions,
.log-field {
margin-left: 18px;
}
.log-heading {
justify-content: space-between;
margin-top: 8px;
}
.mini-action {
background-color: #292d32;
border-color: #40464f;
color: #cdd2d9;
font-size: 9px;
height: 22px;
min-width: 56px;
}
.log-field {
height: 190px;
margin-top: 5px;
}
.status-footer {
background-color: #1d2025;
border-color: #343941;
border-top-width: 1px;
flex-shrink: 0;
min-height: 48px;
padding: 7px 14px;
}
.status-copy {
margin-right: 12px;
}
.status-kicker {
color: #7f8995;
font-size: 9px;
letter-spacing: 0.6px;
-unity-font-style: bold;
}
.status-message {
color: #e6e9ee;
font-size: 11px;
margin-top: 2px;
max-height: 38px;
white-space: normal;
}
.generation-stage {
color: #7fb7f3;
font-size: 10px;
margin-top: 4px;
-unity-font-style: bold;
}
.generation-progress {
height: 17px;
margin-top: 4px;
}
.generation-timing {
color: #929ba7;
font-size: 10px;
margin-top: 3px;
}
.applied-seed-box {
margin-top: 5px;
}
.status--ready {
border-top-color: #346b5d;
}
.status--running {
border-top-color: #4d84bd;
}
.status--error {
background-color: #251d20;
border-top-color: #8c4650;
}
.status--error .status-message {
color: #f2b9c1;
}
.cancel-action {
flex-shrink: 0;
}
.footer-action {
background-color: #2b3037;
border-color: #474e58;
border-radius: 5px;
color: #d8dde5;
flex-shrink: 0;
height: 30px;
margin-right: 6px;
min-width: 74px;
-unity-font-style: bold;
}
.narrow-layout .backend-badge {
display: none;
}
.narrow-layout .page {
padding-left: 12px;
padding-right: 12px;
}
.narrow-layout .field-pair,
.narrow-layout .button-row {
flex-direction: column;
}
.narrow-layout .compact-field,
.narrow-layout .button-row > Button {
margin-right: 0;
min-width: 0;
width: 100%;
}
.narrow-layout .camera-generator-root .unity-base-field__label,
.camera-generator-root.narrow-layout .unity-base-field__label {
min-width: 104px;
}
.summary-box .unity-help-box__icon {
height: 16px;
margin-right: 6px;
width: 16px;
}
.summary-box .unity-help-box__label {
font-size: 10px;
}
.camera-generator-root Button:disabled,
.camera-generator-root .unity-base-field:disabled {
opacity: 0.46;
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f39e900b5f7d47ab9f05d60ac33a6c68
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
unsupportedSelectorAction: 0
@@ -0,0 +1,136 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements">
<ui:VisualElement name="camera-generator-root" class="camera-generator-root">
<ui:ScrollView name="main-scroll" class="main-scroll">
<ui:VisualElement class="page">
<ui:VisualElement class="hero">
<ui:VisualElement class="hero-row">
<ui:VisualElement class="hero-copy">
<ui:Label text="CAMERA WORK AI" class="eyebrow" />
<ui:Label text="AI 카메라 생성" class="hero-title" />
<ui:Label text="Timeline의 모션과 음원으로 편집 가능한 Cinemachine 카메라를 생성합니다." class="hero-description" />
</ui:VisualElement>
<ui:Label text="고품질 Worker" class="backend-badge" />
</ui:VisualElement>
<ui:VisualElement class="flow-strip">
<ui:Label text="1 입력" class="flow-item" />
<ui:Label text="2 전체 생성" class="flow-item" />
<ui:Label text="3 샷 다듬기" class="flow-item" />
<ui:Label text="4 저장" class="flow-item" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="readiness-card" class="readiness-card readiness--warning">
<ui:VisualElement class="readiness-dot" />
<ui:VisualElement class="readiness-copy">
<ui:Label name="readiness-title" text="Timeline 선택이 필요합니다" class="readiness-title" />
<ui:Label name="readiness-detail" text="현재 씬에서 모션과 음원이 있는 Timeline을 선택하세요." class="readiness-detail" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement class="workflow-card">
<ui:VisualElement class="card-heading">
<ui:Label text="1" class="step-badge" />
<ui:VisualElement class="card-heading-copy">
<ui:Label text="입력 Timeline" class="card-title" />
<ui:Label text="모션과 음원이 있는 Timeline을 선택합니다. 기존 카메라는 사용하지 않습니다." class="card-description" />
</ui:VisualElement>
</ui:VisualElement>
<ui:DropdownField name="source-director-dropdown" label="원본 Timeline" class="form-field" />
<ui:HelpBox name="source-summary-box" message-type="Warning" text="모션과 음원이 들어 있는 원본 Timeline을 선택하세요." class="summary-box" />
</ui:VisualElement>
<ui:VisualElement class="workflow-card generation-card">
<ui:VisualElement class="card-heading">
<ui:Label text="2" class="step-badge" />
<ui:VisualElement class="card-heading-copy">
<ui:Label text="전체 카메라 자율 생성" class="card-title" />
<ui:Label text="학습된 컷 리듬과 카메라 문법으로 전체 구간을 자유롭게 구성합니다." class="card-description" />
</ui:VisualElement>
</ui:VisualElement>
<ui:DropdownField name="cut-rhythm-dropdown" label="컷 리듬" tooltip="자동은 음악, 동작과 작업자 컷 데이터를 함께 분석합니다." class="form-field" />
<ui:Label text="거리·무빙·구도는 전체 생성 후 원하는 샷만 따로 조절할 수 있습니다." class="inline-note" />
<ui:Toggle name="fresh-candidate-toggle" text="후보 풀도 새로 계산 (느림)" tooltip="캐시를 사용하지 않고 이번 후보를 처음부터 다시 계산합니다." class="fresh-toggle" />
<ui:HelpBox name="fresh-candidate-warning" message-type="Warning" text="후보 풀을 다시 계산하므로 이번 생성은 더 오래 걸립니다." class="hidden-box" />
<ui:Button name="generate-full-button" text="전체 카메라 자율 생성" class="primary-action" />
</ui:VisualElement>
<ui:VisualElement name="refinement-card" class="workflow-card refinement-card">
<ui:VisualElement class="card-heading">
<ui:Label text="3" class="step-badge" />
<ui:VisualElement class="card-heading-copy">
<ui:Label text="선택한 카메라 다듬기" class="card-title" />
<ui:Label text="Timeline 또는 Hierarchy에서 카메라를 선택한 뒤 필요한 샷만 다시 생성합니다." class="card-description" />
</ui:VisualElement>
</ui:VisualElement>
<ui:HelpBox name="selected-shot-info" message-type="None" text="Timeline의 AI 카메라를 선택하면 자동으로 연결됩니다." class="summary-box" />
<ui:VisualElement name="selected-shot-picker-row">
<ui:DropdownField name="selected-shot-dropdown" label="카메라 직접 선택" class="form-field" />
</ui:VisualElement>
<ui:Foldout name="shot-options-foldout" text="재생성 옵션" value="false" class="inner-foldout">
<ui:Label text="아래 설정은 선택한 카메라 한 개에만 적용됩니다." class="inline-note" />
<ui:VisualElement class="field-pair">
<ui:DropdownField name="shot-size-dropdown" label="샷 거리" class="compact-field" />
<ui:DropdownField name="composition-dropdown" label="인물 구도" class="compact-field" />
</ui:VisualElement>
<ui:DropdownField name="motion-dropdown" label="카메라 움직임" class="form-field" />
<ui:Slider name="motion-intensity-slider" label="움직임 강도" low-value="0" high-value="2" show-input-field="true" class="form-field" />
<ui:FloatField name="distance-field" label="직접 거리 (m)" tooltip="0이면 선택한 샷 거리와 캐릭터 크기에 맞춰 자동 결정합니다." class="form-field" />
<ui:Slider name="body-follow-slider" label="몸 추종 강도" low-value="0" high-value="1" show-input-field="true" tooltip="0이면 무대 기준으로 안정적이고, 1이면 캐릭터 이동을 강하게 따라갑니다." class="form-field" />
<ui:Button name="reset-shot-options-button" text="옵션을 자동으로 되돌리기" class="quiet-action" />
</ui:Foldout>
<ui:VisualElement class="button-row">
<ui:Button name="regenerate-shot-button" text="선택한 카메라 재생성" class="secondary-action grow-action" />
<ui:Button name="remove-result-button" text="생성 결과 지우기" class="danger-action" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="final-card" class="workflow-card final-card">
<ui:VisualElement class="card-heading">
<ui:Label text="4" class="step-badge" />
<ui:VisualElement class="card-heading-copy">
<ui:Label text="완성본 보존" class="card-title" />
<ui:Label text="현재 씬을 원본과 별개의 AI_Camera_Final 씬으로 저장합니다." class="card-description" />
</ui:VisualElement>
</ui:VisualElement>
<ui:Button name="save-final-scene-button" text="완성본 씬으로 저장" class="secondary-action" />
</ui:VisualElement>
<ui:Foldout name="feedback-foldout" text="선택 사항 · 컷 수정 기록" value="false" class="utility-foldout">
<ui:Label text="AI 카메라 컷을 직접 수정한 뒤 기록하면 유지한 컷과 변경한 컷을 익명 데이터로 저장합니다. 씬과 Timeline 자체는 저장하지 않습니다." class="foldout-description" />
<ui:TextField name="editor-style-id-field" label="익명 편집 스타일 ID" class="form-field" />
<ui:Button name="record-correction-button" text="컷 수정 기록 저장" class="quiet-action" />
</ui:Foldout>
<ui:Foldout name="advanced-foldout" text="고급 · 진단" value="false" class="utility-foldout advanced-foldout">
<ui:Label text="경로, Worker, Seed, 캐시와 수동 복구는 문제가 있거나 세부 조정이 필요할 때만 사용하세요." class="foldout-description" />
<ui:VisualElement name="advanced-configuration-host" class="advanced-configuration-host" />
<ui:Label text="수동 작업" class="subsection-title" />
<ui:VisualElement class="button-row advanced-actions">
<ui:Button name="extract-dataset-button" text="Timeline 데이터만 추출" class="quiet-action grow-action" />
<ui:Button name="reapply-full-button" text="현재 결과 전체 다시 적용" class="quiet-action grow-action" />
<ui:Button name="reapply-shot-button" text="현재 결과로 선택 카메라 교체" class="quiet-action grow-action" />
<ui:Button name="build-cache-button" text="준비 캐시 만들기·갱신" class="quiet-action grow-action" />
<ui:Button name="refresh-diagnostics-button" text="목록·상태 새로고침" class="quiet-action grow-action" />
</ui:VisualElement>
<ui:VisualElement class="log-heading">
<ui:Label text="실행 로그" class="subsection-title" />
<ui:Button name="clear-log-button" text="지우기" class="mini-action" />
</ui:VisualElement>
<ui:TextField name="log-field" multiline="true" is-read-only="true" class="log-field" />
</ui:Foldout>
</ui:VisualElement>
</ui:ScrollView>
<ui:VisualElement name="status-footer" class="status-footer status--ready">
<ui:VisualElement class="status-copy">
<ui:Label name="status-message" text="모션과 음원이 들어 있는 Timeline을 선택하세요." class="status-message" />
<ui:Label name="generation-stage-label" text="" class="generation-stage" />
<ui:ProgressBar name="generation-progress" low-value="0" high-value="1" value="0" class="generation-progress" />
<ui:Label name="generation-timing-label" text="생성을 시작하면 단계와 예상 시간을 여기에 표시합니다." class="generation-timing" />
<ui:HelpBox name="applied-seed-box" message-type="Info" text="" class="applied-seed-box" />
</ui:VisualElement>
<ui:Button name="status-log-button" text="로그 보기" class="footer-action" />
<ui:Button name="cancel-generation-button" text="생성 취소" class="cancel-action" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8c71572bfd3749108603d0fe48f1f20b
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}