feat : save map.json on project
This commit is contained in:
+45
-9
@@ -2,22 +2,58 @@
|
|||||||
{
|
{
|
||||||
"name": "test_cube",
|
"name": "test_cube",
|
||||||
"type": "Mesh",
|
"type": "Mesh",
|
||||||
"position": [0, 5, 0],
|
"position": [
|
||||||
"rotation": [0, 0, 0],
|
0,
|
||||||
"scale": [2, 2, 2]
|
5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "test_sphere",
|
"name": "test_sphere",
|
||||||
"type": "Mesh",
|
"type": "Mesh",
|
||||||
"position": [10, 5, 0],
|
"position": [
|
||||||
"rotation": [0, 0, 0],
|
-35.67436887305092,
|
||||||
"scale": [3, 3, 3]
|
-12.343540259022419,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
3
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "test_cylinder",
|
"name": "test_cylinder",
|
||||||
"type": "Mesh",
|
"type": "Mesh",
|
||||||
"position": [-10, 5, 0],
|
"position": [
|
||||||
"rotation": [0, 0, 0],
|
-10,
|
||||||
"scale": [1, 4, 1]
|
5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
1
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -11,6 +11,7 @@ interface EditorControlsProps {
|
|||||||
onUndo: () => void;
|
onUndo: () => void;
|
||||||
onRedo: () => void;
|
onRedo: () => void;
|
||||||
onExportJson: () => void;
|
onExportJson: () => void;
|
||||||
|
onSaveToServer?: () => void;
|
||||||
onResetCamera?: () => void;
|
onResetCamera?: () => void;
|
||||||
onPlayerMode?: () => void;
|
onPlayerMode?: () => void;
|
||||||
isPlayerMode?: boolean;
|
isPlayerMode?: boolean;
|
||||||
@@ -27,6 +28,7 @@ export default function EditorControls({
|
|||||||
onUndo,
|
onUndo,
|
||||||
onRedo,
|
onRedo,
|
||||||
onExportJson,
|
onExportJson,
|
||||||
|
onSaveToServer,
|
||||||
onResetCamera,
|
onResetCamera,
|
||||||
onPlayerMode,
|
onPlayerMode,
|
||||||
isPlayerMode,
|
isPlayerMode,
|
||||||
@@ -89,6 +91,12 @@ export default function EditorControls({
|
|||||||
💾 Export JSON
|
💾 Export JSON
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{onSaveToServer && (
|
||||||
|
<button className="save-button" onClick={onSaveToServer}>
|
||||||
|
💾 Save to Server
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<h3>View</h3>
|
<h3>View</h3>
|
||||||
|
|
||||||
{onResetCamera && (
|
{onResetCamera && (
|
||||||
|
|||||||
@@ -236,6 +236,23 @@ code {
|
|||||||
background: #ff8533;
|
background: #ff8533;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.save-button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #22c55e;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-button:hover {
|
||||||
|
background: #16a34a;
|
||||||
|
}
|
||||||
|
|
||||||
.reset-button {
|
.reset-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
|||||||
@@ -145,6 +145,28 @@ export function EditorPage(): React.JSX.Element {
|
|||||||
}
|
}
|
||||||
}, [applySnapshot]);
|
}, [applySnapshot]);
|
||||||
|
|
||||||
|
const handleSaveToServer = useCallback(async () => {
|
||||||
|
if (!sceneData) return;
|
||||||
|
const json = JSON.stringify(sceneData.mapNodes, null, 2);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/save-map", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: json,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Map enregistrée avec succès!");
|
||||||
|
} else {
|
||||||
|
alert("Erreur lors de l'enregistrement");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error saving map:", err);
|
||||||
|
alert("Erreur lors de l'enregistrement");
|
||||||
|
}
|
||||||
|
}, [sceneData]);
|
||||||
|
|
||||||
const handleExportJson = useCallback(() => {
|
const handleExportJson = useCallback(() => {
|
||||||
if (!sceneData) return;
|
if (!sceneData) return;
|
||||||
const json = JSON.stringify(sceneData.mapNodes, null, 2);
|
const json = JSON.stringify(sceneData.mapNodes, null, 2);
|
||||||
@@ -406,6 +428,7 @@ export function EditorPage(): React.JSX.Element {
|
|||||||
onUndo={handleUndo}
|
onUndo={handleUndo}
|
||||||
onRedo={handleRedo}
|
onRedo={handleRedo}
|
||||||
onExportJson={handleExportJson}
|
onExportJson={handleExportJson}
|
||||||
|
onSaveToServer={handleSaveToServer}
|
||||||
onResetCamera={handleResetCamera}
|
onResetCamera={handleResetCamera}
|
||||||
onPlayerMode={handlePlayerMode}
|
onPlayerMode={handlePlayerMode}
|
||||||
isPlayerMode={isPlayerMode}
|
isPlayerMode={isPlayerMode}
|
||||||
|
|||||||
+28
-1
@@ -1,10 +1,37 @@
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import type { ViteDevServer } from "vite";
|
||||||
|
|
||||||
|
const saveMapPlugin = () => ({
|
||||||
|
name: "save-map-api",
|
||||||
|
configureServer(server: ViteDevServer) {
|
||||||
|
server.middlewares.use("/api/save-map", async (req: any, res: any) => {
|
||||||
|
if (req.method !== "POST") {
|
||||||
|
res.writeHead(405).end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = "";
|
||||||
|
req.on("data", (chunk: any) => (body += chunk));
|
||||||
|
req.on("end", () => {
|
||||||
|
try {
|
||||||
|
const mapPath = path.resolve(__dirname, "public/map.json");
|
||||||
|
fs.writeFileSync(mapPath, body);
|
||||||
|
res.writeHead(200, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify({ success: true }));
|
||||||
|
} catch (err: any) {
|
||||||
|
res.writeHead(500).end(JSON.stringify({ error: err.message }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react(), saveMapPlugin()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
|||||||
Reference in New Issue
Block a user