-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathImageComponent.cpp
More file actions
216 lines (178 loc) · 6.09 KB
/
Copy pathImageComponent.cpp
File metadata and controls
216 lines (178 loc) · 6.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include "ImageComponent.h"
#include "DataSystem.h"
#include "Canvas.h"
#include "ImageComponent.h"
// DeviceState.h include가 여기 있었다 (E, 2026-08-09).
// 이 파일에서 DirectX11:: 심볼을 쓰는 코드가 0이다.
#include "../RenderEngine/Texture.h"
#include "../RenderEngine/mesh.h"
#include "Entity.h"
#include "SceneManager.h"
#include "RenderScene.h"
#include "Scene.h"
#include "transform.h"
#include "RectTransformComponent.h"
#include "UIManager.h"
#include "UITickSystem.h"
ImageComponent::ImageComponent()
{
type = UItype::Image;
}
void ImageComponent::SetTexture(int index)
{
if (index < 0 || index >= textures.size())
return;
curindex = index;
m_curtexture = textures[curindex];
uiinfo.size = textures[curindex]->GetImageSize();
origin = { uiinfo.size.x * 0.5f, uiinfo.size.y * 0.5f };
}
void ImageComponent::SetNativeSize()
{
if (!m_curtexture) return;
uiinfo.size = m_curtexture->GetImageSize();
origin = { uiinfo.size.x * 0.5f, uiinfo.size.y * 0.5f };
// 크기가 0인 텍스처로 rect를 덮으면 요소가 사라진다. 그런 텍스처는 아직
// 로드되지 않았거나 깨진 것이므로, 저작된 크기를 지우지 않고 그대로 둔다.
if (uiinfo.size.x <= 0.f || uiinfo.size.y <= 0.f) return;
if (auto* rect = m_pOwner->GetComponent<RectTransformComponent>())
{
rect->SetSizeDelta({ uiinfo.size.x, uiinfo.size.y });
}
}
bool ImageComponent::isThisTextureExist(std::string_view path) const
{
for (const auto& p : texturePaths)
{
if (p == path)
return true;
}
return false;
}
void ImageComponent::Load(const std::shared_ptr<Texture>& ptr)
{
if (nullptr == ptr)
return;
textures.push_back(ptr);
std::string filename = ptr->m_name + ptr->m_extension;
texturePaths.push_back(filename);
if (1 == textures.size())
{
SetTexture(0);
}
}
void ImageComponent::DeserializeTexture(const std::shared_ptr<Texture>& ptr)
{
if (nullptr == ptr)
return;
textures.push_back(ptr);
if (1 == textures.size())
{
SetTexture(0);
}
}
void ImageComponent::OnInitialized()
{
auto scene = GetOwner()->m_ownerScene;
auto renderScene = SceneManagers->GetRenderScene();
if (scene)
{
renderScene->RegisterCommand(this);
}
// 레지스트리 등록은 수명의 시작(Awake)에서 스스로 한다(6-1).
// 캔버스 연결과 무관하게 등록되므로, 연결이 늦거나 없어도 유령이 되지 않는다.
UIManagers->RegisterImageComponent(this);
// 크기를 텍스처에 맡기기로 한 이미지만 여기서 한 번 맞춘다.
// 예전에는 무조건 했고, 그래서 저작한 크기가 매번 지워졌다(분석 문서 F-7).
if (useNativeTextureSize)
{
SetNativeSize();
}
RefreshTransformFromRect();
}
void ImageComponent::TickLayout(float tick)
{
RefreshTransformFromRect();
}
// 레인 UI — UITickSystem 등록/해지. Awake/OnDestroy(컴포넌트당 1회 게이트)가
// 아니라 씬 편입/이탈 훅을 쓰는 이유는 UITickSystem.h 상단 주석 참조 — DDOL
// 오브젝트가 씬을 건널 때도 매번 다시 불려야 하기 때문이다. 실제 파괴 경로
// (PrefabUtility::ApplyComponentDiff·Scene::FlushPendingDestroy)도 OnDestroy
// 직전에 OnRemovingFromScene을 먼저 부르므로, 이 시스템에서 빠지는 시점이
// 항상 실 파괴보다 먼저다.
void ImageComponent::OnAddedToScene()
{
UIComponent::OnAddedToScene();
UITickSystems->RegisterImage(this);
}
void ImageComponent::OnRemovingFromScene()
{
UITickSystems->UnregisterImage(this);
UIComponent::OnRemovingFromScene();
}
void ImageComponent::RefreshTransformFromRect()
{
auto* rect = m_pOwner ? m_pOwner->GetComponent<RectTransformComponent>() : nullptr;
if (nullptr == rect) return;
const auto& worldRect = rect->GetWorldRect();
// pos는 rect의 중심이다 — SpriteSheetComponent와 UIButton의 히트 테스트가 쓰는
// 것과 같은 규약이다(PHASE 7-6).
//
// 예전 식은 worldRect.x + width * 2 * pivot.x 였다. pivot 0.5에서는 우연히 맞았지만
// (2*0.5 = 1이라 아래 렌더 경로의 보정과 정확히 상쇄됐다) pivot이 다른 값이면
// width*(2p-1) 만큼 어긋난다. worldRect는 이미 pivot을 반영해 계산된 결과이므로
// 여기서 pivot을 또 곱하는 것은 이중 적용이다(분석 문서 F-8).
// 현재 에셋의 pivot이 전부 0.5라 증상이 드러나지 않았을 뿐이다.
pos = { worldRect.x + worldRect.width * 0.5f,
worldRect.y + worldRect.height * 0.5f,
0.0f };
// 텍스처가 없거나 아직 로드되지 않으면 uiinfo.size가 0이다. 나누면 inf/NaN이
// 렌더러까지 흘러가므로 그 프레임의 배율을 1로 둔다 — 예전에는 그대로 나눴다.
scale = { uiinfo.size.x > 0.f ? worldRect.width / uiinfo.size.x : 1.f,
uiinfo.size.y > 0.f ? worldRect.height / uiinfo.size.y : 1.f };
origin = { uiinfo.size.x * 0.5f,
uiinfo.size.y * 0.5f };
scale *= unionScale;
}
void ImageComponent::OnUninitializing()
{
auto scene = GetOwner()->m_ownerScene;
auto renderScene = SceneManagers->GetRenderScene();
if (scene)
{
renderScene->UnregisterCommand(this);
}
// 해제는 무조건 한다. 예전에는 씬이 널이면 건너뛰어 레지스트리에 dangling이 남았다.
UIManagers->UnregisterImageComponent(this);
// 소속 캔버스 목록에서도 빠진다 — Canvas::Update의 매 프레임 청소를 대체한다(6-4).
if (Canvas* owner = GetOwnerCanvas())
{
owner->RemoveUIObject(GetOwner());
}
}
void ImageComponent::UpdateTexture()
{
if (curindex <= 0)
curindex = 0;
if (curindex >= textures.size())
curindex = textures.size() - 1;
SetTexture(curindex);
}
void ImageComponent::OnDeserialized()
{
// CT6-d: 구 ComponentFactory 분기 이동. 캔버스 연결은 UIManager::Update의
// 일괄 연결로 미룬다(6-3). navigations 수동 복원은 이중 적재라 미이식.
for (auto& imagePath : GetTexturePaths())
{
if (imagePath.empty())
continue;
auto texture = DataSystems->LoadSharedTexture(imagePath,
DataSystem::TextureFileType::UITexture);
if (!texture)
{
Debug->LogError("Failed to load texture for ImageComponent: " + imagePath);
continue;
}
DeserializeTexture(texture);
}
}