refactor: reorganize package structure and decouple framework packages (#338)
* refactor: reorganize package structure and decouple framework packages ## Package Structure Reorganization - Reorganized 55 packages into categorized subdirectories: - packages/framework/ - Generic framework (Laya/Cocos compatible) - packages/engine/ - ESEngine core modules - packages/rendering/ - Rendering modules (WASM dependent) - packages/physics/ - Physics modules - packages/streaming/ - World streaming - packages/network-ext/ - Network extensions - packages/editor/ - Editor framework and plugins - packages/rust/ - Rust WASM engine - packages/tools/ - Build tools and SDK ## Framework Package Decoupling - Decoupled behavior-tree and blueprint packages from ESEngine dependencies - Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent) - ESEngine-specific code moved to esengine/ subpath exports - Framework packages now usable with Cocos/Laya without ESEngine ## CI Configuration - Updated CI to only type-check and lint framework packages - Added type-check:framework and lint:framework scripts ## Breaking Changes - Package import paths changed due to directory reorganization - ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine') * fix: update es-engine file path after directory reorganization * docs: update README to focus on framework over engine * ci: only build framework packages, remove Rust/WASM dependencies * fix: remove esengine subpath from behavior-tree and blueprint builds ESEngine integration code will only be available in full engine builds. Framework packages are now purely engine-agnostic. * fix: move network-protocols to framework, build both in CI * fix: update workflow paths from packages/core to packages/framework/core * fix: exclude esengine folder from type-check in behavior-tree and blueprint * fix: update network tsconfig references to new paths * fix: add test:ci:framework to only test framework packages in CI * fix: only build core and math npm packages in CI * fix: exclude test files from CodeQL and fix string escaping security issue
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* BoxCollider2D Inspector Provider
|
||||
* 2D 矩形碰撞体检视器
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Component } from '@esengine/ecs-framework';
|
||||
import type { IComponentInspector, ComponentInspectorContext } from '@esengine/editor-core';
|
||||
import { BoxCollider2DComponent, CollisionLayer2D } from '@esengine/physics-rapier2d';
|
||||
|
||||
export class BoxCollider2DInspectorProvider implements IComponentInspector<BoxCollider2DComponent> {
|
||||
readonly id = 'boxcollider2d-inspector';
|
||||
readonly name = 'BoxCollider2D Inspector';
|
||||
readonly priority = 100;
|
||||
readonly targetComponents = ['BoxCollider2D', 'BoxCollider2DComponent'];
|
||||
|
||||
canHandle(component: Component): component is BoxCollider2DComponent {
|
||||
return component instanceof BoxCollider2DComponent ||
|
||||
component.constructor.name === 'BoxCollider2DComponent';
|
||||
}
|
||||
|
||||
render(context: ComponentInspectorContext): React.ReactElement {
|
||||
const component = context.component as BoxCollider2DComponent;
|
||||
const onChange = context.onChange;
|
||||
|
||||
const handleChange = (prop: string, value: unknown) => {
|
||||
onChange?.(prop, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="entity-inspector">
|
||||
<div className="inspector-section">
|
||||
<div className="section-title">Box Collider 2D</div>
|
||||
|
||||
{/* Size */}
|
||||
<div className="section-subtitle">Size</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Width</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.width}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('width', parseFloat(e.target.value) || 1)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Height</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.height}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('height', parseFloat(e.target.value) || 1)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Offset */}
|
||||
<div className="section-subtitle">Offset</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>X</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.offset.x}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('offset', {
|
||||
...component.offset,
|
||||
x: parseFloat(e.target.value) || 0
|
||||
})}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Y</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.offset.y}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('offset', {
|
||||
...component.offset,
|
||||
y: parseFloat(e.target.value) || 0
|
||||
})}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Material */}
|
||||
<div className="section-subtitle">Material</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Friction</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.friction}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('friction', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Restitution</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.restitution}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('restitution', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Density</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.density}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('density', parseFloat(e.target.value) || 1)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Collision */}
|
||||
<div className="section-subtitle">Collision</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Is Trigger</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.isTrigger}
|
||||
onChange={(e) => handleChange('isTrigger', e.target.checked)}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Layer</label>
|
||||
<select
|
||||
value={component.collisionLayer}
|
||||
onChange={(e) => handleChange('collisionLayer', parseInt(e.target.value, 10))}
|
||||
className="property-select"
|
||||
>
|
||||
<option value={CollisionLayer2D.Default}>Default</option>
|
||||
<option value={CollisionLayer2D.Player}>Player</option>
|
||||
<option value={CollisionLayer2D.Enemy}>Enemy</option>
|
||||
<option value={CollisionLayer2D.Ground}>Ground</option>
|
||||
<option value={CollisionLayer2D.Projectile}>Projectile</option>
|
||||
<option value={CollisionLayer2D.Trigger}>Trigger</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* CircleCollider2D Inspector Provider
|
||||
* 2D 圆形碰撞体检视器
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Component } from '@esengine/ecs-framework';
|
||||
import type { IComponentInspector, ComponentInspectorContext } from '@esengine/editor-core';
|
||||
import { CircleCollider2DComponent, CollisionLayer2D } from '@esengine/physics-rapier2d';
|
||||
|
||||
export class CircleCollider2DInspectorProvider implements IComponentInspector<CircleCollider2DComponent> {
|
||||
readonly id = 'circlecollider2d-inspector';
|
||||
readonly name = 'CircleCollider2D Inspector';
|
||||
readonly priority = 100;
|
||||
readonly targetComponents = ['CircleCollider2D', 'CircleCollider2DComponent'];
|
||||
|
||||
canHandle(component: Component): component is CircleCollider2DComponent {
|
||||
return component instanceof CircleCollider2DComponent ||
|
||||
component.constructor.name === 'CircleCollider2DComponent';
|
||||
}
|
||||
|
||||
render(context: ComponentInspectorContext): React.ReactElement {
|
||||
const component = context.component as CircleCollider2DComponent;
|
||||
const onChange = context.onChange;
|
||||
|
||||
const handleChange = (prop: string, value: unknown) => {
|
||||
onChange?.(prop, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="entity-inspector">
|
||||
<div className="inspector-section">
|
||||
<div className="section-title">Circle Collider 2D</div>
|
||||
|
||||
{/* Radius */}
|
||||
<div className="property-row">
|
||||
<label>Radius</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.radius}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('radius', parseFloat(e.target.value) || 0.5)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Offset */}
|
||||
<div className="section-subtitle">Offset</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>X</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.offset.x}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('offset', {
|
||||
...component.offset,
|
||||
x: parseFloat(e.target.value) || 0
|
||||
})}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Y</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.offset.y}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('offset', {
|
||||
...component.offset,
|
||||
y: parseFloat(e.target.value) || 0
|
||||
})}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Material */}
|
||||
<div className="section-subtitle">Material</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Friction</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.friction}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('friction', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Restitution</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.restitution}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('restitution', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Density</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.density}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('density', parseFloat(e.target.value) || 1)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Collision */}
|
||||
<div className="section-subtitle">Collision</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Is Trigger</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.isTrigger}
|
||||
onChange={(e) => handleChange('isTrigger', e.target.checked)}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Layer</label>
|
||||
<select
|
||||
value={component.collisionLayer}
|
||||
onChange={(e) => handleChange('collisionLayer', parseInt(e.target.value, 10))}
|
||||
className="property-select"
|
||||
>
|
||||
<option value={CollisionLayer2D.Default}>Default</option>
|
||||
<option value={CollisionLayer2D.Player}>Player</option>
|
||||
<option value={CollisionLayer2D.Enemy}>Enemy</option>
|
||||
<option value={CollisionLayer2D.Ground}>Ground</option>
|
||||
<option value={CollisionLayer2D.Projectile}>Projectile</option>
|
||||
<option value={CollisionLayer2D.Trigger}>Trigger</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Rigidbody2D Inspector Provider
|
||||
* 2D 刚体检视器
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Component } from '@esengine/ecs-framework';
|
||||
import type { IComponentInspector, ComponentInspectorContext } from '@esengine/editor-core';
|
||||
import { Rigidbody2DComponent, RigidbodyType2D, CollisionDetectionMode2D } from '@esengine/physics-rapier2d';
|
||||
|
||||
export class Rigidbody2DInspectorProvider implements IComponentInspector<Rigidbody2DComponent> {
|
||||
readonly id = 'rigidbody2d-inspector';
|
||||
readonly name = 'Rigidbody2D Inspector';
|
||||
readonly priority = 100;
|
||||
readonly targetComponents = ['Rigidbody2D', 'Rigidbody2DComponent'];
|
||||
|
||||
canHandle(component: Component): component is Rigidbody2DComponent {
|
||||
return component instanceof Rigidbody2DComponent ||
|
||||
component.constructor.name === 'Rigidbody2DComponent';
|
||||
}
|
||||
|
||||
render(context: ComponentInspectorContext): React.ReactElement {
|
||||
const component = context.component as Rigidbody2DComponent;
|
||||
const onChange = context.onChange;
|
||||
|
||||
const handleChange = (prop: string, value: unknown) => {
|
||||
onChange?.(prop, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="entity-inspector">
|
||||
<div className="inspector-section">
|
||||
<div className="section-title">Rigidbody 2D</div>
|
||||
|
||||
{/* Body Type */}
|
||||
<div className="property-row">
|
||||
<label>Body Type</label>
|
||||
<select
|
||||
value={component.bodyType}
|
||||
onChange={(e) => handleChange('bodyType', parseInt(e.target.value, 10) as RigidbodyType2D)}
|
||||
className="property-select"
|
||||
>
|
||||
<option value={RigidbodyType2D.Dynamic}>Dynamic</option>
|
||||
<option value={RigidbodyType2D.Kinematic}>Kinematic</option>
|
||||
<option value={RigidbodyType2D.Static}>Static</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Mass - only for Dynamic */}
|
||||
{component.bodyType === RigidbodyType2D.Dynamic && (
|
||||
<div className="property-row">
|
||||
<label>Mass</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.mass}
|
||||
min={0.001}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('mass', parseFloat(e.target.value) || 1)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Gravity Scale */}
|
||||
<div className="property-row">
|
||||
<label>Gravity Scale</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.gravityScale}
|
||||
step={0.1}
|
||||
onChange={(e) => handleChange('gravityScale', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Damping Section */}
|
||||
<div className="section-subtitle">Damping</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Linear</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.linearDamping}
|
||||
min={0}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('linearDamping', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Angular</label>
|
||||
<input
|
||||
type="number"
|
||||
value={component.angularDamping}
|
||||
min={0}
|
||||
step={0.01}
|
||||
onChange={(e) => handleChange('angularDamping', parseFloat(e.target.value) || 0)}
|
||||
className="property-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Constraints Section */}
|
||||
<div className="section-subtitle">Constraints</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Freeze Position X</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.constraints.freezePositionX}
|
||||
onChange={(e) => handleChange('constraints', {
|
||||
...component.constraints,
|
||||
freezePositionX: e.target.checked
|
||||
})}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Freeze Position Y</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.constraints.freezePositionY}
|
||||
onChange={(e) => handleChange('constraints', {
|
||||
...component.constraints,
|
||||
freezePositionY: e.target.checked
|
||||
})}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Freeze Rotation</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.constraints.freezeRotation}
|
||||
onChange={(e) => handleChange('constraints', {
|
||||
...component.constraints,
|
||||
freezeRotation: e.target.checked
|
||||
})}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Collision Detection */}
|
||||
<div className="section-subtitle">Collision</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Detection</label>
|
||||
<select
|
||||
value={component.collisionDetection}
|
||||
onChange={(e) => handleChange('collisionDetection', parseInt(e.target.value, 10) as CollisionDetectionMode2D)}
|
||||
className="property-select"
|
||||
>
|
||||
<option value={CollisionDetectionMode2D.Discrete}>Discrete</option>
|
||||
<option value={CollisionDetectionMode2D.Continuous}>Continuous</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Sleep */}
|
||||
<div className="section-subtitle">Sleep</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Can Sleep</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={component.canSleep}
|
||||
onChange={(e) => handleChange('canSleep', e.target.checked)}
|
||||
className="property-checkbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Runtime Info (read-only) */}
|
||||
<div className="section-subtitle">Runtime Info</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Velocity</label>
|
||||
<span className="property-readonly">
|
||||
({component.velocity.x.toFixed(2)}, {component.velocity.y.toFixed(2)})
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Angular Vel</label>
|
||||
<span className="property-readonly">
|
||||
{component.angularVelocity.toFixed(2)} rad/s
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="property-row">
|
||||
<label>Is Awake</label>
|
||||
<span className="property-readonly">
|
||||
{component.isAwake ? 'Yes' : 'No'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user