Squashed commit of the following:

commit b421082374
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Fri Dec 31 20:26:20 2021 +0800

    update specialthanks

commit 765a69294b
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Dec 14 19:10:03 2021 +0800

    fix ios goto

commit 8eb8c3ca72
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Dec 14 19:03:37 2021 +0800

    add event grade

commit ab705dd46c
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Dec 14 18:48:42 2021 +0800

    build version

commit a1e4232369
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Dec 14 18:47:05 2021 +0800

    change talent replace before property allocate

commit f4d7b3ae3c
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Dec 14 18:06:18 2021 +0800

    add event grade

commit 0567e40ddc
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 21:28:10 2021 +0800

    add particle

commit f17003925e
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 20:14:26 2021 +0800

    change ui

commit f8beda1d8f
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 19:08:30 2021 +0800

    change popup message ui

commit 915a2aa17d
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 18:34:29 2021 +0800

    new build

commit b5edabc104
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 18:18:46 2021 +0800

    add hint message

commit a143feadaf
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 17:57:31 2021 +0800

    fix copy bug

commit eab1975791
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 17:56:28 2021 +0800

    add save/load

commit acf9b92134
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Dec 2 14:35:33 2021 +0800

    add theme switch

commit 488a6054ab
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Wed Dec 1 18:30:36 2021 +0800

    fix uiManager bug

commit f0317eaf14
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Wed Dec 1 16:07:03 2021 +0800

    add message popup

commit eb02d1ee6f
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 21:22:54 2021 +0800

    change relocation

commit 60503eae47
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 19:27:16 2021 +0800

    change ScaleButton -> Laya.runtime.ScaleButton

commit 52ef5909c1
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 19:26:31 2021 +0800

    change ScaleButton -> Laya.runtime.ScaleButton

commit 0284f6aa71
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 19:05:24 2021 +0800

    config webpack

commit 0e272ffd99
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 13:17:41 2021 +0800

    add thanks

commit e1e2ab4701
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 28 11:40:21 2021 +0800

    add light theme

commit 4f55c00f86
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sat Nov 27 22:27:39 2021 +0800

    fix bug

commit 1d07bdfc46
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sat Nov 27 21:48:47 2021 +0800

    daily update

commit 52d6a0ca8f
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Wed Nov 24 23:10:04 2021 +0800

    daily update

commit f8dd720d4d
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Wed Nov 24 19:08:13 2021 +0800

    daily update

commit d088c1a862
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 21 21:41:46 2021 +0800

    remove useless

commit a711fcf3ed
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Nov 16 00:53:05 2021 +0800

    add achievement popup
    add page adaptive
    add talent extends

commit 05e02de3db
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sat Nov 13 01:24:04 2021 +0800

    add github and discord

commit bff0109cc5
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sat Nov 13 00:30:01 2021 +0800

    add trajectory auto mode

commit 54c04f65c2
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Fri Nov 12 19:54:31 2021 +0800

    fix property judge negative number bug

commit 660739530b
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Fri Nov 12 19:48:58 2021 +0800

    update achievement

commit c94e9e7433
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Thu Nov 11 21:37:45 2021 +0800

    update daily

commit c06cd9ea62
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Tue Nov 9 00:08:05 2021 +0800

    update daily

commit 2666983f89
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 7 23:00:22 2021 +0800

    add uiManager auto scan and load skin resource

commit 22fa5d755a
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Nov 7 22:17:04 2021 +0800

    update framework

commit f40698d63e
Author: Vick Scarlet <scarlet_vick@outlook.com>
Date:   Sun Oct 31 00:13:22 2021 +0800

    add laya
This commit is contained in:
Vick Scarlet
2021-12-31 20:31:26 +08:00
parent 99640a5813
commit 150c991648
372 changed files with 305714 additions and 5801 deletions

597
src/ui/layaUI.max.all.js Normal file

File diff suppressed because one or more lines are too long

25
src/ui/pluginFunction.js Normal file
View File

@@ -0,0 +1,25 @@
const plugin =
Laya.plugin = {};
plugin.extractComponents = function(uiView, componentNames) {
const components = {};
const deepSearch = (uiView, componentNames) => {
if(!uiView.child) return;
for(let i = uiView.child.length - 1; i >= 0; i--) {
const child = uiView.child[i];
if(componentNames.includes(child?.props.name)) {
components[child.props.name] = child;
uiView.child.splice(i, 1);
continue;
}
deepSearch(child, componentNames, components);
}
};
deepSearch(uiView, componentNames);
return componentName => {
if(components[componentName]) {
return Laya.View.createComp(components[componentName]);
}
return null;
}
}

34
src/ui/promisesLaya.js Normal file
View File

@@ -0,0 +1,34 @@
Laya.promises = {
Tween: {
from: async function (target, props, duration, ease, delay, coverBefore) {
return new Promise(function (resolve, reject) {
try {
Laya.Tween.from(target, props, duration, ease, Laya.Handler.create(null, ()=>resolve(), null, true), delay, coverBefore);
} catch (e) {
reject(e);
}
});
},
to: async function (target, props, duration, ease, delay, coverBefore) {
return new Promise(function (resolve, reject) {
try {
Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(null, ()=>resolve(), null, true), delay, coverBefore);
} catch (e) {
reject(e);
}
});
},
},
loader: {
load: async function (url, progress, type) {
return new Promise(function (resolve, reject) {
try {
Laya.loader.load(url, Laya.Handler.create(null, ret=>resolve(ret), null, true), progress, type);
} catch (e) {
reject(e);
}
});
}
}
};

537
src/ui/runtime.js Normal file
View File

