Fix studio CI regressions

Co-authored-by: Luke The Dev <iamlukethedev@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-04-18 15:57:01 +00:00
co-authored by Luke The Dev
parent 7ae768c6a5
commit e556a7bb6e
4 changed files with 53 additions and 22 deletions
+23 -7
View File
@@ -14,13 +14,29 @@ const downloadBlob = (filename: string, blob: Blob) => {
window.setTimeout(() => URL.revokeObjectURL(url), 0);
};
const sanitizeFilename = (value: string) =>
value
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, 48) || "claw3d-studio-world";
const sanitizeFilename = (value: string) => {
const normalized = value.trim().toLowerCase();
let result = "";
let pendingDash = false;
for (const character of normalized) {
const isAlphaNumeric =
(character >= "a" && character <= "z") ||
(character >= "0" && character <= "9");
if (isAlphaNumeric) {
if (pendingDash && result.length > 0) {
result += "-";
}
result += character;
pendingDash = false;
if (result.length >= 48) {
break;
}
continue;
}
pendingDash = result.length > 0;
}
return result || "claw3d-studio-world";
};
export const exportStudioProjectGlb = async (project: StudioProjectRecord) => {
const exporter = new GLTFExporter();
@@ -15,7 +15,7 @@ type AssetMeshProps = {
const AssetMesh = ({ asset }: AssetMeshProps) => {
const groupRef = useRef<Group>(null);
const geometry = useMemo(() => buildAssetGeometry(asset.kind, asset.scale), [asset.kind, asset.scale]);
const geometry = useMemo(() => buildAssetGeometry(asset.kind), [asset.kind]);
const material = useMemo(
() => buildAssetMaterial(asset.color, asset.emissive ?? null),
[asset.color, asset.emissive],
@@ -48,13 +48,13 @@ const createAssetMesh = (asset: StudioWorldAssetDraft) => {
const material = buildAssetMaterial(asset.color, asset.emissive ?? null);
if (asset.kind === "platform") {
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
mesh.scale.set(asset.scale[0], asset.scale[1], asset.scale[2]);
return mesh;
}
if (asset.kind === "tower") {
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
mesh.scale.set(asset.scale[0], asset.scale[1], asset.scale[2]);
return mesh;
}
@@ -84,7 +84,7 @@ const createAssetMesh = (asset: StudioWorldAssetDraft) => {
metalness: 0.02,
}),
);
const canopy = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const canopy = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
trunk.position.y = 0.5;
canopy.position.y = 1.5;
group.add(trunk, canopy);
@@ -93,14 +93,14 @@ const createAssetMesh = (asset: StudioWorldAssetDraft) => {
}
if (asset.kind === "rock") {
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
mesh.scale.set(asset.scale[0], asset.scale[1], asset.scale[2]);
return mesh;
}
if (asset.kind === "beacon") {
const group = new THREE.Group();
const base = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const base = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
const cap = new THREE.Mesh(
new THREE.SphereGeometry(0.34, 18, 18),
new THREE.MeshStandardMaterial({
@@ -119,13 +119,13 @@ const createAssetMesh = (asset: StudioWorldAssetDraft) => {
}
if (asset.kind === "crate") {
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind, asset.scale), material);
const mesh = new THREE.Mesh(buildAssetGeometry(asset.kind), material);
mesh.scale.set(asset.scale[0], asset.scale[1], asset.scale[2]);
return mesh;
}
const ring = new THREE.Mesh(
buildAssetGeometry(asset.kind, asset.scale),
buildAssetGeometry(asset.kind),
new THREE.MeshStandardMaterial({
color: asset.color,
emissive: asset.emissive ?? asset.color,
+22 -7
View File
@@ -115,13 +115,28 @@ const writeStore = (store: StudioProjectsStore) => {
fs.writeFileSync(storePath, JSON.stringify(store, null, 2), "utf8");
};
const slugify = (value: string) =>
value
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, 48) || "studio-world";
const slugify = (value: string) => {
const input = value.trim().toLowerCase();
let result = "";
let pendingDash = false;
for (const char of input) {
const isAlphaNumeric =
(char >= "a" && char <= "z") || (char >= "0" && char <= "9");
if (isAlphaNumeric) {
if (pendingDash && result) {
result += "-";
}
result += char;
if (result.length >= 48) {
break;
}
pendingDash = false;
continue;
}
pendingDash = result.length > 0;
}
return result || "studio-world";
};
const createProjectId = (name: string) =>
`${slugify(name)}-${Date.now().toString(36)}`;