Skip to content

Commit

Permalink
Merge pull request #40 from galacean/fix/merge-issue
Browse files Browse the repository at this point in the history
Merge origin/main into origin/refactor/2.0
  • Loading branch information
yiiqii committed May 6, 2024
2 parents 18bd485 + af91b1d commit 0f045d5
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 89 deletions.
11 changes: 8 additions & 3 deletions fallback/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getStandardNullContent, getStandardSpriteContent } from './sprite';
import { getStandardInteractContent } from './interact';
import { arrAdd, quatFromXYZRotation, rotationZYXFromQuat } from './utils';
import { getStandardCameraContent } from './camera';
import { version21Migration, version22Migration, version30Migration } from './migration';
import { version21Migration, version22Migration, version24Migration, version30Migration } from './migration';

export * from './utils';

Expand All @@ -30,10 +30,15 @@ export function getStandardJSON (json: any): JSONScene {
return version30Migration(version21Migration(getStandardJSONFromV0(json)));
}

const mainVersion = standardVersion.exec(json.version)?.[1];
const vs = standardVersion.exec(json.version) || [];
const mainVersion = Number(vs[1]);
const minorVersion = Number(vs[2]);

if (mainVersion) {
if (Number(mainVersion) < 3) {
if (mainVersion < 2 || (mainVersion === 2 && minorVersion < 4)) {
json = version24Migration(json);
}
if (mainVersion < 3) {
return version30Migration(version21Migration(json));
}

Expand Down
38 changes: 36 additions & 2 deletions fallback/migration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { JSONScene, JSONSceneLegacy } from '../src';
import type { JSONScene, JSONSceneLegacy, BaseContent } from '../src';
import { ItemType, ItemEndBehavior, END_BEHAVIOR_PAUSE_AND_DESTROY, END_BEHAVIOR_FREEZE, END_BEHAVIOR_PAUSE, DataType } from '../src';
import { convertAnchor, generateGUID } from './utils';
import { convertAnchor, generateGUID, ensureFixedNumber, ensureFixedVec3 } from './utils';

/**
* 2.1 以下版本数据适配(mars-player@2.4.0 及以上版本支持 2.1 以下数据的适配)
Expand Down Expand Up @@ -310,3 +310,37 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {

return result;
}

/**
* 2.5 以下版本 赫尔米特数据转换成贝塞尔数据
*/
export function version24Migration (json: JSONScene): JSONScene {
// 曲线转换成贝塞尔
json.compositions.map((comp: any) => {
for (const item of comp.items) {
convertParam(item.content);
}
});

return json;
}

export function convertParam (content: BaseContent | undefined | null) {
if (!content) {
return;
}
for (const key of Object.keys(content)) {
const value = content[key];
const isArray = Array.isArray(value);

if (isArray && value.length === 2 && Array.isArray(value[1])) {
if (key === 'path') {
content[key] = ensureFixedVec3(value);
} else {
content[key] = ensureFixedNumber(value);
}
} else if (!isArray && typeof value === 'object') {
convertParam(value);
}
}
}
139 changes: 117 additions & 22 deletions fallback/utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import uuidV4 from 'uuid/dist/esm-browser/v4';
import type {
FixedNumberExpression,
RGBAColorValue,
ColorExpression,
NumberExpression,
GradientColor,
GradientStop,
FixedVec3Expression,
vec4,
vec3,
FixedNumberExpression, RGBAColorValue, ColorExpression, NumberExpression, GradientColor,
GradientStop, FixedVec3Expression, vec4, vec3, BezierKeyframeValue,
vec2,
} from '../src';
import { ValueType, ParticleOrigin } from '../src';
import uuidV4 from 'uuid/dist/esm-browser/v4';
import { BezierKeyframeType, ValueType, ParticleOrigin } from '../src';

export function arrAdd<T> (arr: T[], item: T): boolean | undefined {
if (!arr.includes(item)) {
Expand Down Expand Up @@ -44,15 +37,31 @@ export function ensureFixedNumber (a: any): FixedNumberExpression | undefined {
return [ValueType.CONSTANT, a];
}
if (a) {
if (a[0] === 'lines') {
const valueType = a[0];
const valueData = a[1];

if (Array.isArray(valueType)) {
// 没有数据类型的数据
return;
}

if (valueType === 'static' || valueType === ValueType.CONSTANT) {
return [ValueType.CONSTANT, a[1]];
}
if (valueType === 'lines') {
return [ValueType.LINE, a[1]];
}
if (a[0] === 'curve') {
return [ValueType.CURVE, a[1]];
if (valueType === ValueType.LINE) {
// @ts-expect-error
const keyframes: LineKeyframeValue[] = valueData.map(data => [BezierKeyframeType.LINE, data]);

return [ValueType.BEZIER_CURVE, keyframes];
}
if (a[0] === 'static') {
return [ValueType.CONSTANT, a[1]];
if (valueType === 'curve' || valueType === ValueType.CURVE) {
return [ValueType.BEZIER_CURVE, getBezierCurveFromHermiteInGE(valueData)];
}

return a;
}
}

Expand Down Expand Up @@ -81,6 +90,8 @@ export function ensureColorExpression (a: any, normalized?: boolean): ColorExpre
} else if (a[0] === 'color') {
return [ValueType.RGBA_COLOR, colorToArr(a[1], normalized)];
}

return a;
}
}

Expand Down Expand Up @@ -162,8 +173,12 @@ export function parsePercent (c: string): number {
return +c;
}

export function getGradientColor (color: string | Array<string | number[]>, normalized?: boolean): GradientColor | undefined {
export function getGradientColor (color: string | Array<string | number[]> | GradientColor, normalized?: boolean): GradientColor | undefined {
if (Array.isArray(color)) {
if (color[0] === ValueType.GRADIENT_COLOR) {
return color as GradientColor;
}

// @ts-expect-error
return (color[0] === 'gradient' || color[0] === 'color') && ensureGradient(color[1], normalized);
} else {
Expand All @@ -176,12 +191,41 @@ export function ensureFixedVec3 (a: any): FixedVec3Expression | undefined {
if (a.length === 3) {
return [ValueType.CONSTANT_VEC3, a];
}
if (a[0] === 'path') {
return [ValueType.LINEAR_PATH, a[1]];
}
if (a[0] === 'bezier') {
return [ValueType.BEZIER_PATH, a[1]];
const valueType = a[0];

if (
valueType === 'path' ||
valueType === 'bezier' ||
valueType === ValueType.BEZIER_PATH ||
valueType === ValueType.LINEAR_PATH
) {
const valueData = a[1];
const easing = valueData[0];
const points = valueData[1];
let controlPoints = valueData[2];
const bezierEasing = getBezierCurveFromHermiteInGE(easing);

// linear path没有controlPoints
if (!controlPoints) {
controlPoints = [];
for (let keyframeIndex = 0; keyframeIndex < points.length; keyframeIndex++) {
const point = points[keyframeIndex].slice();

if (keyframeIndex === 0) {
controlPoints.push(point);
} else if (keyframeIndex < points.length - 1) {
controlPoints.push(point);
controlPoints.push(point);
} else {
controlPoints.push(point);
}
}
}

return [ValueType.BEZIER_CURVE_PATH, [bezierEasing, points, controlPoints]];
}

return a;
}
}

Expand Down Expand Up @@ -290,3 +334,54 @@ export const particleOriginTranslateMap: Record<number, vec2> = {
[ParticleOrigin.PARTICLE_ORIGIN_RIGHT_BOTTOM]: [0.5, -0.5],
[ParticleOrigin.PARTICLE_ORIGIN_RIGHT_TOP]: [0.5, 0.5],
};
function getBezierCurveFromHermite (m0: number, m1: number, p0: number[], p3: number[]) {
const xStart = p0[0];
const yStart = p0[1];
const xEnd = p3[0];
const yEnd = p3[1];
const dt = xEnd - xStart;

m0 = m0 * dt;
m1 = m1 * dt;
const bezierControlPoints = [[xStart + (xEnd - xStart) / 3, yStart + m0 / 3], [xEnd - (xEnd - xStart) / 3, yEnd - m1 / 3]];

return bezierControlPoints;
}

export function getBezierCurveFromHermiteInGE (geHermiteCurves: number[][]): BezierKeyframeValue[] {
let ymax = -1000000;
let ymin = 1000000;

for (let i = 0; i < geHermiteCurves.length; i++) {
ymax = Math.max(ymax, geHermiteCurves[i][1]);
ymin = Math.min(ymin, geHermiteCurves[i][1]);
}
const geBezierCurves = [[geHermiteCurves[0][0], geHermiteCurves[0][1]]];

for (let i = 0; i < geHermiteCurves.length - 1; i++) {
const m0 = geHermiteCurves[i][3] * (ymax - ymin);
const m1 = geHermiteCurves[i + 1][2] * (ymax - ymin);
const p0 = [geHermiteCurves[i][0], geHermiteCurves[i][1]];
const p3 = [geHermiteCurves[i + 1][0], geHermiteCurves[i + 1][1]];

if (p0[0] != p3[0]) {
const bezierControlPoints = getBezierCurveFromHermite(m0, m1, p0, p3);
const p1 = bezierControlPoints[0];
const p2 = bezierControlPoints[1];

geBezierCurves[geBezierCurves.length - 1].push(p1[0]);
geBezierCurves[geBezierCurves.length - 1].push(p1[1]);
geBezierCurves.push([p2[0], p2[1], p3[0], p3[1]]);
} else {
geBezierCurves[geBezierCurves.length - 1].push(p3[0]);
geBezierCurves[geBezierCurves.length - 1].push(p3[1]);
}
}

// 添加关键帧类型
return geBezierCurves.map((curve, index) => {
return index === 0 ? [BezierKeyframeType.EASE_OUT, curve as [number, number, number, number]]
: index === geBezierCurves.length - 1 ? [BezierKeyframeType.EASE_IN, curve as [number, number, number, number]]
: [BezierKeyframeType.EASE, curve as [number, number, number, number, number, number]];
});
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@galacean/effects-specification",
"version": "1.1.0",
"version": "1.2.0",
"description": "Galacean Effects JSON Specification",
"module": "./dist/index.mjs",
"main": "./dist/index.js",
Expand Down
3 changes: 2 additions & 1 deletion src/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ export interface JSONSceneLegacy {
* 2.1 增加文本元素
* 2.2 数据类型兼容
* 2.3 新增动态视频、陀螺仪支持旋转
* 2.4 支持贝塞尔曲线
*/
version: '1.0' | '1.1' | '1.2' | '1.3' | '1.5' | '1.8' | '2.0' | '2.1' | '2.2' | '2.3',
version: '1.0' | '1.1' | '1.2' | '1.3' | '1.5' | '1.8' | '2.0' | '2.1' | '2.2' | '2.3' | '2.4',
/**
* 播放器版本信息
*/
Expand Down
20 changes: 10 additions & 10 deletions test/cases/model/camera.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ describe('camera item', () => {
expect(nearFixed[1]).to.eql(0.2, 'near.value');
expect(fovFixed[0]).to.eql(ValueType.LINE, 'fov.type');
expect(fovFixed[1]).to.eql([[0, 15], [1, 20]], 'fov.value');
expect(farFixed[0]).to.eql(ValueType.CURVE, 'far.type');
expect(farFixed[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'far.value');
expect(farFixed[0]).to.eql(ValueType.BEZIER_CURVE, 'far.type');
// expect(farFixed[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'far.value');
expect(opt.clipMode).to.eql(1);
});

Expand Down Expand Up @@ -80,8 +80,8 @@ describe('camera item', () => {
expect(rol.separateAxes).to.be.true;
expect(rol.x[0]).to.eql(ValueType.CONSTANT, 'x.type');
expect(rol.x[1]).to.eql(2, 'x.value');
expect(rol.y[0]).to.eql(ValueType.CURVE, 'y.type');
expect(rol.y[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'y.value');
expect(rol.y[0]).to.eql(ValueType.BEZIER_CURVE, 'y.type');
// expect(rol.y[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'y.value');
expect(rol.z[0]).to.eql(ValueType.LINE, 'z.value');
expect(rol.z[1]).to.eql([[0, 1], [0.5, 0], [1, 1]], 'z.value');
});
Expand Down Expand Up @@ -117,8 +117,8 @@ describe('camera item', () => {
expect(pol.linearX[1]).to.eql([[0, -1], [1, 3]], 'linearX.value');
expect(pol.linearY[0]).to.eql(ValueType.CONSTANT, 'linearY.type');
expect(pol.linearY[1]).to.eql(1, 'linearY.value');
expect(pol.linearZ[0]).to.eql(ValueType.CURVE, 'linearZ.type');
expect(pol.linearZ[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'linearZ.value');
expect(pol.linearZ[0]).to.eql(ValueType.BEZIER_CURVE, 'linearZ.type');
// expect(pol.linearZ[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'linearZ.value');
});

it('camera transform path linear, constant, bezier', () => {
Expand Down Expand Up @@ -150,13 +150,13 @@ describe('camera item', () => {

const lt = getStandardItem(getItem(linearPath));

expect(lt.content.positionOverLifetime.path[0]).to.eql(ValueType.LINEAR_PATH, 'constantPath.type');
expect(lt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 1, 2]]], 'constantPath.value');
expect(lt.content.positionOverLifetime.path[0]).to.eql(ValueType.BEZIER_CURVE_PATH, 'constantPath.type');
// expect(lt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 1, 2]]], 'constantPath.value');

const bt = getStandardItem(getItem(bezierPath));

expect(bt.content.positionOverLifetime.path[0]).to.eql(ValueType.BEZIER_PATH, 'constantPath.type');
expect(bt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[-1.3, 0, 0], [3, 0, 0]], [[1, 1.5, 0], [2.5, 1.2, 0]]], 'constantPath.value');
expect(bt.content.positionOverLifetime.path[0]).to.eql(ValueType.BEZIER_CURVE_PATH, 'constantPath.type');
// expect(bt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[-1.3, 0, 0], [3, 0, 0]], [[1, 1.5, 0], [2.5, 1.2, 0]]], 'constantPath.value');
});

});
Expand Down
Loading

0 comments on commit 0f045d5

Please sign in to comment.