@@ -0,0 +1,537 @@
const runtime =
Laya.runtime = {};
runtime.ColorFilterItem =
class ColorFilterItem extends Laya.Image {
constructor() {
super();
}
#hexToRgba = (hex) => {
const rgba = [];
hex = hex.replace('#', '');
hex = hex.match(new RegExp('(.{2})(.{2})(.{2})(.{2})', 'i'));
hex.forEach((item, index) => {
rgba[index] = parseInt(item, 16);
});
rgba.shift();
return rgba;
}
#rgbaToMatrix = (rgba) => {
let matrix = [
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
];
matrix[0] = rgba[0] / 255;
matrix[6] = rgba[1] / 255;
matrix[12] = rgba[2] / 255;
matrix[18] = rgba[3] / 255;
return matrix;
}
get colorFilter() {
return this._colorFilter;
}
set colorFilter(value) {
this._colorFilter = value;
if(value) {
const rgba = this.#hexToRgba(this.colorFilter);
const matrix = this.#rgbaToMatrix(rgba);
const colorFilter = new Laya.ColorFilter(matrix);
this.filters = [colorFilter];
} else {
this.filters = [];
}
}
}
runtime.UIBase =
class UIBase extends Laya.View {
constructor() {
super();
}
}
runtime.ViewBase =
class ViewBase extends runtime.UIBase {
constructor() {
super();
}
}
runtime.DialogBase =
class DialogBase extends runtime.UIBase {
constructor() {
super();
}
}
runtime.ScaleButton =
class ScaleButton extends Laya.Button {
constructor() {
super();
this.on(Laya.Event.MOUSE_DOWN, this, this.onMouse, [Laya.Event.MOUSE_DOWN]);
this.on(Laya.Event.MOUSE_OUT, this, this.onMouse, [Laya.Event.MOUSE_OUT]);
this.on(Laya.Event.MOUSE_UP, this, this.onMouse, [Laya.Event.MOUSE_UP]);
}
onMouse(type) {
Laya.Tween.clearAll(this);
switch (type) {
case Laya.Event.MOUSE_DOWN:
Laya.Tween.to(this, { scaleX: 0.9, scaleY: 0.9 }, 100);
break;
case Laya.Event.MOUSE_OUT:
case Laya.Event.MOUSE_UP:
Laya.Tween.to(this, { scaleX: 1, scaleY: 1 }, 100);
break;
default:
break;
}
}
}
runtime.RGBAItem =
class RGBAItem {
constructor(config={}) {
for(const key in config)
switch(key) {
case 'r':
case 'g':
case 'b':
case 'a':
case 'hex':
case 'hexa':
case 'rgb':
case 'rgba':
this[key] = config[key];
break;
case 'on':
this.on(config[key]);
break;
default:
break;
}
}
#r;
#g;
#b;
#a;
#on = new Set();
on(fn) {
this.#on.add(fn);
}
off(fn) {
this.#on.delete(fn);
}
clear() {
this.#on.clear();
}
#event() {
this.#on.forEach(fn => fn(this));
}
#rgb(v) {
return [
this.#dec(v.slice(1, 3)),
this.#dec(v.slice(3, 5)),
this.#dec(v.slice(5, 7)),
];
}
#rgba(v) {
return [
this.#dec(v.slice(1, 3)),
this.#dec(v.slice(3, 5)),
this.#dec(v.slice(5, 7)),
this.#dec(v.slice(7, 9)),
];
}
#hex(v) {
v = parseInt(v).toString(16);
return v.length == 1 ? '0' + v : v;
}
#dec(v) {
return parseInt(v, 16);
}
get hex() {
return `#${
this.#hex(this.r)
}${
this.#hex(this.g)
}${
this.#hex(this.b)
}`;
}
set hex(v) {
[this.#r, this.#g, this.#b] = this.#rgb(v);
this.#event();
}
get hexa() {
return `#${
this.#hex(this.r)
}${
this.#hex(this.g)
}${
this.#hex(this.b)
}${
this.#hex(this.a)
}`;
}
set hexa(v) {
[this.#r, this.#g, this.#b] = this.#rgba(v);
this.#event();
}
get rgb() {
return [this.r, this.g, this.b];
}
set rgb(v) {
[this.#r, this.#g, this.#b] = v;
this.#event();
}
get rgba() {
return [this.r, this.g, this.b, this.a];
}
set rgba(v) {
[this.#r, this.#g, this.#b, this.#a] = v;
this.#event();
}
get r() {
return this.#r||0;
}
set r(value) {
this.#r = value;
this.#event();
}
get g() {
return this.#g||0;
}
set g(value) {
this.#g = value;
this.#event();
}
get b() {
return this.#b||0;
}
set b(value) {
this.#b = value;
this.#event();
}
get a() {
return this.#a||0;
}
set a(value) {
this.#a = value;
this.#event();
}
cRgb(hex) {
const [r, g, b] = this.#rgb(hex);
return {r, g, b};
}
cRgba(hexa) {
const [r, g, b, a] = this.#rgba(hexa);
return {r, g, b, a};
}
distance(left, right) {
const [lr, lg, lb] = this.#rgb(left);
const [rr, rg, rb] = this.#rgb(right);
const {r, g, b} = this;
const ddr = Math.abs(r - lr);
const ddg = Math.abs(g - lg);
const ddb = Math.abs(b - lb);
const result = (d, a, b) => ((d / Math.abs(b - a)) || 0);
switch(Math.max(ddr, ddg, ddb)) {
case ddr: return result(ddr, lr, rr);
case ddg: return result(ddg, lg, rg);
case ddb: return result(ddb, lb, rb);
default: return 1;
}
}
}
runtime.ColorfulBox =
class ColorfulBox extends Laya.Box {
constructor() {
super();
this.on(Laya.Event.MOUSE_OVER, this, this.onMouse, [Laya.Event.MOUSE_DOWN]);
// this.on(Laya.Event.MOUSE_DOWN, this, this.onMouse, [Laya.Event.MOUSE_DOWN]);
this.on(Laya.Event.MOUSE_OUT, this, this.onMouse, [Laya.Event.MOUSE_OUT]);
// this.on(Laya.Event.MOUSE_UP, this, this.onMouse, [Laya.Event.MOUSE_UP]);
this.#draw();
}
#defaultColor = '#ffffff';
#hoverColor = '#ffffff';
#defaultStroke = '#ffffff';
#hoverStroke = '#ffffff';
#defaultLabel = '#000000';
#hoverLabel = '#000000';
#color = new runtime.RGBAItem({hex: this.#defaultColor, on: ()=>this.#draw()});
#stroke = new runtime.RGBAItem({hex: this.#defaultStroke, on: ()=>this.#draw()});
#label = new runtime.RGBAItem({hex: this.#defaultLabel, on: ({hex})=>{
const label = this.getChildByName('label');
if (!label) return;
label.color = hex;
}});
#lineWidth = 0;
#radius = 0;
#animationTime = 200;
#state = 1;
onMouse(type) {
const label = this.getChildByName('label');
const tween = (colorItem, target, last) => {
Laya.Tween.clearAll(colorItem);
const distance = colorItem.distance(target, last);
if(!isFinite(distance)) {
colorItem.hex = target;
return;
}
Laya.Tween.to(colorItem, colorItem.cRgb(target), colorItem.distance(target, last) * this.#animationTime);
}
switch (type) {
case Laya.Event.MOUSE_OVER:
case Laya.Event.MOUSE_DOWN:
if(this.#state == 2) return;
this.#state = 2;
tween(this.#color, this.#hoverColor, this.#defaultColor);
tween(this.#stroke, this.#hoverStroke, this.#defaultStroke);
if(label) tween(this.#label, this.#hoverLabel, this.#defaultLabel);
break;
case Laya.Event.MOUSE_OUT:
case Laya.Event.MOUSE_UP:
if(this.#state == 1) return;
this.#state = 1;
tween(this.#color, this.#defaultColor, this.#hoverColor);
tween(this.#stroke, this.#defaultStroke, this.#hoverStroke);
if(label) tween(this.#label, this.#defaultLabel, this.#hoverLabel);
break;
default:
break;
}
}
#draw() {
this.graphics.clear();
const w = this.width;
const h = this.height;
const r = Math.min(this.#radius, w / 2, h / 2);
const fillStyle = this.#color.hex;
const strokeStyle = this.#stroke.hex;
const lineWidth = this.lineWidth;
if(r <= 0) {
this.graphics.drawRect(0, 0, w, h, fillStyle, strokeStyle, lineWidth);
return;
}
const a = w + lineWidth;
const b = h + lineWidth;
const c = r + lineWidth;
const d = a - r;
const e = b - r;
const f = -lineWidth;
this.graphics.drawPath(0, 0, [
["moveTo", c, f],
["arcTo", a, f, a, c, c],
["arcTo", a, b, d, b, c],
["arcTo", f, b, f, e, c],
["arcTo", f, f, c, f, c],
["closePath"],
], { fillStyle: strokeStyle });
const x = w - r;
const y = h - r;
this.graphics.drawPath(0, 0, [
["moveTo", r, 0],
["arcTo", w, 0, w, r, r],
["arcTo", w, h, x, h, r],
["arcTo", 0, h, 0, y, r],
["arcTo", 0, 0, r, 0, r],
["closePath"],
], { fillStyle });
}
get width() {
return super.width;
}
set width(value) {
super.width = value;
this.#draw();
}
get height() {
return super.height;
}
set height(value) {
super.height = value;
this.#draw();
}
get defaultColor() {
return this.#defaultColor;
}
set defaultColor(value) {
this.#defaultColor = value;
Laya.Tween.clearAll(this.#color);
Laya.Tween.clearAll(this.#stroke);
Laya.Tween.clearAll(this.#label);
this.#color.hex = value;
}
get hoverColor() {
return this.#hoverColor;
}
set hoverColor(value) {
this.#hoverColor = value;
}
get defaultStroke() {
return this.#defaultStroke;
}
set defaultStroke(value) {
this.#defaultStroke = value;
Laya.Tween.clearAll(this.#color);
Laya.Tween.clearAll(this.#stroke);
Laya.Tween.clearAll(this.#label);
this.#stroke.hex = value;
}
get hoverStroke() {
return this.#hoverStroke;
}
set hoverStroke(value) {
this.#hoverStroke = value;
}
get defaultLabel() {
return this.#defaultLabel;
}
set defaultLabel(value) {
this.#defaultLabel = value;
const label = this.getChildByName('label');
if (!label) return;
Laya.Tween.clearAll(this.#color);
Laya.Tween.clearAll(this.#stroke);
Laya.Tween.clearAll(this.#label);
label.color = value;
}
get hoverLabel() {
return this.#hoverLabel;
}
set hoverLabel(value) {
this.#hoverLabel = value;
}
get animationTime() {
return this.#animationTime;
}
set animationTime(value) {
this.#animationTime = value;
}
get radius() {
return this.#radius||0;
}
set radius(value) {
this.#radius = value;
this.#draw();
}
get lineWidth() {
return this.#lineWidth||0;
}
set lineWidth(value) {
this.#lineWidth = value;
this.#draw();
}
get label() {
return this.getChildByName('label')?.text;
}
set label(value) {
const label = this.getChildByName('label');
if (!label) return;
label.text = value;
}
}
runtime.BlankBox =
class BlankBox extends Laya.Box {
constructor() {
super();
this.mask = new Laya.Sprite();
this.#blank = new Laya.Sprite();
this.addChild(this.#blank);
}
#blank;
#timeLine;
#pause = true;
#draw() {
this.mask.graphics.clear();
this.#blank.graphics.clear();
this.mask.graphics.drawRect(0, 0, this.width, this.height, '#000000');
this.#blank.graphics.drawRect(0, 0, this.width, this.height, '#000000');
if(this.#timeLine) this.#timeLine.destroy();
this.#timeLine = new Laya.TimeLine()
.to(this.#blank, { x: this.width }, 2000)
.to(this.#blank, { x: -this.width }, 0);
this.#timeLine.play(0, true);
if(this.#pause) this.#timeLine.pause();
}
get pause() {
return this.#pause;
}
set pause(value) {
if(this.#pause == value) return;
this.#pause = value;
this.#blank.visible = !value;
if(value) this.#timeLine.pause();
else this.#timeLine.resume();
}
destroy(destroyChild) {
this.#timeLine.destroy(true);
super.destroy(destroyChild);
}
get width() {
return super.width;
}
set width(value) {
super.width = value;
this.#blank.x = -this.width;
this.#draw();
}
get height() {
return super.height;
}
set height(value) {
super.height = value;
this.#draw();
}
}

View File

@@ -0,0 +1,102 @@
export default class CyberAchievement extends ui.view.CyberTheme.CyberAchievementUI {
constructor() {
super();
this.btnBack.on(Laya.Event.CLICK, this, () => $ui.switchView(UI.pages.MAIN));
const min = Math.min(this.btnAchievement.fontSize, this.btnStatistics.fontSize);
const max = Math.max(this.btnAchievement.fontSize, this.btnStatistics.fontSize);
this.#state = {min, max};
this.btnStatistics.on(Laya.Event.CLICK, this, ()=>this.switch('statistics'));
this.btnAchievement.on(Laya.Event.CLICK, this, ()=>this.switch('achievement'));
this.btnRank.on(Laya.Event.CLICK, this, $$event, ['message', ['M_NoRank']]);
this.listAchievements.renderHandler = new Laya.Handler(this, this.onRenderAchievement);
this.listAchievements.scrollBar.elasticDistance = 150;
this.on(Laya.Event.RESIZE, this, () => {
this.boxPage.width = 2 * this.width;
this.boxA.width = this.boxB.width = this.width;
if(this.boxPage.x < 0) {
this.boxPage.x = - this.width;
}
const renderWidth = this.listAchievements?._itemRender?.props?.width;
if(renderWidth) {
const col = Math.max(Math.floor((this.width - 65) / renderWidth), 1);
this.listAchievements.width = col * renderWidth + (col - 1) * (this.listAchievements.spaceY || 0) + 30;
}
});
}
#state;
#tweens;
init() {
this.switch('statistics', 0);
const {statistics, achievements, PropertyTypes: pt} = core;
this.listAchievements.array = achievements;
this.labRemakeTimes.text = statistics[pt.TMS].value;
this.labRemakeTimesJudge.text = statistics[pt.TMS].judge;
this.labAchievementCountJudge.color = $ui.common.grade[statistics[pt.TMS].grade];
this.labAchievementCount.text = statistics[pt.CACHV].value;
this.labAchievementCountJudge.text = statistics[pt.CACHV].judge;
this.labAchievementCountJudge.color = $ui.common.grade[statistics[pt.CACHV].grade];
this.labEventRate.text = parseInt(statistics[pt.REVT].value*100)+'%';
this.prgEventRate.value = statistics[pt.REVT].value;
this.labTalentRate.text = parseInt(statistics[pt.RTLT].value*100)+'%';
this.prgTalentRate.value = statistics[pt.RTLT].value;
}
switch(page, time=300) {
if(this.#tweens) {
this.#tweens.forEach(tween => Laya.Tween.clear(tween));
}
this.#tweens = [];
switch (page) {
case 'statistics':
time = - this.boxPage.x / this.width * time;
this.#tweens.push(
Laya.Tween.to(this.boxPage, {x: 0}, time, Laya.Ease.backOut, Laya.Handler.create(this, () => this.#tweens = null)),
Laya.Tween.to(this.btnStatistics, {fontSize: this.#state.max, anchorX: 0.5, anchorY: 1}, time, Laya.Ease.backOut),
Laya.Tween.to(this.btnAchievement, {fontSize: this.#state.min, anchorX: 0.5, anchorY: 1}, time, Laya.Ease.backOut),
);
break;
case 'achievement':
time = (this.width + this.boxPage.x) / this.width * time;
this.#tweens.push(
Laya.Tween.to(this.boxPage, {x: - this.width}, time, Laya.Ease.backOut, Laya.Handler.create(this, () => this.#tweens = null)),
Laya.Tween.to(this.btnStatistics, {fontSize: this.#state.min, anchorX: 0.5, anchorY: 1}, time, Laya.Ease.backOut),
Laya.Tween.to(this.btnAchievement, {fontSize: this.#state.max, anchorX: 0.5, anchorY: 1}, time, Laya.Ease.backOut),
);
break;
}
}
onRenderAchievement(box, index) {
const dataSource = box.dataSource;
const name = box.getChildByName('name');
const description = box.getChildByName('description');
const completed = box.getChildByName('completed');
const uncomplete = box.getChildByName('uncomplete');
if(dataSource.isAchieved) {
name.text = dataSource.name;
description.text = dataSource.description;
completed.visible = true;
uncomplete.visible = false;
} else {
name.text = dataSource.hide? '???': dataSource.name;
description.text = dataSource.hide? '???': dataSource.description;
completed.visible = false;
uncomplete.visible = true;
}
box.colorFilter = $ui.gradeFilter(dataSource.grade);
}
}

View File

@@ -0,0 +1,37 @@
export default class CyberMain extends ui.view.CyberTheme.CyberMainUI {
constructor() {
super();
this.btnRemake.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.TALENT));
this.btnAchievement.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.ACHIEVEMENT));
this.btnThanks.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.THANKS));
this.btnGithub.on(Laya.Event.CLICK, this, goto, ['github']);
this.btnDiscord.on(Laya.Event.CLICK, this, goto, ['discord']);
this.btnThemes.on(Laya.Event.CLICK, this, ()=>$ui.showDialog(UI.pages.THEMES));
this.btnSaveLoad.on(Laya.Event.CLICK, this, ()=>$ui.showDialog(UI.pages.SAVELOAD));
this.on(Laya.Event.RESIZE, this, () => {
const scale = Math.max(
this.width / this.imgBg.width,
this.height / this.imgBg.height
);
this.imgBg.scale(scale, scale);
});
}
static load() {
return [
"fonts/方正像素12.ttf",
"images/atlas/images/accessories.atlas",
"images/atlas/images/border.atlas",
"images/atlas/images/button.atlas",
"images/atlas/images/icons.atlas",
"images/atlas/images/progress.atlas",
"images/atlas/images/slider.atlas",
]
}
init() {
this.btnDiscord.visible =
this.btnAchievement.visible =
this.btnThanks.visible = !!core.times;
}
}

View File

@@ -0,0 +1,20 @@
export default class CyberAchievementPopup extends ui.view.CyberTheme.CyberAchievementPopupUI {
constructor() {
super();
}
async popup({achievement}, parent) {
Laya.Tween.clearAll(this);
Laya.Tween.clearAll(this.boxBg);
this.alpha = 0.8;
this.labName.text = achievement.name;
this.labName.color = $ui.common.grade[achievement.grade];
this.x = - this.width;
this.boxBg.x = this.boxBg.width;
await Promise.all([
Laya.promises.Tween.to(this, {x: 0}, 300, Laya.Ease.strongOut),
Laya.promises.Tween.to(this.boxBg, {x: 0}, 300, Laya.Ease.strongOut, 50),
])
await Laya.promises.Tween.to(this, {alpha: 0}, 3000, Laya.Ease.strongIn);
}
}

View File

@@ -0,0 +1,245 @@
export default class CyberProperty extends ui.view.CyberTheme.CyberPropertyUI {
constructor() {
super();
const types =
this.#types = core.PropertyTypes;
this.btnCharmIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.CHR, 1]);
this.btnCharmReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.CHR, -1]);
this.btnIntelligenceIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.INT, 1]);
this.btnIntelligenceReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.INT, -1]);
this.btnStrengthIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.STR, 1]);
this.btnStrengthReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.STR, -1]);
this.btnMoneyIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.MNY, 1]);
this.btnMoneyReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.MNY, -1]);
this.inputCharm.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.CHR]);
this.inputIntelligence.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.INT]);
this.inputStrength.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.STR]);
this.inputMoney.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.MNY]);
const selectAll = ({currentTarget: item}) => { item.text=''; };
this.inputCharm.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputIntelligence.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputStrength.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputMoney.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.btnRandomAllocate.on(Laya.Event.CLICK, this, this.random);
this.btnNext.on(Laya.Event.CLICK, this, this.next);
this.listSelectedTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
}
#types;
#propertyPoints;
#propertyAllocate;
#propertyAllocateLimit;
init({talents}) {
this.listSelectedTalents.array = talents;
const replace = core.remake(talents.map(talent => talent.id));
if(replace.length > 0) {
$$event('message', [replace.map(v => ['F_TalentReplace', v])]);
}
this.#propertyPoints = core.getPropertyPoints();
this.#propertyAllocateLimit = core.propertyAllocateLimit;
this.labLeftPropertyPoint.text = this.#propertyPoints;
this.#propertyAllocate = {
[this.#types.CHR]: 0,
[this.#types.INT]: 0,
[this.#types.STR]: 0,
[this.#types.MNY]: 0,
}
this.updateAllocate();
}
next() {
const left = this.#propertyPoints - this.total;
if (left > 0) {
return $$event('message', ['F_PropertyPointLeft', left]);
}
$ui.switchView(
UI.pages.TRAJECTORY,
{
propertyAllocate: this.#propertyAllocate,
talents: this.listSelectedTalents.array,
}
);
}
get total() {
return this.#propertyAllocate[this.#types.CHR]
+ this.#propertyAllocate[this.#types.INT]
+ this.#propertyAllocate[this.#types.STR]
+ this.#propertyAllocate[this.#types.MNY];
}
updateAllocate() {
const charm = this.#propertyAllocate[this.#types.CHR];
const intelligence = this.#propertyAllocate[this.#types.INT];
const strength = this.#propertyAllocate[this.#types.STR];
const money = this.#propertyAllocate[this.#types.MNY];
this.inputCharm.text = ''+charm;
this.inputIntelligence.text = ''+intelligence;
this.inputStrength.text = ''+strength;
this.inputMoney.text = ''+money;
this.labLeftPropertyPoint.text = this.#propertyPoints - this.total;
this.btnCharmIncrease.disabled = this.btnCharmIncrease.gray = false;
this.btnCharmReduce.disabled = this.btnCharmReduce.gray = false;
this.btnIntelligenceIncrease.disabled = this.btnIntelligenceIncrease.gray = false;
this.btnIntelligenceReduce.disabled = this.btnIntelligenceReduce.gray = false;
this.btnStrengthIncrease.disabled = this.btnStrengthIncrease.gray = false;
this.btnStrengthReduce.disabled = this.btnStrengthReduce.gray = false;
this.btnMoneyIncrease.disabled = this.btnMoneyIncrease.gray = false;
this.btnMoneyReduce.disabled = this.btnMoneyReduce.gray = false;
if (this.total >= this.#propertyPoints) {
this.btnCharmIncrease.disabled = this.btnCharmIncrease.gray = true;
this.btnIntelligenceIncrease.disabled = this.btnIntelligenceIncrease.gray = true;
this.btnStrengthIncrease.disabled = this.btnStrengthIncrease.gray = true;
this.btnMoneyIncrease.disabled = this.btnMoneyIncrease.gray = true;
} else if (this.total <= 0) {
this.btnCharmReduce.disabled = this.btnCharmReduce.gray = true;
this.btnIntelligenceReduce.disabled = this.btnIntelligenceReduce.gray = true;
this.btnStrengthReduce.disabled = this.btnStrengthReduce.gray = true;
this.btnMoneyReduce.disabled = this.btnMoneyReduce.gray = true;
}
if (charm <= this.#propertyAllocateLimit[0]) {
this.btnCharmReduce.disabled = this.btnCharmReduce.gray = true;
} else if (charm >= this.#propertyAllocateLimit[1]) {
this.btnCharmIncrease.disabled = this.btnCharmIncrease.gray = true;
}
if (intelligence <= this.#propertyAllocateLimit[0]) {
this.btnIntelligenceReduce.disabled = this.btnIntelligenceReduce.gray = true;
} else if (intelligence >= this.#propertyAllocateLimit[1]) {
this.btnIntelligenceIncrease.disabled = this.btnIntelligenceIncrease.gray = true;
}
if (strength <= this.#propertyAllocateLimit[0]) {
this.btnStrengthReduce.disabled = this.btnStrengthReduce.gray = true;
} else if (strength >= this.#propertyAllocateLimit[1]) {
this.btnStrengthIncrease.disabled = this.btnStrengthIncrease.gray = true;
}
if (money <= this.#propertyAllocateLimit[0]) {
this.btnMoneyReduce.disabled = this.btnMoneyReduce.gray = true;
} else if (money >= this.#propertyAllocateLimit[1]) {
this.btnMoneyIncrease.disabled = this.btnMoneyIncrease.gray = true;
}
}
check(left, right, value) {
if (value < left) return false;
if (value > right) return false;
return true;
}
random() {
let t = this.#propertyPoints;
const arr = new Array(4).fill(this.#propertyAllocateLimit[1]);
while (t > 0) {
const sub = Math.round(Math.random() * (Math.min(t, this.#propertyAllocateLimit[1]) - 1)) + 1;
while(true) {
const select = Math.floor(Math.random() * 4) % 4;
if(arr[select] - sub <0) continue;
arr[select] -= sub;
t -= sub;
break;
}
}
this.#propertyAllocate[this.#types.CHR] = this.#propertyAllocateLimit[1] - arr[0];
this.#propertyAllocate[this.#types.INT] = this.#propertyAllocateLimit[1] - arr[1];
this.#propertyAllocate[this.#types.STR] = this.#propertyAllocateLimit[1] - arr[2];
this.#propertyAllocate[this.#types.MNY] = this.#propertyAllocateLimit[1] - arr[3];
this.updateAllocate();
}
onPropertyAllocate(type, value) {
if (!this.check(
this.#propertyAllocateLimit[0],
this.#propertyAllocateLimit[1],
this.#propertyAllocate[type] + value
)) {
return;
}
if (!this.check(
0,
this.#propertyPoints,
this.total + value
)) {
return;
}
this.#propertyAllocate[type] += value;
this.updateAllocate();
}
onPropertyAllocateInput(type, inputItem) {
let value = parseInt(inputItem.text) || 0;
const total = this.total;
if (total + value < 0) {
value = this.#propertyAllocateLimit[0] * 4 - total;
} else if (total + value > this.#propertyPoints) {
value = this.#propertyPoints - total;
}
if (value < this.#propertyAllocateLimit[0]) {
value = this.#propertyAllocateLimit[0];
} else if (value > this.#propertyAllocateLimit[1]) {
value = this.#propertyAllocateLimit[1];
}
const alter = value - this.#propertyAllocate[type];
if (alter) {
this.onPropertyAllocate(type, alter);
} else {
this.updateAllocate();
}
}
renderTalent(box) {
const dataSource = box.dataSource;
const labTitle = box.getChildByName("labTitle");
const grade1 = box.getChildByName("grade1");
const grade2 = box.getChildByName("grade2");
const grade3 = box.getChildByName("grade3");
const labDescription = box.getChildByName("labDescription");
labTitle.text = dataSource.name;
labDescription.text = dataSource.description;
switch (dataSource.grade) {
case 1:
grade1.visible = true;
grade2.visible = false;
grade3.visible = false;
break;
case 2:
grade1.visible = false;
grade2.visible = true;
grade3.visible = false;
break;
case 3:
grade1.visible = false;
grade2.visible = false;
grade3.visible = true;
break;
default:
grade1.visible = false;
grade2.visible = false;
grade3.visible = false;
break;
}
}
}

View File

@@ -0,0 +1,126 @@
export default class CyberSummary extends ui.view.CyberTheme.CyberSummaryUI {
constructor() {
super();
this.listSelectedTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
this.btnAgain.on(Laya.Event.CLICK, this, this.onAgain);
}
#selectedTalent;
onAgain() {
core.talentExtend(this.#selectedTalent);
core.times ++;
$ui.switchView(UI.pages.MAIN);
}
init({talents}) {
const {summary, lastExtendTalent} = core;
const gradeFilters = $ui.common.filter;
const gradeColors = $ui.common.grade;
const age = summary[core.PropertyTypes.HAGE];
this.labAge.text = ''+age.value;
this.labAgeJudge.text = age.judge;
this.labAgeJudge.color = gradeColors[age.grade];
const sum = summary[core.PropertyTypes.SUM];
this.labTotal.text = ''+sum.value;
this.labTotalJudge.text = sum.judge;
this.labTotalJudge.color = gradeColors[sum.grade];
const chr = summary[core.PropertyTypes.HCHR];
this.labCharm.text = ''+chr.value;
this.prgCharm.value = chr.progress;
this.labCharmJudge.text = chr.judge;
this.labCharmJudge.color = gradeColors[chr.grade];
this.boxCharmGrade.colorFilter = gradeFilters[chr.grade];
const int = summary[core.PropertyTypes.HINT];
this.labIntelligence.text = ''+int.value;
this.prgIntelligence.value = int.progress;
this.labIntelligenceJudge.text = int.judge;
this.labIntelligenceJudge.color = gradeColors[int.grade];
this.boxIntelligenceGrade.colorFilter = gradeFilters[int.grade];
const str = summary[core.PropertyTypes.HSTR];
this.labStrength.text = ''+str.value;
this.prgStrength.value = str.progress;
this.labStrengthJudge.text = str.judge;
this.labStrengthJudge.color = gradeColors[str.grade];
this.boxStrengthGrade.colorFilter = gradeFilters[str.grade];
const mny = summary[core.PropertyTypes.HMNY];
this.labMoney.text = ''+mny.value;
this.prgMoney.value = mny.progress;
this.labMoneyJudge.text = mny.judge;
this.labMoneyJudge.color = gradeColors[mny.grade];
this.boxMoneyGrade.colorFilter = gradeFilters[mny.grade];
const spr = summary[core.PropertyTypes.HSPR];
this.labSpirit.text = ''+spr.value;
this.prgSpirit.value = spr.progress;
this.labSpiritJudge.text = spr.judge;
this.labSpiritJudge.color = gradeColors[spr.grade];
this.boxSpiritGrade.colorFilter = gradeFilters[spr.grade];
talents.sort(({id:a, grade:ag}, {id:b, grade:bg},)=>{
if(a == lastExtendTalent) return -1;
if(b == lastExtendTalent) return 1;
return bg - ag;
});
this.#selectedTalent = talents[0].id;
this.listSelectedTalents.array = talents;
}
renderTalent(box) {
const dataSource = box.dataSource;
const labTitle = box.getChildByName("labTitle");
const grade1 = box.getChildByName("grade1");
const grade2 = box.getChildByName("grade2");
const grade3 = box.getChildByName("grade3");
const labDescription = box.getChildByName("labDescription");
const selected = box.getChildByName("selected");
const unselected = box.getChildByName("unselected");
labTitle.text = dataSource.name;
labDescription.text = dataSource.description;
switch (dataSource.grade) {
case 1:
grade1.visible = true;
grade2.visible = false;
grade3.visible = false;
break;
case 2:
grade1.visible = false;
grade2.visible = true;
grade3.visible = false;
break;
case 3:
grade1.visible = false;
grade2.visible = false;
grade3.visible = true;
break;
default:
grade1.visible = false;
grade2.visible = false;
grade3.visible = false;
break;
}
selected.visible = dataSource.id == this.#selectedTalent;
unselected.visible = !selected.visible;
box.off(Laya.Event.CLICK, this, this.onSelectTalent);
box.on(Laya.Event.CLICK, this, this.onSelectTalent, [dataSource.id]);
}
onSelectTalent(talentId) {
if(talentId == this.#selectedTalent) {
this.#selectedTalent = null;
} else {
this.#selectedTalent = talentId;
}
this.listSelectedTalents.refresh();
}
}

View File

@@ -0,0 +1,121 @@
export default class CyberTalent extends ui.view.CyberTheme.CyberTalentUI {
constructor() {
super();
this.btnDrawCard.on(Laya.Event.CLICK, this, this.onClickDrawCard);
this.btnNext.on(Laya.Event.CLICK, this, this.onClickNext);
this.listTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
this.listTalents.scrollBar.elasticDistance = 150;
this.on(Laya.Event.RESIZE, this, () => {
const renderWidth = this.listTalents?._itemRender?.props?.width;
if(renderWidth) {
const col = Math.max(Math.floor((this.width - 40) / renderWidth), 1);
this.listTalents.width = col * renderWidth + (col - 1) * (this.listTalents.spaceY || 0);
}
});
}
#selected = new Set();
static load() {
return ['images/background/background_2@3x.png'];
}
init() {
this.pageDrawCard.visible = true;
this.pageResult.visible = false;
this.btnNext.label = 'UI_Talent_Select_Uncomplete';
this.#selected.clear();
}
close() {}
onClickDrawCard() {
this.pageDrawCard.visible = false;
this.pageResult.visible = true;
this.listTalents.array = core.talentRandom();
}
onClickNext() {
if(this.#selected.size < core.talentSelectLimit) {
return $$event('message', ['F_TalentSelectNotComplect', core.talentSelectLimit]);
}
const talents = [...this.#selected].map(index => this.listTalents.array[index]);
$ui.switchView(UI.pages.PROPERTY, { talents });
}
renderTalent(box, index) {
const dataSource = box.dataSource;
const hboxTitle = box.getChildByName("hboxTitle");
const labTitle = hboxTitle.getChildByName("labTitle");
const grades = hboxTitle.getChildByName("grades");
const grade1 = grades.getChildByName("grade1");
const grade2 = grades.getChildByName("grade2");
const grade3 = grades.getChildByName("grade3");
const labDescription = box.getChildByName("labDescription");
const unselected = box.getChildByName("unselected");
const selected = box.getChildByName("selected");
switch (dataSource.grade) {
case 1:
grades.x = 0;
labTitle.x = 1;
grade1.visible = true;
grade2.visible = false;
grade3.visible = false;
break;
case 2:
grades.x = 0;
labTitle.x = 1;
grade1.visible = false;
grade2.visible = true;
grade3.visible = false;
break;
case 3:
grades.x = 0;
labTitle.x = 1;
grade1.visible = false;
grade2.visible = false;
grade3.visible = true;
break;
default:
grades.x = 1;
labTitle.x = 0;
grade1.visible = false;
grade2.visible = false;
grade3.visible = false;
break;
}
labTitle.text = dataSource.name;
labTitle.event(Laya.Event.RESIZE);
labDescription.text = dataSource.description;
unselected.visible = !( selected.visible = this.#selected.has(index) );
box.offAll(Laya.Event.CLICK);
box.on(Laya.Event.CLICK, this, () => {
if(this.#selected.has(index)) {
this.#selected.delete(index);
} else {
if(this.#selected.size >= core.talentSelectLimit) {
return $$event('message', ['F_TalentSelectLimit', core.talentSelectLimit]);
}
const exclusive = core.exclusive(
[...this.#selected].map(index => this.listTalents.array[index].id),
this.listTalents.array[index].id
);
if(exclusive != null) {
for(const {name, id} of this.listTalents.array)
if(exclusive == id)
return $$event('message', ['F_TalentConflict', name]);
return;
}
this.#selected.add(index);
}
this.btnNext.label = this.#selected.size === core.talentSelectLimit
? 'UI_Next'
: 'UI_Talent_Select_Uncomplete';
unselected.visible = !( selected.visible = this.#selected.has(index) );
});
}
}

View File

@@ -0,0 +1,167 @@
export default class CyberTrajectory extends ui.view.CyberTheme.CyberTrajectoryUI {
constructor() {
super();
let pos1 = [0, 0];
this.panelTrajectory.on(Laya.Event.MOUSE_DOWN, this, e => pos1 = [e.stageX, e.stageY]);
this.panelTrajectory.on(Laya.Event.MOUSE_UP, this, e => {
const distanceX = e.stageX - pos1[0];
const distanceY = e.stageY - pos1[1];
if(Math.sqrt(Math.abs(distanceX) + Math.abs(distanceY)) > 10) {
return;
}
this.onNext();
});
this.btnSummary.on(Laya.Event.CLICK, this, this.onSummary);
this.panelTrajectory.vScrollBar.elasticDistance = 150;
let interval = null;
let timeout = null;
const scroll = alter => {
let value = this.panelTrajectory.vScrollBar.value + alter;
if(value < 0) value = 0;
if(value > this.panelTrajectory.vScrollBar.max) value = this.panelTrajectory.vScrollBar.max;
this.panelTrajectory.scrollTo(0, value);
}
const on = (btn, alter) => {
btn.off(Laya.Event.CLICK, this, scroll);
btn.on(Laya.Event.CLICK, this, scroll, [100*alter]);
timeout = setTimeout(() => {
btn.off(Laya.Event.CLICK, this, scroll);
interval = setInterval(() => scroll(10*alter), 10);
}, 100);
}
const clear = () => {
if(interval) {
clearInterval(interval);
interval = null;
}
if(timeout) {
clearTimeout(timeout);
timeout = null;
}
};
this.btnUp.on(Laya.Event.MOUSE_DOWN, this, on, [this.btnUp, -1]);
this.btnDown.on(Laya.Event.MOUSE_DOWN, this, on, [this.btnDown, 1]);
this.btnUp.on(Laya.Event.MOUSE_UP, this, clear);
this.btnUp.on(Laya.Event.MOUSE_OUT, this, clear);
this.btnDown.on(Laya.Event.MOUSE_UP, this, clear);
this.btnDown.on(Laya.Event.MOUSE_OUT, this, clear);
this.scbSpeed.on(Laya.Event.CHANGE, this, () => this.speed = this.scbSpeed.value);
this.scbSpeed.on(Laya.Event.MOUSE_UP, this, () => this.onNext());
}
#speed;
#auto;
static #createComponent = Laya.plugin.extractComponents(CyberTrajectory.uiView, ['boxTrajectoryItem']);
#createTrajectoryItem() {
const item = CyberTrajectory.#createComponent('boxTrajectoryItem');
item.labContent = item.getChildByName('labContent');
item.labAge = item.getChildByName('hboxAge').getChildByName('labAge');
item.boxGrade = item.getChildByName('boxGrade');
return item;
}
#isEnd;
#trajectoryItems;
#talents;
init({propertyAllocate, talents}) {
this.boxParticle.visible = false;
this.boxSpeed.visible = true;
this.btnSummary.visible = false;
this.#trajectoryItems = [];
this.#isEnd = false;
this.#talents = talents;
core.start(propertyAllocate);
this.updateProperty();
this.onNext();
}
close() {
this.scbSpeed.value = 0;
this.speed = 0;
this.#trajectoryItems.forEach(item => {
item.removeSelf();
item.destroy();
});
this.#trajectoryItems = null;
}
updateProperty() {
const types = core.PropertyTypes;
const propertys = core.propertys;
this.labCharm.text = propertys[types.CHR];
this.labIntelligence.text = propertys[types.INT];
this.labStrength.text = propertys[types.STR];
this.labMoney.text = propertys[types.MNY];
this.labSpirit.text = propertys[types.SPR];
}
onNext() {
if(this.#isEnd) return;
const { age, content, isEnd } = core.next();
this.#isEnd = isEnd;
if(isEnd) {
this.boxSpeed.visible = false;
this.btnSummary.visible = true;
}
this.renderTrajectory(age, content);
if(age >= 100) {
this.boxParticle.visible = true;
}
Laya.timer.frameOnce(1, this, () => {
this.panelTrajectory.scrollTo(0, this.panelTrajectory.contentHeight);
});
this.updateProperty();
}
renderTrajectory(age, content) {
const item = this.#createTrajectoryItem();
item.labAge.text = ''+age;
item.labContent.text = content.map(
({type, description, grade, name, postEvent}) => {
switch(type) {
case 'TLT':
return `天赋【${name}】发动:${description}`;
case 'EVT':
return description + (postEvent?`\n${postEvent}`:'');
}
}
).join('\n');
$_.deepMapSet(
item.boxGrade,
$ui.common.gradeBlk[content[content.length - 1].grade || 0]
);
this.vboxTrajectory.addChild(item);
this.#trajectoryItems.push(item);
this.#trajectoryItems.forEach((item, index) => item.y = index);
}
onSummary() {
const talents = this.#talents;
$ui.switchView(UI.pages.SUMMARY, {talents});
}
get speed() {
return this.#speed;
}
set speed(speed) {
this.#speed = speed;
this.prgSpeed.value = speed / this.scbSpeed.max;
clearInterval(this.#auto);
this.#auto = null;
if(!speed) return;
this.#auto = setInterval(
() => this.onNext(),
3000 * (1 - this.prgSpeed.value) + 300
);
}
}

View File

@@ -0,0 +1,53 @@
export default class Achievement extends ui.view.DefaultTheme.AchievementUI {
constructor() {
super();
this.btnBack.on(Laya.Event.CLICK, this, () => $ui.switchView(UI.pages.MAIN));
this.btnRank.on(Laya.Event.CLICK, this, $$event, ['message', ['M_NoRank']]);
this.listAchievements.renderHandler = new Laya.Handler(this, this.onRenderAchievement);
this.listAchievements.scrollBar.elasticDistance = 150;
}
init() {
const {statistics, achievements, PropertyTypes: pt} = core;
this.listAchievements.array = achievements;
this.labRemakeTimes.text = $_.format($lang.F_RemakeTimes, statistics[pt.TMS].value);
this.labRemakeTimesJudge.text = statistics[pt.TMS].judge;
$_.deepMapSet(this.boxRemakeTimes, $ui.common.achievement[statistics[pt.TMS].grade]);
this.labAchievementCount.text = $_.format($lang.F_AchievementCount, statistics[pt.CACHV].value);
this.labAchievementCountJudge.text = statistics[pt.CACHV].judge;
$_.deepMapSet(this.boxAchievementCount, $ui.common.achievement[statistics[pt.CACHV].grade]);
this.labEventRate.text = parseInt(statistics[pt.REVT].value*100)+'%';
this.prgEventRate.scaleX = statistics[pt.REVT].value;
$_.deepMapSet(this.boxEventRate, $ui.common.achievement[statistics[pt.REVT].grade]);
this.labTalentRate.text = parseInt(statistics[pt.RTLT].value*100)+'%';
this.prgTalentRate.scaleX = statistics[pt.RTLT].value;
$_.deepMapSet(this.boxTalentRate, $ui.common.achievement[statistics[pt.RTLT].grade]);
}
onRenderAchievement(box) {
const dataSource = box.dataSource;
const name = box.getChildByName('name');
const description = box.getChildByName('description');
const boxMask = box.getChildByName('boxMask');
$_.deepMapSet(box, $ui.common.achievement[dataSource.grade]);
name.color = description.color = $ui.common.defaultFontColor;
if(dataSource.isAchieved) {
name.text = dataSource.name;
description.text = dataSource.description;
boxMask.visible = false;
} else {
name.text = dataSource.hide? '???': dataSource.name;
description.text = dataSource.hide? '???': dataSource.description;
boxMask.visible = true;
}
}
}

View File

@@ -0,0 +1,27 @@
export default class Main extends ui.view.DefaultTheme.MainUI {
constructor() {
super();
this.btnRemake.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.TALENT));
this.btnAchievement.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.ACHIEVEMENT));
this.btnThanks.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.THANKS));
this.btnGithub.on(Laya.Event.CLICK, this, goto, ['github']);
this.btnDiscord.on(Laya.Event.CLICK, this, goto, ['discord']);
this.btnThemes.on(Laya.Event.CLICK, this, ()=>$ui.showDialog(UI.pages.THEMES));
this.btnSaveLoad.on(Laya.Event.CLICK, this, ()=>$ui.showDialog(UI.pages.SAVELOAD));
}
static load() {
return [
"images/atlas/images/icons.atlas",
]
}
init() {
this.btnDiscord.visible =
this.btnAchievement.visible =
this.btnThanks.visible = !!core.times;
const text = this.labSubTitle.text;
this.labSubTitle.text = ' ';
this.labSubTitle.text = text;
}
}

View File

@@ -0,0 +1,20 @@
export default class achievementPopup extends ui.view.DefaultTheme.AchievementPopupUI {
constructor() {
super();
}
async popup({achievement}, parent) {
Laya.Tween.clearAll(this);
Laya.Tween.clearAll(this.boxBg);
this.alpha = 0.8;
this.labName.text = achievement.name;
this.labName.color = $ui.common.grade[achievement.grade];
this.x = - this.width;
this.boxBg.x = this.boxBg.width;
await Promise.all([
Laya.promises.Tween.to(this, {x: 0}, 300, Laya.Ease.strongOut),
Laya.promises.Tween.to(this.boxBg, {x: 0}, 300, Laya.Ease.strongOut, 50),
])
await Laya.promises.Tween.to(this, {alpha: 0}, 3000, Laya.Ease.strongIn);
}
}

View File

@@ -0,0 +1,183 @@
export default class Property extends ui.view.DefaultTheme.PropertyUI {
constructor() {
super();
const types =
this.#types = core.PropertyTypes;
this.btnCharmIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.CHR, 1]);
this.btnCharmReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.CHR, -1]);
this.btnIntelligenceIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.INT, 1]);
this.btnIntelligenceReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.INT, -1]);
this.btnStrengthIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.STR, 1]);
this.btnStrengthReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.STR, -1]);
this.btnMoneyIncrease.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.MNY, 1]);
this.btnMoneyReduce.on(Laya.Event.CLICK, this, this.onPropertyAllocate, [types.MNY, -1]);
this.inputCharm.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.CHR]);
this.inputIntelligence.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.INT]);
this.inputStrength.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.STR]);
this.inputMoney.on(Laya.Event.INPUT, this, this.onPropertyAllocateInput, [types.MNY]);
const selectAll = ({currentTarget: item}) => { item.text=''; };
this.inputCharm.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputIntelligence.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputStrength.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.inputMoney.on(Laya.Event.MOUSE_DOWN, this, selectAll);
this.btnRandomAllocate.on(Laya.Event.CLICK, this, this.random);
this.btnNext.on(Laya.Event.CLICK, this, this.next);
this.listSelectedTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
}
#types;
#propertyPoints;
#propertyAllocate;
#propertyAllocateLimit;
init({talents}) {
this.listSelectedTalents.array = talents;
const replace = core.remake(talents.map(talent => talent.id));
if(replace.length > 0) {
$$event('message', [replace.map(v => ['F_TalentReplace', v])]);
}
this.#propertyPoints = core.getPropertyPoints();
this.#propertyAllocateLimit = core.propertyAllocateLimit;
this.labLeftPropertyPoint.text = this.#propertyPoints;
this.#propertyAllocate = {
[this.#types.CHR]: 0,
[this.#types.INT]: 0,
[this.#types.STR]: 0,
[this.#types.MNY]: 0,
}
this.updateAllocate();
}
next() {
const left = this.#propertyPoints - this.total;
if (left > 0) {
return $$event('message', ['F_PropertyPointLeft', left]);
}
$ui.switchView(
UI.pages.TRAJECTORY,
{
propertyAllocate: this.#propertyAllocate,
talents: this.listSelectedTalents.array,
}
);
}
get total() {
return this.#propertyAllocate[this.#types.CHR]
+ this.#propertyAllocate[this.#types.INT]
+ this.#propertyAllocate[this.#types.STR]
+ this.#propertyAllocate[this.#types.MNY];
}
updateAllocate() {
const charm = this.#propertyAllocate[this.#types.CHR];
const intelligence = this.#propertyAllocate[this.#types.INT];
const strength = this.#propertyAllocate[this.#types.STR];
const money = this.#propertyAllocate[this.#types.MNY];
this.inputCharm.text = ''+charm;
this.inputIntelligence.text = ''+intelligence;
this.inputStrength.text = ''+strength;
this.inputMoney.text = ''+money;
this.labLeftPropertyPoint.text = this.#propertyPoints - this.total;
this.btnCharmIncrease.disabled = this.btnCharmIncrease.gray = false;
this.btnCharmReduce.disabled = this.btnCharmReduce.gray = false;
this.btnIntelligenceIncrease.disabled = this.btnIntelligenceIncrease.gray = false;
this.btnIntelligenceReduce.disabled = this.btnIntelligenceReduce.gray = false;
this.btnStrengthIncrease.disabled = this.btnStrengthIncrease.gray = false;
this.btnStrengthReduce.disabled = this.btnStrengthReduce.gray = false;
this.btnMoneyIncrease.disabled = this.btnMoneyIncrease.gray = false;
this.btnMoneyReduce.disabled = this.btnMoneyReduce.gray = false;
}
check(left, right, value) {
if (value < left) return false;
if (value > right) return false;
return true;
}
random() {
let t = this.#propertyPoints;
const arr = new Array(4).fill(this.#propertyAllocateLimit[1]);
while (t > 0) {
const sub = Math.round(Math.random() * (Math.min(t, this.#propertyAllocateLimit[1]) - 1)) + 1;
while(true) {
const select = Math.floor(Math.random() * 4) % 4;
if(arr[select] - sub <0) continue;
arr[select] -= sub;
t -= sub;
break;
}
}
this.#propertyAllocate[this.#types.CHR] = this.#propertyAllocateLimit[1] - arr[0];
this.#propertyAllocate[this.#types.INT] = this.#propertyAllocateLimit[1] - arr[1];
this.#propertyAllocate[this.#types.STR] = this.#propertyAllocateLimit[1] - arr[2];
this.#propertyAllocate[this.#types.MNY] = this.#propertyAllocateLimit[1] - arr[3];
this.updateAllocate();
}
onPropertyAllocate(type, value) {
if (!this.check(
this.#propertyAllocateLimit[0],
this.#propertyAllocateLimit[1],
this.#propertyAllocate[type] + value
)) {
return;
}
if (!this.check(
0,
this.#propertyPoints,
this.total + value
)) {
return;
}
this.#propertyAllocate[type] += value;
this.updateAllocate();
}
onPropertyAllocateInput(type, inputItem) {
let value = parseInt(inputItem.text) || 0;
const total = this.total;
if (total + value < 0) {
value = this.#propertyAllocateLimit[0] * 4 - total;
} else if (total + value > this.#propertyPoints) {
value = this.#propertyPoints - total;
}
if (value < this.#propertyAllocateLimit[0]) {
value = this.#propertyAllocateLimit[0];
} else if (value > this.#propertyAllocateLimit[1]) {
value = this.#propertyAllocateLimit[1];
}
const alter = value - this.#propertyAllocate[type];
if (alter) {
this.onPropertyAllocate(type, alter);
} else {
this.updateAllocate();
}
}
renderTalent(box) {
const dataSource = box.dataSource;
box.label = $_.format($lang.F_TalentSelection, dataSource);
const style = $ui.common.card[dataSource.grade].normal;
$_.deepMapSet(box, style);
}
}

View File

@@ -0,0 +1,68 @@
export default class Summary extends ui.view.DefaultTheme.SummaryUI {
constructor() {
super();
this.listSummary.renderHandler = Laya.Handler.create(this, this.renderSummary, null, false);
this.listSelectedTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
this.btnAgain.on(Laya.Event.CLICK, this, this.onAgain);
}
#selectedTalent;
onAgain() {
core.talentExtend(this.#selectedTalent);
core.times ++;
$ui.switchView(UI.pages.MAIN);
}
init({talents}) {
const {summary, lastExtendTalent} = core;
this.listSummary.array = [
[core.PropertyTypes.HCHR, $lang.UI_Property_Charm],
[core.PropertyTypes.HINT, $lang.UI_Property_Intelligence],
[core.PropertyTypes.HSTR, $lang.UI_Property_Strength],
[core.PropertyTypes.HMNY, $lang.UI_Property_Money],
[core.PropertyTypes.HSPR, $lang.UI_Property_Spirit],
[core.PropertyTypes.HAGE, $lang.UI_Final_Age],
[core.PropertyTypes.SUM, $lang.UI_Total_Judge],
].map(([type, key]) => {
const data = summary[type];
return {
label: `${key}${$lang.UI_Colon} ${data.value} ${$lang[data.judge]}`,
grade: data.grade,
}
});
talents.sort(({id:a, grade:ag}, {id:b, grade:bg},)=>{
if(a == lastExtendTalent) return -1;
if(b == lastExtendTalent) return 1;
return bg - ag;
});
this.#selectedTalent = talents[0].id;
this.listSelectedTalents.array = talents;
}
renderSummary(box) {
const {label, grade} = box.dataSource;
box.label = label;
$_.deepMapSet(box, $ui.common.summary[grade]);
}
renderTalent(box) {
const dataSource = box.dataSource;
box.label = $_.format($lang.F_TalentSelection, dataSource);
const style = $ui.common.card[dataSource.grade];
$_.deepMapSet(box, dataSource.id == this.#selectedTalent? style.selected: style.normal);
box.getChildByName('blank').pause = dataSource.id != this.#selectedTalent;
box.off(Laya.Event.CLICK, this, this.onSelectTalent);
box.on(Laya.Event.CLICK, this, this.onSelectTalent, [dataSource.id]);
}
onSelectTalent(talentId) {
if(talentId == this.#selectedTalent) {
this.#selectedTalent = null;
} else {
this.#selectedTalent = talentId;
}
this.listSelectedTalents.refresh();
}
}

View File

@@ -0,0 +1,78 @@
export default class Talent extends ui.view.DefaultTheme.TalentUI {
constructor() {
super();
this.btnDrawCard.on(Laya.Event.CLICK, this, this.onClickDrawCard);
this.btnNext.on(Laya.Event.CLICK, this, this.onClickNext);
this.listTalents.renderHandler = Laya.Handler.create(this, this.renderTalent, null, false);
this.listTalents.scrollBar.elasticDistance = 150;
}
#selected = new Set();
init() {
this.pageDrawCard.visible = true;
this.pageResult.visible = false;
this.btnNext.label = 'UI_Talent_Select_Uncomplete';
this.#selected.clear();
}
close() {}
onClickDrawCard() {
this.pageDrawCard.visible = false;
this.pageResult.visible = true;
this.listTalents.array = core.talentRandom();
}
onClickNext() {
if(this.#selected.size < core.talentSelectLimit) {
return $$event('message', ['F_TalentSelectNotComplect', core.talentSelectLimit]);
}
const talents = [...this.#selected].map(index => this.listTalents.array[index]);
$ui.switchView(UI.pages.PROPERTY, { talents });
}
renderTalent(box, index) {
const dataSource = box.dataSource;
const blank = box.getChildByName('blank');
box.label = $_.format($lang.F_TalentSelection, dataSource);
const style = $ui.common.card[dataSource.grade];
const changeStyle = () => {
const selected = this.#selected.has(index);
blank.pause = !selected;
$_.deepMapSet(box, selected? style.selected: style.normal);
}
changeStyle();
box.offAll(Laya.Event.CLICK);
box.on(Laya.Event.CLICK, this, () => {
if(this.#selected.has(index)) {
this.#selected.delete(index);
} else {
if(this.#selected.size >= core.talentSelectLimit) {
return $$event('message', ['F_TalentSelectLimit', core.talentSelectLimit]);
}
const exclusive = core.exclusive(
[...this.#selected].map(index => this.listTalents.array[index].id),
this.listTalents.array[index].id
);
if(exclusive != null) {
for(const {name, id} of this.listTalents.array)
if(exclusive == id)
return $$event('message', ['F_TalentConflict', name]);
return;
}
this.#selected.add(index);
}
this.btnNext.label = this.#selected.size === core.talentSelectLimit
? 'UI_Next'
: 'UI_Talent_Select_Uncomplete';
changeStyle();
});
}
}

View File

@@ -0,0 +1,59 @@
export default class Thanks extends ui.view.DefaultTheme.ThanksUI {
constructor() {
super();
this.btnBack.on(Laya.Event.CLICK, this, ()=>$ui.switchView(UI.pages.MAIN));
this.listSupports.renderHandler = Laya.Handler.create(this, this.renderSupport, null, false);
this.panelTopSupports.vScrollBar.elasticDistance = 150;
this.listSupports.scrollBar.elasticDistance = 150;
this.btnAFD.on(Laya.Event.CLICK, this, goto, ['sponsor_afd']);
this.btnDDF.on(Laya.Event.CLICK, this, goto, ['sponsor_ddf']);
}
static #createComponent = Laya.plugin.extractComponents(Thanks.uiView, ['boxTopSupport']);
#createTopSupportItem() {
const item = Thanks.#createComponent('boxTopSupport');
item.name = item.getChildByName('name');
item.comment = item.getChildByName('comment');
$_.deepMapSet(item, $ui.common.topSupportItem);
return item;
}
#topSupports;
init() {
const supports = [];
this.#topSupports = [];
core.specialThanks
.sort(()=>0.5-Math.random())
.forEach(({group, name, comment, color})=>
group == 2
? supports.push({name, color})
: this.renderTopSupport(name, comment, color)
);
this.listSupports.array = supports;
}
renderTopSupport(name, comment, color) {
const item = this.#createTopSupportItem();
item.name.text = name;
item.comment.text = comment;
item.name.color = color || '#000000';
this.vboxTopSupports.addChild(item);
this.#topSupports.push(item);
this.#topSupports.forEach((item, index) => item.y = index);
}
renderSupport(label) {
const {name, color} = label.dataSource;
label.text = name;
label.color = color || $ui.common.defaultFontColor;
}
close() {
this.#topSupports.forEach(item => {
item.removeSelf();
item.destroy();
});
this.#topSupports = null;
}
}

View File

@@ -0,0 +1,143 @@
export default class Trajectory extends ui.view.DefaultTheme.TrajectoryUI {
constructor() {
super();
let pos1 = [0, 0];
this.panelTrajectory.on(Laya.Event.MOUSE_DOWN, this, e => pos1 = [e.stageX, e.stageY]);
this.panelTrajectory.on(Laya.Event.MOUSE_UP, this, e => {
const distanceX = e.stageX - pos1[0];
const distanceY = e.stageY - pos1[1];
if(Math.sqrt(Math.abs(distanceX) + Math.abs(distanceY)) > 10) {
return;
}
this.onNext();
});
this.btnSummary.on(Laya.Event.CLICK, this, this.onSummary);
this.panelTrajectory.vScrollBar.elasticDistance = 150;
this.scbSpeed.on(Laya.Event.CHANGE, this, () => this.speed = this.scbSpeed.value);
this.scbSpeed.on(Laya.Event.MOUSE_UP, this, () => this.onNext());
}
#speed;
#auto;
static load() {
return [
"images/atlas/images/progress.atlas",
'images/atlas/images/slider.atlas',
];
}
static #createComponent = Laya.plugin.extractComponents(Trajectory.uiView, ['boxTrajectoryItem']);
#createTrajectoryItem() {
const item = Trajectory.#createComponent('boxTrajectoryItem');
item.labContent = item.getChildByName('labContent');
item.labAge = item.getChildByName('hboxAge').getChildByName('labAge');
const config = $ui.common.trajectoryItem;
$_.deepMapSet(item, config.box);
item.grade = grade => {
$_.deepMapSet(item, config.grade[grade || 0]);
}
item.getChildByName('hboxAge')._childs.forEach(child => child.color = config.ageColor);
item.labContent.color = config.contentColor;
return item;
}
#isEnd;
#trajectoryItems;
#talents;
init({propertyAllocate, talents}) {
this.boxParticle.visible = false;
this.boxSpeed.visible = true;
this.btnSummary.visible = false;
this.#trajectoryItems = [];
this.#isEnd = false;
this.#talents = talents;
core.start(propertyAllocate);
this.updateProperty();
this.onNext();
}
close() {
this.scbSpeed.value = 0;
this.speed = 0;
this.#trajectoryItems.forEach(item => {
item.removeSelf();
item.destroy();
});
this.#trajectoryItems = null;
}
updateProperty() {
const types = core.PropertyTypes;
const propertys = core.propertys;
this.labCharm.text = propertys[types.CHR];
this.labIntelligence.text = propertys[types.INT];
this.labStrength.text = propertys[types.STR];
this.labMoney.text = propertys[types.MNY];
this.labSpirit.text = propertys[types.SPR];
}
onNext() {
if(this.#isEnd) return;
const { age, content, isEnd } = core.next();
this.#isEnd = isEnd;
if(isEnd) {
this.boxSpeed.visible = false;
this.btnSummary.visible = true;
}
this.renderTrajectory(age, content);
if(age >= 100) {
this.boxParticle.visible = true;
}
Laya.timer.frameOnce(1, this, () => {
this.panelTrajectory.scrollTo(0, this.panelTrajectory.contentHeight);
});
this.updateProperty();
}
renderTrajectory(age, content) {
const item = this.#createTrajectoryItem();
item.labAge.text = ''+age;
item.labContent.text = content.map(
({type, description, grade, name, postEvent}) => {
switch(type) {
case 'TLT':
return `天赋【${name}】发动:${description}`;
case 'EVT':
return description + (postEvent?`\n${postEvent}`:'');
}
}
).join('\n');
item.grade(content[content.length - 1].grade);
this.vboxTrajectory.addChild(item);
this.#trajectoryItems.push(item);
this.#trajectoryItems.forEach((item, index) => item.y = index);
}
onSummary() {
const talents = this.#talents;
$ui.switchView(UI.pages.SUMMARY, {talents});
}
get speed() {
return this.#speed;
}
set speed(speed) {
this.#speed = speed;
this.prgSpeed.value = speed / this.scbSpeed.max;
clearInterval(this.#auto);
this.#auto = null;
if(!speed) return;
this.#auto = setInterval(
() => this.onNext(),
3000 * (1 - this.prgSpeed.value) + 300
);
}
}

15
src/ui/themes/loading.js Normal file
View File

@@ -0,0 +1,15 @@
export default class Loading extends ui.view.LoadingUI {
constructor() {
super();
}
static load() {
return [
"images/atlas/images/resource.atlas"
]
}
show() {}
onProgress(progress) {}
}

20
src/ui/themes/message.js Normal file
View File

@@ -0,0 +1,20 @@
export default class MessagePopup extends ui.view.MessagePopupUI {
constructor() {
super();
this.left = this.right = 0;
this.boxBg.defaultColor = "#000000";
this.boxBg.hoverColor = "#000000";
this.boxBg.radius = 20;
}
async popup({message}, parent) {
this.message.text = message;
this.message.commitMeasure();
this.height = this.message.height + this.boxBg.radius * 2 + this.message.fontSize;
Laya.Tween.clearAll(this);
this.alpha = 0;
this.y = - 2 * this.height;
await Laya.promises.Tween.to(this, { y: 0, alpha: 1 }, 300, Laya.Ease.backOut),
await Laya.promises.Tween.to(this, { alpha: 0}, 300, Laya.Ease.strongIn, 3000);
}
}

95
src/ui/themes/saveload.js Normal file
View File

@@ -0,0 +1,95 @@
export default class SaveLoad extends ui.view.SaveLoadUI {
constructor() {
super();
this.btnClose.on(Laya.Event.CLICK, this, async ()=>{
await this.close();
$ui.switchView(UI.pages.MAIN);
});
this.btnRead.on(Laya.Event.CLICK, this, async ()=>{
const result = await $$copy(this.input.text = this.data);
$$event('message', [result? 'UI_CopySuccess': 'UI_CopyFaild']);
});
this.btnWrite.on(Laya.Event.CLICK, this, async ()=>{
const text = await $$read();
if(text == false) {
this.data = [
this.input.text,
'UI_PasteFaildDecodeSuccess',
'UI_PasteFaildDecodeFaild'
];
} else {
this.input.text = text;
this.data = [
text,
'UI_PasteSuccessDecodeSuccess',
'UI_PasteSuccessDecodeFaild'
];
}
});
this.btnSave.on(Laya.Event.CLICK, this, ()=>{
let blob = new Blob([this.data], { type: 'application/json' });
const slice = blob.slice || blob.webkitSlice || blob.mozSlice;
blob = slice.call(blob, 0, blob.size, 'application/octet-stream');
const a = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
a.href = URL.createObjectURL(blob);
a.download = `Remake_save_${new Date().toISOString().replace(':','.')}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
});
this.btnLoad.on(Laya.Event.CLICK, this, ()=>{
const file = document.createElement('input');
file.setAttribute('type', 'file');
file.setAttribute('name', 'file');
file.setAttribute('accept', 'application/json');
file.setAttribute('style', 'display: none;');
document.body.appendChild(file);
file.click();
file.onchange = (e)=>{
const file = e.target.files[0];
if(!file) return;
const reader = new FileReader();
reader.onload = () => this.data = [reader.result];
reader.readAsText(file);
document.body.removeChild(file);
};
});
this.input.on(Laya.Event.MOUSE_DOWN, this, ()=>{
this.input.setSelection(0, this.input.text.length);
})
}
static load() {
return ["images/atlas/images/radio.atlas"];
}
init() {
this.input.text = this.data;
}
get data() {
const data = {};
Object
.keys(localStorage)
.filter(v=>v.substr(0,4)!='goog')
.forEach(key=>data[key] = localStorage[key]);
return JSON.stringify(data);
}
set data([v, success = 'UI_LoadSuccess', faild = 'UI_LoadFaild']) {
try {
const data = JSON.parse(v);
for(const key in data)
localStorage.setItem(key, data[key]);
$$event('message', [success]);
$ui.theme = $ui.theme;
this.btnClose.event(Laya.Event.CLICK);
} catch (e) {
console.error(e);
$$event('message', [faild]);
}
}
}

40
src/ui/themes/themes.js Normal file
View File

@@ -0,0 +1,40 @@
export default class Themes extends ui.view.ThemesUI {
constructor() {
super();
this.btnClose.on(Laya.Event.CLICK, this, ()=>this.close());
this.btnOK.on(Laya.Event.CLICK, this, async ()=>{
const selected = this.selected;
if(!selected == $ui.theme) return this.close();
$ui.theme = selected;
await this.close();
$ui.switchView(UI.pages.MAIN);
});
}
static load() {
return ["images/atlas/images/radio.atlas"];
}
init() {
this.selected = localStorage.getItem('theme');
}
get selected() {
switch(this.radioTheme.selectedIndex) {
case 0: return 'cyber';
case 1: return 'dark';
case 2: return 'light';
default: return 'default';
}
}
set selected(v) {
let index;
switch(v) {
case 'cyber': index = 0; break;
case 'dark': index = 1; break;
case 'light': index = 2; break;
default: index = -1; break;
}
this.radioTheme.selectedIndex = index;
}
}

1088
src/ui/themes/views.js Normal file

File diff suppressed because it is too large Load Diff

360
src/ui/uiManager.js Normal file
View File

@@ -0,0 +1,360 @@
import Views from './themes/views.js';
export default class UIManager {
constructor(stage) {
UIManager.#views = Views;
if(!stage) {
stage = Laya.stage;
}
this.#stage = stage;
stage.addChild(this.#viewLayer);
this.#viewLayer.zOrder = 1;
stage.addChild(this.#dialogLayer);
this.#dialogLayer.zOrder = 2;
stage.addChild(this.#popupLayer);
this.#popupLayer.zOrder = 3;
this.#viewLayer.top =
this.#viewLayer.bottom =
this.#viewLayer.left =
this.#viewLayer.right =
this.#dialogLayer.top =
this.#dialogLayer.bottom =
this.#dialogLayer.left =
this.#dialogLayer.right =
this.#popupLayer.top =
this.#popupLayer.bottom =
this.#popupLayer.left =
this.#popupLayer.right =
this.#dialogMask.top =
this.#dialogMask.bottom =
this.#dialogMask.left =
this.#dialogMask.right = 0;
this.#dialogMask.graphics.drawRect(0, 0, 5000, 5000, '#000000');
this.#dialogMask.alpha = 0.4;
this.#dialogMask.on(Laya.Event.CLICK, this, ()=>{
this.#dialogStack[this.#dialogStack.length - 1]?.close?.();
})
}
static #instance = {};
static #views;
#stage;
#loading;
#currentView;
#viewLayer = new Laya.Panel();
#dialogLayer = new Laya.Panel();
#popupLayer = new Laya.Panel();
#dialogMask = new Laya.Sprite();
#viewMap = new Map();
#class = new Map();
#dialogStack = [];
static get inst() {
return this.getInstance();
}
static getInstance(name="default") {
return this.#instance[name] || (this.#instance[name] = new UIManager());
}
static get pages() {
return this.#views.pages;
}
static get popups() {
return this.#views.popups;
}
static theme(theme, prop) {
return this.#views.themes[theme][prop];
}
async setLoading(loading) {
const className = this.#pages[loading];
const view = await this.getView(className, null, null, loading);
view.top = view.bottom = view.left = view.right = 0;
view.zOrder = 4;
this.#loading = view;
}
async switchView(viewName, args, actions) {
const className = this.#pages[viewName];
// get view instance
const view = await this.getView(className, args, actions?.load, viewName, 'pages');
view.top = view.bottom = view.left = view.right = 0;
// close current view
this.clearAllDialog();
await this.#currentView?.__close?.(view);
await this.#currentView?.close?.(view);
this.#viewLayer.removeChildren();
// open new view
await view.init?.(args);
this.#currentView = view;
this.#viewLayer.addChild(view);
view.__close = actions?.close;
await actions?.open?.(view);
await view.show?.();
}
async getView(className, args, preload, viewName, type) {
// check if view is already loaded
let view = await this.#viewMap.get(className);
let timeout;
if(this.#loading) {
timeout = setTimeout(
()=>this.#stage.addChild(this.#loading),
3000
);
}
const onProgress = this.#loading?.onProgress;
if(!view) {
// load view
const ViewClass = await this.loadView(className);
const resourceList = await ViewClass.load?.(args);
const scanedResourceList = this.#loading? this.scanResource(ViewClass.uiView): [];
if(preload) {
preload = [].concat(preload).concat(scanedResourceList);
} else {
preload = scanedResourceList;
}
await this.loadRes(resourceList, preload, onProgress);
// create view
view = new ViewClass();
// add view to map
this.#viewMap.set(className, view);
} else {
// load resource
const resourceList = await view.constructor.load?.(args);
await this.loadRes(resourceList, preload, onProgress);
}
if(timeout) clearTimeout(timeout);
this.#loading?.removeSelf();
this.#config(view, viewName, type);
// return view
return view;
}
async loadView(className) {
// load view
if(this.#class.has(className)) return this.#class.get(className);
const c = (await import(`./themes/${className}.js`)).default;
this.#class.set(className, c);
return c;
}
async loadRes(resourceList, preload, onProgress) {
const cnt = (resourceList?.length || 0)
+(preload?.length || 0);
if(resourceList && resourceList.length) {
const s = resourceList.length / cnt;
await Laya.promises.loader.load(resourceList, Laya.Handler.create(null, prg=>onProgress?.(prg*s)));
}
if(preload && preload.length) {
const s = 1 - preload.length / cnt;
const l = preload.length / cnt;
await Laya.promises.loader.load(preload, Laya.Handler.create(null, prg=>onProgress?.(prg*l+s)));
}
}
#showDialogStack() {
if(this.#dialogStack.length == 0) {
this.#dialogLayer.visible = false;
return;
}
this.#dialogLayer.visible = true;
this.#dialogStack.forEach((dialog, i)=>{
this.#dialogLayer.addChild(dialog);
dialog.zOrder = i;
})
this.#dialogLayer.addChild(this.#dialogMask);
const l = this.#dialogStack.length;
this.#dialogMask.zOrder = l -1;
this.#dialogStack[l -1].zOrder = l;
}
async showDialog(dialogName, args, actions) {
const className = this.#pages[dialogName];
const dialog = await this.getView(className, args, actions?.load, dialogName, 'pages');
const index = this.#dialogStack.indexOf(dialog);
if(index != -1) {
this.#dialogStack.splice(index, 1);
}
this.#dialogStack.push(dialog);
dialog.init?.(args);
dialog.centerX = dialog.centerY = 0;
this.#showDialogStack();
const open = actions?.open || (async () => {
dialog.scaleX = 0;
dialog.scaleY = 0;
await Laya.promises.Tween.to(dialog, { scaleX: 1, scaleY: 1 }, 300, Laya.Ease.backOut);
});
await open(dialog);
dialog.mouseThrough = true;
dialog.mouseEnabled = true;
dialog.close = async ()=>{
if(actions?.close) {
await actions.close();
} else {
await Laya.promises.Tween.to(dialog, { scaleX: 0, scaleY: 0 }, 300, Laya.Ease.strongIn);
}
const index = this.#dialogStack.indexOf(dialog);
if(index != -1) {
this.#dialogStack.splice(index, 1);
}
this.#showDialogStack();
}
this.#dialogLayer.addChild(dialog);
}
async popup(type, args) {
const className = this.#popups[type];
const popup = await this.getView(className, args, null, type, 'popups');
this.#popupLayer.addChild(popup);
await popup.popup(args, this.#popupLayer);
this.#popupLayer.removeChild(popup);
}
clearAllDialog() {
this.#dialogStack = [];
this.#showDialogStack();
}
#config(view, key, type) {
const config = this.#configs?.[type]?.[key];
if(!config) return;
if(view.config && view.config(config)) return;
const applyConfig = (target, config) => {
if(!target) return;
if(typeof config == 'string') {
config = this.#configs?.class?.[config];
}
$_.deepMapSet(target, config);
};
if(config.names)
for(const name in config.names)
this.#deepGetChildsByName(view, name)
.forEach(child => applyConfig(child, config.names[name]));
if(config.vars)
for(const key in config.vars)
applyConfig(view[key], config.vars[key]);
}
#deepGetChildsByName(parent, name) {
const list = [];
if(!parent || !parent._childs) return list;
for(const child of parent._childs) {
if(child.name == name) list.push(child);
if(child._childs) list.push(...this.#deepGetChildsByName(child, name));
}
return list;
}
#cutPath(path) {
path = ''+path;
let index = path.length;
do {
index --;
if(path[index] == '.') {
break;
}
} while (index>0)
return [
path.substring(0, index),
path.substring(index, path.length)
];
}
#subSkin(skin, type) {
if(!skin || !skin.replace(/\s/g, '')) return [];
switch (type) {
case 'ProgressBar':
return [ skin, ...this.#progressBarSkin(skin) ];
case 'ScrollBar':
return [ skin, ...this.#scrollBarSkin(skin) ];
default:
return [skin]
}
}
#progressBarSkin(skin) {
if(!skin.replace(/\s/g, '')) return [];
let p = this.#cutPath(skin);
return [`${p[0]}$bar${p[1]}`];
}
#scrollBarSkin(skin) {
if(!skin.replace(/\s/g, '')) return [];
let p = this.#cutPath(skin);
return [
`${p[0]}$bar${p[1]}`,
`${p[0]}$up${p[1]}`,
`${p[0]}$down${p[1]}`
];
}
scanResource(uiView) {
if(!uiView) return [];
const resourceList = [];
resourceList.push(...this.#subSkin(uiView.props?.skin, uiView.type));
resourceList.push(...this.#subSkin(uiView.props?.hScrollBarSkin, 'ScrollBar'));
resourceList.push(...this.#subSkin(uiView.props?.vScrollBarSkin, 'ScrollBar'));
uiView.child?.forEach(child => {
resourceList.push(...this.scanResource(child));
});
return resourceList;
}
get currentView() {
return this.#currentView;
}
get currentDialog() {
return this.#dialogStack[this.#dialogStack.length -1];
}
get theme() {
return localStorage.getItem('theme');
}
set theme(value) {
localStorage.setItem('theme', value);
this.#stage.bgColor = this.#configs.bgColor;
document?.querySelector?.('meta[name="theme-color"]')?.setAttribute?.('content', this.#configs.bgColor);
}
get #pages() {
return UIManager.theme(this.theme, 'pages');
}
get #popups() {
return UIManager.theme(this.theme, 'popups');
}
get #configs() {
return UIManager.theme(this.theme, 'configs');
}
get common() {
return this.#configs.common;
}
gradeColor(grade) {
return this.common.grade[grade];
}
gradeFilter(grade) {
return this.common.filter[grade];
}
}