-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
175 lines (154 loc) · 5.74 KB
/
Copy pathmain.js
File metadata and controls
175 lines (154 loc) · 5.74 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
(async function () {
// Phase 3: Asset Security Integration
// Initialize asset protection before loading any assets
let assetSecurity = null;
// Import asset security (with fallback for development)
try {
const { getAssetSecurity } = await import('./src/security/AssetSecurityIntegration.js');
assetSecurity = getAssetSecurity();
console.log('🔐 Asset security initialized');
} catch (error) {
console.warn('Asset security not available:', error.message);
}
// Phase 4: Advanced Monitoring Integration
// Initialize security monitoring system
let securityMonitor = null;
try {
const { getSecurityMonitor } = await import('./src/security/SecurityMonitor.js');
securityMonitor = getSecurityMonitor();
console.log('🛡️ Security monitoring initialized');
} catch (error) {
console.warn('Security monitoring not available:', error.message);
}
// Wait for DOM to be ready
function ready() {
return new Promise(resolve => {
if (document.readyState === "complete" || document.readyState === "interactive") {
resolve();
} else {
document.addEventListener("DOMContentLoaded", resolve);
}
});
}
await ready();
// Initialize asset security if available
if (assetSecurity) {
try {
await assetSecurity.initialize();
console.log('✅ Asset protection active');
} catch (error) {
console.warn('Asset protection initialization failed:', error);
}
}
// Initialize security monitoring if available
if (securityMonitor) {
try {
securityMonitor.startMonitoring();
console.log('✅ Security monitoring active');
} catch (error) {
console.warn('Security monitoring initialization failed:', error);
}
}
// Wait for UnicornStudio global to be available
function unicornReady() {
return new Promise(resolve => {
if (window.UnicornStudio) return resolve();
const check = setInterval(() => {
if (window.UnicornStudio) {
clearInterval(check);
resolve();
}
}, 50);
});
}
await unicornReady();
try {
// Protect scene file path if asset security is available
let sceneFilePath = "./sandro-clinic-glass.json";
if (assetSecurity) {
try {
sceneFilePath = await assetSecurity.protectAsset(sceneFilePath);
console.log('🔒 Scene file protected');
} catch (error) {
console.warn('Scene protection failed, using original path:', error);
}
}
// Add the scene using the correct UnicornStudio API with full viewport settings
const scene = await window.UnicornStudio.addScene({
elementId: "unicorn-root", // Container element
fps: 60, // Smooth animation
scale: 1, // Full scale for maximum quality
dpi: window.devicePixelRatio || 1.5, // Auto-detect device pixel ratio
filePath: sceneFilePath, // Protected scene file
lazyLoad: false, // Load immediately for better UX
altText: "Sandro Clinic Interactive Scene", // SEO optimization
ariaLabel: "Interactive Sandro Clinic experience with glass effects", // Accessibility
production: false, // Development mode
fixed: false, // Let scene be responsive, not fixed
interactivity: {
mouse: {
disableMobile: false, // Keep mouse interaction on mobile/touch
disabled: false // Enable all interactions
}
}
});
console.log('UnicornStudio scene loaded successfully:', scene);
// Enable UnicornStudio protection if available
if (assetSecurity && scene) {
try {
await assetSecurity.loadProtectedModel(sceneFilePath, { scene });
console.log('🛡️ UnicornStudio protection enabled');
} catch (error) {
console.warn('UnicornStudio protection failed:', error);
}
}
// Add responsive resize handler for optimal scaling
let resizeTimeout;
function handleResize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
if (scene && scene.resize) {
scene.resize(); // UnicornStudio's built-in responsive resize
// Force canvas to fill viewport after resize
const canvas = document.querySelector('#unicorn-root canvas');
if (canvas) {
canvas.style.width = '100vw';
canvas.style.height = '100vh';
canvas.style.objectFit = 'cover';
}
console.log('Scene resized for viewport:', window.innerWidth, 'x', window.innerHeight);
}
}, 150); // Debounce resize events
}
// Listen for viewport changes
window.addEventListener('resize', handleResize);
window.addEventListener('orientationchange', () => {
setTimeout(handleResize, 300); // Delay for orientation change completion
});
// Optional: Listen for visibility changes to pause/resume scene
document.addEventListener('visibilitychange', () => {
if (scene) {
if (document.hidden) {
scene.paused = true; // Pause when tab is hidden (performance)
} else {
scene.paused = false; // Resume when tab is visible
}
}
});
// Expose scene globally for debugging (remove in production)
window.sandroScene = scene;
} catch (error) {
console.error('Error loading UnicornStudio scene:', error);
const container = document.getElementById('unicorn-root');
if (container) {
container.innerHTML = `
<div class="error-container">
<h2>Scene Loading Error</h2>
<p><strong>Error:</strong> ${error.message}</p>
<p>Please check your network connection and try refreshing the page.</p>
<p><small>Viewport: ${window.innerWidth} × ${window.innerHeight}</small></p>
</div>
`;
}
}
})();