Skip to content

Commit

Permalink
add more module
Browse files Browse the repository at this point in the history
  • Loading branch information
SantyWang committed Sep 21, 2023
1 parent 550ae69 commit 40da83b
Show file tree
Hide file tree
Showing 77 changed files with 1,020 additions and 466 deletions.
217 changes: 147 additions & 70 deletions cocos/core/curves/gradient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
*/

import { CCClass } from '../data';
import { Enum } from '../value-types';
import { Color, lerp, repeat, EPSILON, approx, random, clamp01 } from '../math';
import { Color, lerp, repeat, EPSILON, approx, random, clamp01, clamp } from '../math';
import { Enum } from '..';

const Mode = Enum({
Blend: 0,
Fixed: 1,
});
const tempColor = new Color();

enum Mode {
BLEND,
FIXED
}

export class ColorKey {
/**
Expand All @@ -43,6 +45,15 @@ export class ColorKey {
* @zh 时间值。
*/
public time = 0;

constructor (color?: Color, time?: number) {
if (color) {
this.color.set(color);
}
if (time !== undefined) {
this.time = time;
}
}
}

CCClass.fastDefine('cc.ColorKey', ColorKey, {
Expand All @@ -64,6 +75,15 @@ export class AlphaKey {
* @zh 时间帧。
*/
public time = 0;

constructor (alpha?: number, time?: number) {
if (alpha !== undefined) {
this.alpha = alpha;
}
if (time !== undefined) {
this.time = time;
}
}
}

CCClass.fastDefine('cc.AlphaKey', AlphaKey, {
Expand All @@ -74,6 +94,10 @@ CCClass.fastDefine('cc.AlphaKey', AlphaKey, {
CCClass.Attr.setClassAttr(AlphaKey, 'alpha', 'visible', true);
CCClass.Attr.setClassAttr(AlphaKey, 'time', 'visible', true);

export declare namespace Gradient {
export type Mode = EnumAlias<typeof Mode>;
}

/**
* @en Gradient is a component that has a lot of color keys and alpha keys to get the interpolated color value.
* @zh 渐变曲线控件包含了颜色关键帧和透明度关键帧,在关键帧中进行插值渐变返回最终的颜色值。
Expand All @@ -89,22 +113,85 @@ export class Gradient {
* 混合模式对取到的最近两个颜色帧进行插值计算。
* 固定模式直接取最近的颜色帧返回,不进行插值。
*/
public static Mode = Mode;
public static Mode = Enum(Mode);

/**
* @en Array of color key.
* @zh 颜色关键帧列表。
*/
public colorKeys: ColorKey[] = [];
public get colorKeys (): ColorKey[] {
const keys: ColorKey[] = [];
for (let i = 0; i < this._colors.length; i++) {
keys.push(new ColorKey(Color.fromUint32(new Color(), this._colors[i]), this._colorTimes[i]));
}
return keys;
}

public set colorKeys (val) {
if (val.length === 1 || val.length === 0) {
this._colors.length = 2;
this._colorTimes.length = 2;
this._colors[0] = this._colors[1] = val.length === 1 ? Color.toUint32(val[0].color) : 0xFFFFFFFF;
this._colorTimes[0] = 0;
this._colorTimes[1] = 1;
} else {
val.sort((a, b): number => a.time - b.time);
this._colors.length = val.length;
this._colorTimes.length = val.length;
for (let i = 0; i < val.length; i++) {
this._colors[i] = Color.toUint32(val[i].color);
this._colorTimes[i] = val[i].time;
}
}
}

/**
* @en Array of alpha key.
* @zh 透明度关键帧列表。
*/
public alphaKeys: AlphaKey[] = [];
public get alphaKeys (): AlphaKey[] {
const keys: AlphaKey[] = [];
for (let i = 0; i < this._alphas.length; i++) {
keys.push(new AlphaKey(this._alphas[i], this._alphaTimes[i]));
}
return keys;
}

public set alphaKeys (val) {
if (val.length === 1 || val.length === 0) {
this._alphas.length = 2;
this._alphas.length = 2;
this._alphas[0] = this._alphas[1] = val.length === 1 ? val[0].alpha : 0xFF;
this._alphaTimes[0] = 0;
this._alphaTimes[1] = 1;
} else {
val.sort((a, b): number => a.time - b.time);
this._alphas.length = val.length;
this._alphaTimes.length = val.length;
for (let i = 0; i < val.length; i++) {
this._alphas[i] = val[i].alpha;
this._alphaTimes[i] = val[i].time;
}
}
}

public get mode (): Mode {
return this._mode;
}

public set mode (val) {
this._mode = val;
}

/**
* @en Blend mode.
* @zh 混合模式。
*/
public mode = Mode.Blend;
private _mode = Mode.BLEND;
private _colors: number[] = [0xFFFFFFFF, 0xFFFFFFFF];
private _colorTimes: number[] = [0, 1];
private _alphas: number[] = [255, 255];
private _alphaTimes: number[] = [0, 1];

/**
* @en Set color keys array and alpha keys array.
Expand All @@ -120,14 +207,10 @@ export class Gradient {
/**
* @en Sort color keys and alpha keys.
* @zh 对颜色和透明度的关键帧进行排序。
* @deprecated Since v3.8, Sorting will be automatic when setting keyframes, no longer need to call this method manually.
*/
public sortKeys (): void {
if (this.colorKeys.length > 1) {
this.colorKeys.sort((a, b): number => a.time - b.time);
}
if (this.alphaKeys.length > 1) {
this.alphaKeys.sort((a, b): number => a.time - b.time);
}
// useless
}

/**
Expand Down Expand Up @@ -165,93 +248,87 @@ export class Gradient {
return this.getRandomColor(new Color());
}

public set (gradient: Readonly<Gradient>): void {
this.colorKeys = gradient.colorKeys;
this.alphaKeys = gradient.alphaKeys;
this.mode = gradient.mode;
}

/**
* @en Generates a random color and alpha.
* @zh 随机生成颜色和透明度。
* @param out @en Randomized color. @zh 随机生成的颜色。
* @returns @en Randomized color. @zh 随机生成的颜色。
*/
public getRandomColor (out: Color): Color {
const c = this.colorKeys[Math.trunc(random() * this.colorKeys.length)];
const a = this.alphaKeys[Math.trunc(random() * this.alphaKeys.length)];
out.set(c.color);
out._set_a_unsafe(a.alpha);
const c = this._colors[Math.trunc(random() * this._colors.length)];
const a = this._alphas[Math.trunc(random() * this._alphas.length)];
Color.fromUint32(out, c);
out._set_a_unsafe(a);
return out;
}

private getRGB (out: Color, time: number): Color {
const colorKeys = this.colorKeys;
const length = colorKeys.length;
const colors = this._colors;
const colorTimes = this._colorTimes;
const length = colors.length;
Color.copy(out, Color.WHITE);
if (length > 1) {
time = clamp01(time);
const lastIndex = length - 1;
clamp(time, colorTimes[0], colorTimes[lastIndex]);
Color.fromUint32(out, colors[lastIndex]);
for (let i = 1; i < length; ++i) {
const preTime = colorKeys[i - 1].time;
const curTime = colorKeys[i].time;
const preTime = colorTimes[i - 1];
const curTime = colorTimes[i];
if (time >= preTime && time < curTime) {
if (this.mode === Mode.Fixed) {
Color.copy(out, colorKeys[i].color);
return out;
if (this.mode === Mode.FIXED) {
Color.fromUint32(out, colors[i]);
} else {
const factor = (time - preTime) / (curTime - preTime);
Color.fromUint32(out, colors[i]);
Color.fromUint32(tempColor, colors[i - 1]);
Color.lerp(out, tempColor, out, factor);
}
const factor = (time - preTime) / (curTime - preTime);
Color.lerp(out, colorKeys[i - 1].color, colorKeys[i].color, factor);
return out;
break;
}
}
const lastIndex = length - 1;
if (approx(time, colorKeys[lastIndex].time, EPSILON)) {
Color.copy(out, colorKeys[lastIndex].color);
} else if (time < colorKeys[0].time) {
Color.lerp(out, Color.BLACK, colorKeys[0].color, time / colorKeys[0].time);
} else if (time > colorKeys[lastIndex].time) {
Color.lerp(out, colorKeys[lastIndex].color, Color.BLACK, (time - colorKeys[lastIndex].time) / (1 - colorKeys[lastIndex].time));
}
// console.warn('something went wrong. can not get gradient color.');
} else if (length === 1) {
Color.copy(out, colorKeys[0].color);
} else {
Color.copy(out, Color.WHITE);
}
return out;
}

private getAlpha (time: number): number {
const basicAlpha = 0; // default alpha is 0
const alphaKeys = this.alphaKeys;
const length = alphaKeys.length;
let alpha = 255;
const alphas = this._alphas;
const alphaTimes = this._alphaTimes;
const length = alphas.length;
if (length > 1) {
time = repeat(time, 1.0 + EPSILON);
const lastIndex = length - 1;
clamp(time, alphaTimes[0], alphaTimes[lastIndex]);
alpha = alphas[lastIndex];
for (let i = 1; i < length; ++i) {
const preTime = alphaKeys[i - 1].time;
const curTime = alphaKeys[i].time;
const preTime = alphaTimes[i - 1];
const curTime = alphaTimes[i];
if (time >= preTime && time < curTime) {
if (this.mode === Mode.Fixed) {
return alphaKeys[i].alpha;
if (this.mode === Mode.FIXED) {
alpha = alphas[i];
} else {
const factor = (time - preTime) / (curTime - preTime);
alpha = lerp(alphas[i - 1], alphas[i], factor);
}
const factor = (time - preTime) / (curTime - preTime);
return lerp(alphaKeys[i - 1].alpha, alphaKeys[i].alpha, factor);
break;
}
}
const lastIndex = length - 1;
if (approx(time, alphaKeys[lastIndex].time, EPSILON)) {
return alphaKeys[lastIndex].alpha;
} else if (time < alphaKeys[0].time) {
return lerp(basicAlpha, alphaKeys[0].alpha, time / alphaKeys[0].time);
} else if (time > alphaKeys[lastIndex].time) {
return lerp(alphaKeys[lastIndex].alpha, basicAlpha, (time - alphaKeys[lastIndex].time) / (1 - alphaKeys[lastIndex].time));
}
return 255;
} else if (length === 1) {
return alphaKeys[0].alpha;
} else {
return 255;
}
return alpha;
}
}

CCClass.fastDefine('cc.Gradient', Gradient, {
colorKeys: [],
alphaKeys: [],
mode: Mode.Blend,
_colors: [],
_colorTimes: [],
_alphas: [],
_alphaTimes: [],
_mode: Mode.BLEND,
});

CCClass.Attr.setClassAttr(Gradient, 'colorKeys', 'visible', true);
Expand Down
Loading

0 comments on commit 40da83b

Please sign in to comment.