Explorar o código

chore: remove debug log from api.ts

unknown hai 2 meses
pai
achega
1053b13e0b
Modificáronse 3 ficheiros con 66 adicións e 15 borrados
  1. 1 1
      src/components/ModelUploadSection.vue
  2. 64 13
      src/components/StlViewer.vue
  3. 1 1
      src/lib/api.ts

+ 1 - 1
src/components/ModelUploadSection.vue

@@ -207,7 +207,7 @@
           <div v-for="file in files" :key="file.id"
             class="flex items-center gap-4 p-4 bg-gradient-card rounded-xl border border-border/50 hover:border-primary/30 transition-colors">
             <div class="w-24 h-24 bg-primary/5 rounded-xl border border-black/[0.05] flex items-center justify-center relative overflow-hidden shrink-0">
-              <StlViewer v-if="file.name.toLowerCase().endsWith('.stl') && file.file" :file="file.file" />
+              <StlViewer v-if="file.name.toLowerCase().endsWith('.stl') && file.file" :file="file.file" :color="selectedColor" />
               <FileBox v-else class="w-10 h-10 text-primary opacity-50" />
             </div>
             <div class="flex-1 min-w-0">

+ 64 - 13
src/components/StlViewer.vue

@@ -1,20 +1,70 @@
 <template>
-  <div ref="container" class="w-full h-full cursor-move" title="Drag to rotate" />
+  <div ref="container" class="w-full h-full cursor-move rounded-xl overflow-hidden transition-colors duration-500" :style="{ backgroundColor: backgroundColor }" title="Drag to rotate" />
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, onUnmounted } from "vue";
+import { ref, onMounted, onUnmounted, watch, computed } from "vue";
 import * as THREE from "three";
 import { STLLoader } from "three/addons/loaders/STLLoader.js";
 import { OrbitControls } from "three/addons/controls/OrbitControls.js";
 
 interface Props {
   file: File;
+  color?: string; // Color name or hex
 }
 
 const props = defineProps<Props>();
 const container = ref<HTMLElement | null>(null);
 let animationId = 0;
+let renderer: THREE.WebGLRenderer | null = null;
+let mesh: THREE.Mesh | null = null;
+
+// Standard color map for common names
+const COLOR_MAP: Record<string, string> = {
+  "white": "#ffffff",
+  "black": "#1a1a1a",
+  "grey": "#808080",
+  "gray": "#808080",
+  "red": "#ef4444",
+  "blue": "#3b82f6",
+  "green": "#22c55e",
+  "yellow": "#eab308",
+  "orange": "#f97316",
+  "purple": "#a855f7",
+  "pink": "#ec4899",
+  "silver": "#c0c0c0",
+  "gold": "#ffd700",
+  "transparent": "#f3f4f6", // fallback for visual
+  "natural": "#f5f5dc",
+};
+
+const getHexColor = (colorName?: string) => {
+  if (!colorName) return "#808080";
+  if (colorName.startsWith("#")) return colorName;
+  return COLOR_MAP[colorName.toLowerCase()] || "#808080";
+};
+
+const isLight = (hex: string) => {
+  const color = hex.startsWith("#") ? hex : getHexColor(hex);
+  const rgb = parseInt(color.slice(1), 16);
+  const r = (rgb >> 16) & 0xff;
+  const g = (rgb >> 8) & 0xff;
+  const b = (rgb >> 0) & 0xff;
+  const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
+  return luma > 150; // Threshold for "light"
+};
+
+const backgroundColor = computed(() => {
+  if (!props.color) return "transparent";
+  return isLight(props.color) ? "#0f172a" : "#f8fafc"; // Slate-900 or Slate-50
+});
+
+watch(() => props.color, (newColor) => {
+  if (mesh && mesh.material instanceof THREE.MeshPhongMaterial) {
+    const hex = getHexColor(newColor);
+    mesh.material.color.set(hex);
+  }
+});
 
 onMounted(() => {
   if (!container.value) return;
@@ -27,9 +77,9 @@ onMounted(() => {
   const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 2000);
   camera.position.set(0, 0, 150);
 
-  const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
+  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
   renderer.setSize(width, height);
-  renderer.setClearColor(0x000000, 0); // transparent
+  renderer.setClearColor(0x000000, 0); // Always transparent, handled by CSS
   container.value.appendChild(renderer.domElement);
 
   const controls = new OrbitControls(camera, renderer.domElement);
@@ -38,7 +88,7 @@ onMounted(() => {
   controls.autoRotateSpeed = 3.0;
 
   // Add lights
-  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1);
+  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.2);
   hemiLight.position.set(0, 200, 0);
   scene.add(hemiLight);
 
@@ -53,13 +103,14 @@ onMounted(() => {
     geometry.center();
     geometry.computeVertexNormals();
 
+    const hex = getHexColor(props.color);
     const material = new THREE.MeshPhongMaterial({ 
-      color: 0x3b82f6,
-      specular: 0x111111, 
-      shininess: 100 
+      color: hex,
+      specular: 0x222222, 
+      shininess: 60 
     });
     
-    const mesh = new THREE.Mesh(geometry, material);
+    mesh = new THREE.Mesh(geometry, material);
     
     geometry.computeBoundingSphere();
     const radius = geometry.boundingSphere?.radius || 50;
@@ -73,12 +124,12 @@ onMounted(() => {
   const animate = () => {
     animationId = requestAnimationFrame(animate);
     controls.update();
-    renderer.render(scene, camera);
+    if (renderer) renderer.render(scene, camera);
   };
   animate();
 
   const handleResize = () => {
-    if (!container.value) return;
+    if (!container.value || !renderer) return;
     const w = container.value.clientWidth;
     const h = container.value.clientHeight;
     camera.aspect = w / h;
@@ -91,10 +142,10 @@ onMounted(() => {
   onUnmounted(() => {
     cancelAnimationFrame(animationId);
     window.removeEventListener("resize", handleResize);
-    if (renderer.domElement.parentNode) {
+    if (renderer && renderer.domElement.parentNode) {
       renderer.domElement.parentNode.removeChild(renderer.domElement);
     }
-    renderer.dispose();
+    renderer?.dispose();
   });
 });
 </script>

+ 1 - 1
src/lib/api.ts

@@ -2,7 +2,7 @@ import i18n from "../i18n";
 
 export const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';
 export const RESOURCES_BASE_URL = API_BASE_URL.replace(/\/api\/?$/, '');
-console.log("DEBUG: Resources will be loaded from:", RESOURCES_BASE_URL);
+
 
 const getErrorMessage = async (response: Response, defaultMsg: string) => {
   try {