feat(web-platform): release V0.8.1 常规地图优化
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled

This commit is contained in:
2026-09-03 13:18:35 +08:00
parent deead17a9a
commit a9b07e0abf
49 changed files with 4987 additions and 569 deletions
@@ -16,7 +16,7 @@ import {
Select,
Tabs,
} from '../../components/ui';
import type { MapSelection } from '../../map/types';
import type { MapSelection, PlacedMapSelection } from '../../map/types';
import type {
EditableMapDocument,
MapEditorInteractionCallbacks,
@@ -50,10 +50,15 @@ interface ModelControlsProps {
selectedPolicyPath?: string;
policyStatus?: RLPolicyStatus;
mapSelection: MapSelection;
activeMapAssetId?: string;
mapSceneDirty: boolean;
maps: MapEntry[];
showVisualMap: boolean;
showMapCollision: boolean;
editorDocument: EditableMapDocument | null;
editorDraftDocument?: EditableMapDocument;
activeTab?: 'properties' | 'controls' | 'data' | 'map';
onActiveTabChange?: (value: 'properties' | 'controls' | 'data' | 'map') => void;
onUrdfMode: (value: UrdfLoadMode) => void;
onBaseMode: (value: UrdfBaseMode) => void;
onShowCollision: (value: boolean) => void;
@@ -78,7 +83,13 @@ interface ModelControlsProps {
onPolicyCommand: (command: RLCommand) => void;
onRemovePolicy: () => void;
onApplyMap: (value: MapSelection) => void;
onMapDraft: (value: PlacedMapSelection) => void;
onEditorPreview: (document: EditableMapDocument | null) => void;
onEditorDraftChange: (
descriptorPath: string,
document: EditableMapDocument,
dirty: boolean,
) => void;
onEditorApply: (document: EditableMapDocument) => Promise<boolean>;
onEditorExport: () => void;
onEditorConvert: () => Promise<boolean>;
@@ -86,6 +97,7 @@ interface ModelControlsProps {
onEditorSelect: (id: string | null) => void;
onEditorTransformMode: (mode: MapEditorTransformMode) => void;
onEditorSnapping: (translation: number | null, rotationDegrees: number | null) => void;
onEditorSurfaceHeight?: (position: readonly [number, number, number]) => number | null;
onMapDisplay: (visual: boolean, collision: boolean) => void;
onMapTabOpen?: () => void;
onDataRecorderConfigure: (patch: Partial<DataRecorderConfig>) => void;
@@ -95,7 +107,10 @@ interface ModelControlsProps {
onDataRecordingExport: (format: 'csv' | 'json') => void;
}
export function ModelControlsSidebar(props: ModelControlsProps) {
const [tab, setTab] = useState<'properties' | 'controls' | 'data' | 'map'>('properties'),
const [internalTab, setInternalTab] = useState<'properties' | 'controls' | 'data' | 'map'>(
'properties',
),
tab = props.activeTab ?? internalTab,
s = props.snapshot;
if (!s)
return (
@@ -315,7 +330,8 @@ export function ModelControlsSidebar(props: ModelControlsProps) {
label="模型控制侧栏"
value={tab}
onValueChange={(value) => {
setTab(value);
setInternalTab(value);
props.onActiveTabChange?.(value);
if (value === 'map') props.onMapTabOpen?.();
}}
items={[
@@ -353,7 +369,11 @@ export function ModelControlsSidebar(props: ModelControlsProps) {
icon: <MapIcon className="h-3.5 w-3.5" />,
content: (
<PhysicalMapPanel
key={JSON.stringify(props.mapSelection)}
key={`${props.activeMapAssetId ?? 'none'}:${
props.mapSelection.kind === 'project'
? props.mapSelection.descriptorPath
: props.mapSelection.kind
}`}
value={props.mapSelection}
maps={props.maps}
rootBodies={s.bodies
@@ -369,7 +389,10 @@ export function ModelControlsSidebar(props: ModelControlsProps) {
showVisualMap={props.showVisualMap}
showMapCollision={props.showMapCollision}
editorDocument={props.editorDocument}
editorDraftDocument={props.editorDraftDocument}
sceneDirty={props.mapSceneDirty}
onEditorPreview={props.onEditorPreview}
onEditorDraftChange={props.onEditorDraftChange}
onEditorApply={props.onEditorApply}
onEditorExport={props.onEditorExport}
onEditorConvert={props.onEditorConvert}
@@ -377,7 +400,9 @@ export function ModelControlsSidebar(props: ModelControlsProps) {
onEditorSelect={props.onEditorSelect}
onEditorTransformMode={props.onEditorTransformMode}
onEditorSnapping={props.onEditorSnapping}
onEditorSurfaceHeight={props.onEditorSurfaceHeight}
onMapDisplay={props.onMapDisplay}
onDraft={props.onMapDraft}
onApply={props.onApplyMap}
/>
),
@@ -1,6 +1,6 @@
import { useState } from 'react';
import { Box, FolderTree, Map as MapIcon } from 'lucide-react';
import type { ModelEntry } from '../../project/types';
import type { MapEntry, ModelEntry } from '../../project/types';
import {
countProjectSearchResults,
ProjectTree,
@@ -15,6 +15,7 @@ import { Button, Tabs } from '../../components/ui';
import {
DEFAULT_PHYSICAL_MAP_CONFIG,
type MapSelection,
type PlacedMapAsset,
type SystemTerrainPreset,
} from '../../map/types';
import type {
@@ -37,14 +38,25 @@ export function ProjectSidebar({
visible = true,
nativeUrdf,
mapSelection,
maps,
placedMaps,
activeMapId,
pendingSceneChangeCount,
pendingSceneIds,
editorDocument,
editorDocuments,
activeTab,
onActiveTabChange,
onRemove,
onSelectEntry,
onJointHover,
onAddMapAsset,
onAddProjectMap,
onSelectTerrain,
onApplyScene,
onDiscardScene,
onSelectMap,
onRemoveMap,
onSelectMapObject,
}: {
projectName?: string;
@@ -56,7 +68,13 @@ export function ProjectSidebar({
visible?: boolean;
nativeUrdf: boolean;
mapSelection: MapSelection;
maps: MapEntry[];
placedMaps: PlacedMapAsset[];
activeMapId?: string;
pendingSceneChangeCount: number;
pendingSceneIds: string[];
editorDocument: EditableMapDocument | null;
editorDocuments?: ReadonlyMap<string, EditableMapDocument>;
activeTab?: 'project' | 'structure' | 'assets';
onActiveTabChange?: (value: 'project' | 'structure' | 'assets') => void;
onRemove: () => void;
@@ -66,8 +84,13 @@ export function ProjectSidebar({
type: EditableMapObjectType,
placementMode: MapObjectPlacementMode,
) => void | Promise<void>;
onAddProjectMap: (descriptorPath: string) => void;
onSelectTerrain: (preset: SystemTerrainPreset) => void;
onSelectMapObject: (id: string) => void;
onApplyScene: () => void;
onDiscardScene: () => void;
onSelectMap: (id: string) => void;
onRemoveMap: (id: string) => void;
onSelectMapObject: (mapId: string, objectId: string) => void;
}) {
const [internalTab, setInternalTab] = useState<'project' | 'structure' | 'assets'>('project'),
[fileQuery, setFileQuery] = useState(''),
@@ -173,8 +196,19 @@ export function ProjectSidebar({
: DEFAULT_PHYSICAL_MAP_CONFIG.size
}
document={editorDocument}
documents={editorDocuments}
maps={maps}
placedMaps={placedMaps}
activeMapId={activeMapId}
pendingSceneChangeCount={pendingSceneChangeCount}
pendingSceneIds={pendingSceneIds}
onAdd={onAddMapAsset}
onAddProjectMap={onAddProjectMap}
onSelectTerrain={onSelectTerrain}
onApplyScene={onApplyScene}
onDiscardScene={onDiscardScene}
onSelectMap={onSelectMap}
onRemoveMap={onRemoveMap}
onSelectObject={onSelectMapObject}
/>
),