Commit f1c44819 authored by wildfirecode's avatar wildfirecode

1

parent 6a723ce7
{"ver":"1.0.1","uuid":"5eeb7cd2-c151-4778-b888-86a7799e8936","subMetas":{},"isGroup":true}
{
"name": "main",
"root": {
"components": [
{
"script": "components/base/Transform"
},
{
"script": "components/other/CameraController",
"properties": {
"viewportAnchor": {
"x": 0.5,
"y": 0.5
}
}
}
],
"children": [
{
"name": "MainStage",
"uuid": "20181212032053",
"components": [
{
"script": "components/base/Transform",
"properties": {}
},
],
"children": []
}
]
},
"entity-cache": [],
"resource-groups": {
"preload": []
}
}
\ No newline at end of file
{"ver":"1.0.1","uuid":"1f50815f-bf2f-4cf6-8432-f56f3aa834ef","subMetas":{},"type":"scene"}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>scilla-kuwo</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="full-screen" content="true"/>
<meta name="screen-orientation" content="portrait"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="360-fullscreen" content="true"/>
<style>
html, body {
padding: 0;
margin: 0;
border: 0;
height: 100%;
background-color: #282C34;
}
</style>
<script src='http://127.0.0.1:35729/livereload.js?ext=Chrome&extver=2.1.0'></script>
<!--<script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script>-->
<script>
//var vConsole = new VConsole();
var cms_scheduler = {
get: function get() {
return {
$showModal: function () {
}
};
}
}
</script>
</head>
<body>
<div id="gameContainer" style="width: 100%;height: 100%;overflow: hidden;"></div>
<script src="debug/bundle.js"></script>
<script>
window['scilla-kuwo'].startup(document.getElementById('gameContainer'), {});
</script>
</body>
</html>
{
"name": "scilla-kuwo",
"fps": 60,
"designWidth": 750,
"designHeight": 1334,
"scaleMode": "showAll",
"modifyCanvasSize": true,
"webServiceUrl": "http://localhost:4001",
"resPath": "",
"scenes": [
"main"
]
}
{
"systemParams": "darwin-x64-64",
"modulesFolders": [
"node_modules"
],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [
"scilla-components@git+http://gitlab2.dui88.com/laoqifeng/scilla-components.git",
"scilla-core@git+http://gitlab2.dui88.com/laoqifeng/scilla-core.git",
"tslib@^1.9.3"
],
"lockfileEntries": {
"scilla-components@git+http://gitlab2.dui88.com/laoqifeng/scilla-components.git": "git+http://gitlab2.dui88.com/laoqifeng/scilla-components.git#810156761cf22a7933b5b6066f3633a7c2bdaa9d",
"scilla-core@git+http://gitlab2.dui88.com/laoqifeng/scilla-core.git": "git+http://gitlab2.dui88.com/laoqifeng/scilla-core.git#cd8752837a5d56bd4336d9247cc5844b673e6a5f",
"tslib@^1.9.3": "http://npm.dui88.com:80/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
},
"files": [],
"artifacts": {}
}
\ No newline at end of file
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
/.rpt2_cache/
{
"name": "scilla-components",
"version": "1.0.0",
"main": "./dist/bundle.js",
"types": "./types/index.d.ts",
"license": "MIT",
"scripts": {
"build": "rollup -c"
},
"dependencies": {
"tslib": "^1.9.3"
},
"devDependencies": {
"rollup": "^0.66.6",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-typescript2": "^0.18.0",
"rollup-plugin-uglify": "^6.0.0",
"tslib": "^1.9.3",
"typescript": "^3.1.6"
}
}
/**
* Created by rockyl on 2018/11/16.
*/
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const typescript = require('rollup-plugin-typescript2');
const {uglify} = require('rollup-plugin-uglify');
export default {
input: 'src/index.ts',
output: {
file: 'dist/bundle.js',
format: 'umd',
name: 'scilla',
//sourcemap: true,
},
plugins: [
resolve({
browser: true,
}),
typescript({
typescript: require('typescript'),
tslib: require('tslib'),
useTsconfigDeclarationDir: true,
}),
commonjs(),
uglify({}),
]
};
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
/**
* Created by rockyl on 2019-01-04.
*
* 弹动缩放
*/
import {ScillaComponent, createTween, Tween, Vector2D, createVector2D} from "scilla";
const originScale: Vector2D = createVector2D(1, 1);
export default class BounceZoom extends ScillaComponent {
targetScale: Vector2D = createVector2D(1.5, 1.5);
duration:number = 100;
private _tween: Tween;
onAwake() {
super.onAwake();
this._tween = createTween(this.transform, false,
{clazz: Vector2D, fields: ['x', 'y'], autoPlay: false}
)
.to({scale: this.targetScale.clone()}, this.duration * 0.5)
.to({scale: originScale.clone()}, this.duration * 0.5)
}
play(){
this._tween.play(true);
}
}
/**
* Created by rockyl on 2019-01-04.
*
* 渐变组件
*/
import {math, ScillaComponent} from "scilla";
export default class Fade extends ScillaComponent {
fromAlpha: number = 0;
toAlpha: number = 1;
duration: number = 1000;
private _startTime: number;
private _playing: boolean;
onUpdate(t) {
super.onUpdate(t);
if(this._playing){
if(!this._startTime){
this._startTime = t;
}
let ratio = (t - this._startTime) / this.duration;
this.transform.alpha = math.lerp(this.fromAlpha, this.toAlpha, ratio);
if(ratio >= 1){
this.stop();
}
}
}
play(){
this._startTime = 0;
this._playing = true;
}
stop(){
this._playing = false;
}
}
/**
* Created by rockyl on 2018/11/5.
*
* 自转组件
*/
import {createTween, ScillaComponent, ScillaEvent, Tween} from "scilla";
export default class Rotation extends ScillaComponent {
duration: number = 10000;
autoPlay: boolean = false;
loop: number = -1;
onComplete: ScillaEvent = new ScillaEvent();
private _tween: Tween;
onCreate() {
super.onCreate();
}
onAwake() {
super.onAwake();
if(!this._tween){
this._tween = createTween(this.transform, false, {autoPlay: this.autoPlay, loop: this.loop, initFields: ['_rotation']})
.to({rotation: 360}, this.duration)
.call(()=>{
this.onComplete.invoke();
});
}
}
play(){
this._tween.play(true);
}
stop(){
this._tween.stop();
}
}
/**
* Created by rockyl on 2018/11/5.
*/
import {ScillaComponent} from "scilla";
export default class RoundLoop extends ScillaComponent {
transform;
duration: number = 10000;
onUpdate(t) {
super.onUpdate(t);
const {position} = this.transform;
position.setXY(
Math.cos(t * 0.001) * 100,
Math.sin(t * 0.001) * 100,
)
}
}
/**
* Created by rockyl on 2018/11/5.
*
* 摇摆组件
*/
import {ScillaComponent} from "scilla";
export default class Swing extends ScillaComponent {
duration: number = 10000;
onUpdate(t) {
super.onUpdate(t);
this.transform.rotation = Math.sin(t / 100) * 5;
}
}
/**
* Created by rockyl on 2018-11-27.
*
* 触摸缩放交互效果组件
*/
import {createTween, createVector2D, ease, Ease, Tween, Vector2D,} from "scilla";
import {InteractComponent} from "../base";
export default class TouchZoom extends InteractComponent {
scaleOffset: Vector2D = createVector2D(0.1, 0.1);
duration: number = 200;
easeName: Ease = Ease.backOut;
private _zoomIn: Tween;
private _zoomOut: Tween;
private _touchBegin: boolean;
onAwake() {
super.onAwake();
if (!this._zoomIn) {
const {scaleOffset, duration, transform} = this;
const easeFunc = ease[this.easeName];
const scaleFrom = transform.scale.clone();
const scaleTo = transform.scale.clone().add(scaleOffset);
this._zoomIn = createTween(transform, false, {autoPlay: false, clazz: Vector2D, fields: ['x', 'y']})
.to({scale: scaleTo}, duration, easeFunc);
this._zoomOut = createTween(transform, false, {autoPlay: false, clazz: Vector2D, fields: ['x', 'y']})
.to({scale: scaleFrom}, duration, easeFunc);
}
}
onTouchBegin(e) {
super.onTouchOver(e);
if (this.interactable) {
this._touchBegin = true;
this._zoomIn.play(true);
}
}
onGlobalTouchEnd(e) {
super.onGlobalTouchEnd(e);
if (this._touchBegin) {
this._touchBegin = false;
this._zoomOut.play(true);
}
return false;
}
}
/**
* Created by rockyl on 2018/11/5.
*
* 波动组件
*/
import {ScillaComponent, raw, ScillaEvent} from "scilla";
const PI2 = Math.PI * 2;
export enum WaveMethod {
/**
* 公转
*/
round = 'round',
/**
* 自转
*/
rotate = 'rotate',
/**
* 缩放
*/
zoom = 'zoom',
/**
* 透明渐变
*/
fade = 'fade',
/**
* 横向波动
*/
cosWave = 'cosWave',
/**
* 纵向波动
*/
sinWave = 'sinWave',
/**
* 抖动
*/
shake = 'shake',
/**
* 呼吸
*/
breath = 'breath',
}
export default class Wave extends ScillaComponent {
duration: number = 1000;
waveMethod: WaveMethod;
waveParams: raw;
loop: number = -1;
autoPlay: boolean = true;
onComplete: ScillaEvent = new ScillaEvent();
onLoopComplete: ScillaEvent = new ScillaEvent();
private _playing;
private _waveMethod;
private _startTime;
private _oldProps: any = {};
private _loopCounting;
onAwake() {
super.onAwake();
this._waveMethod = waveLibs[this.waveMethod];
this._startTime = 0;
const {transform: {position}} = this;
this._oldProps.x = position.x;
this._oldProps.y = position.y;
if (this.autoPlay) {
this.play();
}
}
onUpdate(t) {
super.onUpdate(t);
if (this._playing) {
if (!this._startTime) {
this._startTime = t;
}
const {duration, waveParams, _waveMethod, transform, transform: {position, scale}, _oldProps} = this;
let pass = (t - this._startTime) % duration;
let r = pass / duration * PI2;
let loopCounting = Math.floor((t - this._startTime) / duration);
if(loopCounting != this._loopCounting){
this._loopCounting = loopCounting;
if(this.onLoopEnd()){
r = PI2;
}
}
let params = waveParams || [];
let props = _waveMethod(...params, r);
if (props.hasOwnProperty('x')) {
position.x = (props.x || 0) + _oldProps.x;
}
if (props.hasOwnProperty('y')) {
position.y = (props.y || 0) + _oldProps.y;
}
if (props.hasOwnProperty('sx')) {
scale.x = props.sx;
}
if (props.hasOwnProperty('sy')) {
scale.y = props.sy;
}
if (props.hasOwnProperty('r')) {
transform.rotation = props.r;
}
}
}
private onLoopEnd(){
if (this.loop < 0) {
this.onLoopComplete.invoke();
} else if (this._loopCounting < this.loop) {
this.onLoopComplete.invoke();
} else {
this._playing = false;
this.onComplete.invoke();
return true;
}
}
play() {
this._loopCounting = 0;
this._playing = true;
this._startTime = 0;
}
stop() {
this._playing = false;
}
}
const {cos, sin, PI} = Math;
const waveLibs = {
round: function (h: number, t: number): any {
return {x: cos(t) * h, y: sin(t) * h};
},
cosWave: function (h: number, t: number): any {
return {x: cos(t) * h, y: 0};
},
sinWave: function (h: number, t: number): any {
h = h || 1;
return {x: 0, y: sin(t) * h};
},
rotate: function (t: number): any {
return {r: 360 * t / PI / 2};
},
shake: function (angle: number, count: number, t: number): any {
return {r: sin(t * count) * angle};
},
breath: function (scale: number = 0.1, t: number): any {
return {sx: sin(t) * scale + 1, sy: -sin(t + PI / 4) * scale + 1};
},
zoom: function (scale: number = 0.1, t: number): any {
return {sx: sin(t) * scale + 1, sy: sin(t) * scale + 1};
},
fade: function (base = 1, t: number): any {
return {alpha: (sin(t) + 1) * 0.5 + base};
},
};
/**
* Created by rockyl on 2018/11/5.
*/
import {ScillaComponent} from "scilla";
export default class ZoomLoop extends ScillaComponent{
onUpdate(t) {
super.onUpdate(t);
this.transform.scale.x = this.transform.scale.y = Math.abs(Math.sin(t * 0.001)) * 0.15 + 1;
}
}
/**
* Created by rockyl on 2019-01-10.
*/
export {default as BounceZoom} from './BounceZoom'
export {default as Fade} from './Fade'
export {default as Rotation} from './Rotation'
export {default as RoundLoop} from './RoundLoop'
export {default as Swing} from './Swing'
export {default as TouchZoom} from './TouchZoom'
export {default as Wave} from './Wave'
export {default as ZoomLoop} from './ZoomLoop'
/**
* Created by rockyl on 2018/11/7.
*/
import {Matrix, ScillaComponent, decorators} from "scilla";
import Renderer from "../renderer/Renderer";
const {dirtyFieldTrigger} = decorators;
/**
* 可交互组件
*/
export default class InteractComponent extends ScillaComponent {
/**
* 是否可交互
*/
@dirtyFieldTrigger
interactable = true;
/**
* 触摸中断
*/
touchInterrupt: boolean = false;
protected invertMatrix = Matrix.create();
protected localPos: any = {};
protected isOut = true;
private _touchBeginFlag: boolean;
constructor() {
super();
}
_dealGlobalTouchBegin(e) {
let interrupt = super._dealGlobalTouchBegin(e);
const hitOn = this.hitTest(e);
if (hitOn) {
this._touchBeginFlag = true;
this.onTouchBegin(e);
this._dealTouchOver(e);
}
return hitOn && interrupt;
}
_dealGlobalTouchMove(e) {
let interrupt = super._dealGlobalTouchMove(e);
const hitOn = this.hitTest(e);
if (hitOn) {
this._dealTouchOver(e);
this.onTouchMove(e);
} else {
this._dealTouchOut(e);
}
return hitOn && interrupt;
}
_dealGlobalTouchEnd(e) {
let interrupt = super._dealGlobalTouchEnd(e);
const hitOn = this.hitTest(e);
if (hitOn) {
this.onTouchEnd(e);
if(this._touchBeginFlag){
this.onTouchTap(e);
this._touchBeginFlag = false;
}
}
this.isOut = true;
return hitOn && interrupt;
}
_dealTouchOver(e) {
if (this.isOut) {
this.isOut = false;
this.onTouchOver(e);
}
}
_dealTouchOut(e) {
if (!this.isOut) {
this.isOut = true;
this.onTouchOut(e);
}
}
onTouchBegin(e) {
//console.log('onTouchBegin', e);
}
onTouchMove(e) {
//console.log('onTouchMove', e);
}
onTouchOver(e) {
//console.log('onTouchOver', e);
}
onTouchOut(e) {
//console.log('onTouchOut', e);
}
onTouchEnd(e) {
//console.log('onTouchEnd', e);
}
onTouchTap(e) {
//console.log('onTouchTap', e);
}
/**
* 碰撞检测
* @param e
*/
hitTest(e) {
const matrix = this.transform.getMatrix();
const invertMatrix = this.invertMatrix;
invertMatrix.copyFrom(matrix);
invertMatrix.invert();
invertMatrix.transformPoint(e.x, e.y, this.localPos);
let result = false;
const renderers = this.entity.getComponents(Renderer);
for (let renderer of renderers) {
if (renderer.hitTest(this.localPos.x, this.localPos.y)) {
if (renderer.isUsedToMask) {
continue
} else {
result = true;
break
}
} else if (renderer.isUsedToMask) {
return false
}
}
return result;
}
}
/**
* Created by rockyl on 2018-12-13.
*
* 触摸中断组件
*/
import InteractComponent from "./InteractComponent";
export default class TouchInterrupt extends InteractComponent {
touchInterrupt: boolean = true;
}
/**
* Created by rockyl on 2018/11/5.
*/
import {ScillaComponent, Vector2D, Matrix, decorators} from "scilla";
import Renderer from "../renderer/Renderer";
const {dirtyFieldDetector, dirtyFieldTrigger} = decorators;
/**
* 矩阵处理顺序
* SCALE_ROTATE: 先缩放后旋转
* ROTATE_SCALE: 先旋转后缩放
*/
export enum MATRIX_ORDER {
SCALE_ROTATE,
ROTATE_SCALE,
}
/**
* 矩阵转换组件
* 缩放、旋转、位移
*/
export default class Transform extends ScillaComponent {
onVector2DModify = (value, key, oldValue) => {
this.makeDirty(value, key, oldValue);
};
/**
* 坐标
*/
@dirtyFieldTrigger
position: Vector2D = new Vector2D(0);
/**
* 节点透明度
*/
@dirtyFieldTrigger
alpha: number = 1;
/**
* 节点渲染透明度
*/
private _renderAlpha: number;
get renderAlpha(): number{
return this._renderAlpha;
}
/**
* 尺寸
* 对于不同的子类渲染都有不同的效果
*/
private _width: number = NaN;
private _height: number = NaN;
/**
* 缩放
*/
@dirtyFieldTrigger
scale: Vector2D = new Vector2D(1, 1);
/**
* 轴距
*/
@dirtyFieldTrigger
pivot: Vector2D = new Vector2D(0.5, 0.5);
@dirtyFieldDetector
rotation = 0;
private order: MATRIX_ORDER = MATRIX_ORDER.SCALE_ROTATE;
protected _localMatrix: Matrix = Matrix.create();
protected _globalMatrix: Matrix = Matrix.create();
protected _globalPivotMatrix: Matrix = Matrix.create();
protected dirty: boolean;
get width(): number {
const renderer = this.entity.getComponent(Renderer);
return renderer ? renderer.bounds.width : (isNaN(this._width) ? 0 : this._width);
}
get explicitWidth(): number {
return this._width;
}
set width(value: number) {
if (this._width != value) {
this._width = value;
this.makeDirty(value, 'width');
}
}
get height(): number {
const renderer = this.entity.getComponent(Renderer);
return renderer ? renderer.bounds.height : (isNaN(this._height) ? 0 : this._height);
}
get explicitHeight(): number {
return this._height;
}
set height(value: number) {
if (this._height != value) {
this._height = value;
this.makeDirty(value, 'height');
}
}
makeDirty(value, key, oldValue?) {
this.dirty = true;
switch (key) {
case 'width':
case 'height':
const renderers = this.entity.getComponents(Renderer);
for (let renderer of renderers) {
renderer.makeDirty();
}
break;
}
}
/**
* @inheritDoc
*/
onModify(value, key, oldValue) {
super.onModify(value, key, oldValue);
this.makeDirty(value, key, oldValue);
switch (key) {
case 'position':
case 'scale':
//case 'size':
value.onChange = this.onVector2DModify;
break;
}
}
/**
* 更新本地矩阵
*/
protected updateLocalMatrix() {
const {
position: {x, y},
scale: {x: sx, y: sy}, rotation,
} = this;
const matrix = this._localMatrix;
matrix.identity();
if (this.order = MATRIX_ORDER.ROTATE_SCALE) {
matrix.scale(sx, sy);
matrix.rotate(rotation * Math.PI / 180);
} else {
matrix.rotate(rotation * Math.PI / 180);
matrix.scale(sx, sy);
}
matrix.translate(
x,
y,
);
}
/**
* 更新全局矩阵
*/
protected updateGlobalMatrix() {
const {
entity, _globalMatrix, _localMatrix, _globalPivotMatrix,
pivot: {x: px, y: py},
width, height,
} = this;
_globalMatrix.copyFrom(_localMatrix);
if (entity.parent) {
const parentTransform: Transform = entity.parent.getComponent(Transform);
if (parentTransform) {
this._renderAlpha = parentTransform._renderAlpha * this.alpha;
_globalMatrix.concat(parentTransform.getMatrix());
}
}else{
this._renderAlpha = this.alpha;
}
_globalPivotMatrix.copyFrom(_globalMatrix);
_globalPivotMatrix.translate(
-(px - 0.5) * width,
-(py - 0.5) * height,
);
}
/**
* 获取矩阵
*/
getMatrix(withPivot = false): Matrix {
return withPivot ? this._globalPivotMatrix : this._globalMatrix;
}
onUpdate(t) {
if (this.dirty) {
this.updateLocalMatrix();
this.dirty = false;
}
this.updateGlobalMatrix();
super.onUpdate(t);
}
}
/**
* Created by rockyl on 2019-01-10.
*/
export {default as InteractComponent} from './InteractComponent'
export {default as TouchInterrupt} from './TouchInterrupt'
export {default as Transform} from './Transform'
/**
* Created by rockyl on 2019-01-24.
*/
export * from './animation';
export * from './base';
export * from './other';
export * from './renderer';
export * from './ui';
/**
* Created by rockyl on 2018/11/15.
*
*/
import {Entity, getStageSize, ScillaComponent, createVector2D, Vector2D, math} from "scilla";
import Transform from "../base/Transform";
/**
* 相机控制组件
*/
export default class CameraController extends ScillaComponent {
target: Entity;
viewportAnchor: Vector2D = createVector2D();
targetPosition: Vector2D;
maxScale = 1.2;
private followPosition: Vector2D;
private stageSize;
onCreate() {
super.onCreate();
}
onAwake() {
super.onAwake();
const {target, viewportAnchor} = this;
this.stageSize = getStageSize();
if (target) {
this.targetPosition = target.getComponent(Transform).position;
}
this.followPosition = createVector2D();
if (viewportAnchor) {
const {width, height} = this.stageSize;
const {x, y} = this.viewportAnchor;
this.transform.position.setXY(width * x, height * y);
}
}
onUpdate(t) {
super.onUpdate(t);
if (!this.targetPosition) {
return;
}
const {transform: {scale, position}, stageSize: {width, height}, targetPosition: {x, y, length}, maxScale} = this;
const newScale = maxScale - length * maxScale / 2048;
scale.setXY(newScale, newScale);
this.followPosition.setXY(width / 2, height / 2).subtract(this.targetPosition);
position.copyFrom(math.lerpObj(position, this.followPosition, 0.1, Vector2D, ['x', 'y']));
}
onSleep() {
super.onSleep();
}
onDestroy() {
super.onDestroy();
}
}
/**
* Created by rockyl on 2018-12-17.
*
* 内容组件尺寸自适应组件
*/
import {ScillaComponent, Size} from "scilla";
import Transform from "../base/Transform";
export default class ContentSizeFitter extends ScillaComponent {
private _measureSize: Size = new Size();
afterUpdate() {
super.afterUpdate();
const measureSize = this._measureSize;
measureSize.set(0, 0);
for(let child of this.entity.children){
const transform = child.getComponent(Transform);
if(transform){
const {width, height, pivot} = transform;
measureSize.width += width;
measureSize.height += height;
}
}
this.transform.width = measureSize.width;
this.transform.height = measureSize.height;
}
}
/**
* Created by rockyl on 2018-12-05.
*
*/
import {ScillaComponent} from "scilla";
import Renderer from "../renderer/Renderer";
import Transform from "../base/Transform";
/**
* 相对布局组件
*/
export default class RelativeLayout extends ScillaComponent {
left: number = NaN;
right: number = NaN;
top: number = NaN;
bottom: number = NaN;
horizontalCenter: number = NaN;
verticalCenter: number = NaN;
once: boolean = true;
onCreate() {
super.onCreate();
}
onAwake() {
super.onAwake();
this.adjust();
}
onUpdate(t) {
super.onUpdate(t);
if (!this.once) {
this.adjust();
}
}
onSleep() {
super.onSleep();
}
onDestroy() {
super.onDestroy();
}
adjust = () => {
const {
entity, entity: {parent}, transform, transform: {position, pivot: {x: ax, y: ay},},
left, right, top, bottom, horizontalCenter, verticalCenter
} = this;
const hasLeft = !isNaN(left);
const hasRight = !isNaN(right);
const hasTop = !isNaN(top);
const hasBottom = !isNaN(bottom);
const hasHorizontalCenter = !isNaN(horizontalCenter);
const hasVerticalCenter = !isNaN(verticalCenter);
const parentRenderers = parent.getComponents(Renderer);
for (let parentRenderer of parentRenderers) {
parentRenderer.measureBounds();
}
const parentTransform:Transform = parent.getComponent(Transform);
let pWidth, pHeight;
if(parentRenderers.length > 0){
const parentBounds = parentRenderers[0].bounds;
pWidth = parentBounds.width;
pHeight = parentBounds.height;
}else{
pWidth = parentTransform.explicitWidth;
pHeight = parentTransform.explicitHeight;
}
const {x: pax, y: pay} = parentTransform.pivot;
const renderers = entity.getComponents(Renderer);
for (let renderer of renderers) {
renderer.measureBounds();
}
let {width, height, } = transform;
let {x, y} = position;
let widthModified = false, heightModified = false;
//adjust
{
if (hasHorizontalCenter) {
x = (pWidth - width) / 2 - pWidth * pax + width * ax;
} else if (hasLeft) {
if (hasRight) {
widthModified = true;
width = pWidth - right - left;
x = (left - right) / 2 - (0.5 - ax) * width;
} else {
x = left - pWidth * pax + width * ax;
}
} else if (hasRight) {
x = -right + pWidth * (1 - pax) - width * (1 - ax);
}
if (hasVerticalCenter) {
y = (pHeight - height) / 2 - pHeight * pay + height * ay;
} else if (hasTop) {
if (hasBottom) {
heightModified = true;
height = pHeight - bottom - top;
y = (top - bottom) / 2 - (0.5 - ay) * height;
} else {
y = top - pHeight * pay + height * ay;
}
} else if (hasBottom) {
y = -bottom + pHeight * (1 - pay) - height * (1 - ay);
}
}
position.x = x;
position.y = y;
if(widthModified){
transform.width = width;
}
if(heightModified){
transform.height = height;
}
if(widthModified || heightModified){
for (let renderer of renderers) {
renderer.measureBounds();
}
}
}
}
/**
* Created by rockyl on 2019-01-10.
*/
export {default as CameraController} from './CameraController'
export {default as ContentSizeFitter} from './ContentSizeFitter'
export {default as RelativeLayout} from './RelativeLayout'
/**
* Created by rockyl on 2018/11/6.
*/
import GraphicRenderer from "./GraphicRenderer";
import {decorators} from "scilla";
const {dirtyFieldDetector} = decorators;
/**
* 圆形渲染组件
*/
export default class CircleRenderer extends GraphicRenderer {
/**
* 半径
*/
@dirtyFieldDetector
radius = 50;
/**
* 开始角度
*/
@dirtyFieldDetector
startAngle: number = 0;
/**
* 结束角度
*/
@dirtyFieldDetector
endAngle: number = 360;
/**
* 是否回归到圆心
*/
@dirtyFieldDetector
backToCenter: boolean = true;
protected getRenderSize(): any {
const {radius} = this;
return {width: radius * 2, height: radius * 2};
}
/**
* @inheritDoc
*/
protected draw() {
const {context, bounds: {width, height}, startAngle, endAngle, backToCenter, _margin, _useCacheMode} = this;
let offset = _useCacheMode ? _margin : 0;
const radius = Math.min(width, height) / 2;
const pos = offset + radius;
if(startAngle == 0 && endAngle == 360){
context.arc(pos, pos, radius, 0, 2 * Math.PI);
}else{
if(backToCenter){
context.moveTo(pos, pos);
}
context.arc(pos, pos, radius, startAngle * Math.PI / 180, endAngle * Math.PI / 180);
if(backToCenter){
context.lineTo(pos, pos);
}
}
super.draw();
}
}
/**
* Created by rockyl on 2018-11-30.
*
* 帧动画组件
*
* todo 倒置播放
*/
import Renderer from "./Renderer";
import {FrameAnimation, ScillaEvent} from "scilla";
/**
* 帧动画渲染组件
*/
export default class FrameAnimationRenderer extends Renderer {
/**
* 帧动画资源
*/
public frameAnimation: FrameAnimation;
/**
* 是否自动播放
*/
public autoPlay: boolean = false;
/**
* 帧率
* 不设置就读取动画文件的帧率
*/
public fps: number = NaN;
public onComplete: ScillaEvent = new ScillaEvent();
public onLoopComplete: ScillaEvent = new ScillaEvent();
private _playing;
private _startTime;
private _startFrame;
private _endFrame;
private _currentFrameIndex;
private _startFlag;
private _loop;
private _loopCounting;
private _flag;
/**
* @inheritDoc
*/
onAwake() {
super.onAwake();
if(this.autoPlay){
this.play(0, -1);
}
}
/**
* @inheritDoc
*/
onUpdate(t) {
if (this._playing) {
const {frameAnimation, _startFrame, _endFrame, fps} = this;
if (this._startFlag) {
this._startFlag = false;
this._startTime = t;
this._loopCounting ++;
}
const mFPS = isNaN(fps) ? frameAnimation.fps : fps;
const passTime = t - this._startTime;
const passFrameCount = Math.floor(passTime / (1000 / mFPS));
const passFrameInRegion = passFrameCount % (_endFrame - _startFrame + 1);
this._currentFrameIndex = _startFrame + passFrameInRegion;
if(passFrameInRegion == 0 && passFrameCount > 0){
this._currentFrameIndex = _endFrame;
this.onLoopEnd();
}
}
super.onUpdate(t);
}
/**
* @inheritDoc
*/
onSleep() {
super.onSleep();
}
/**
* 当一遍播放结束时
*/
onLoopEnd(){
if (this._loop < 0) {
this._startFlag = true;
this.onLoopComplete.invoke();
} else if (this._loopCounting < this._loop) {
this._startFlag = true;
this.onLoopComplete.invoke();
} else {
this._playing = false;
this.onComplete.invoke();
}
}
/**
* 播放
* @param frame
* @param loop
* @param force
*/
play(frame: number | string = 0, loop: number = 0, force = true) {
this._loop = loop;
this._loopCounting = 0;
if (!this.frameAnimation) {
return;
}
let startFrame = 0, endFrame = this.frameAnimation.frameCount - 1;
if (typeof frame == 'string') {
const label = this.frameAnimation.getLabel(frame);
if (label) {
startFrame = label.frame - 1;
endFrame = label.end;
}
} else {
startFrame = frame;
}
this._startFrame = startFrame;
this._endFrame = endFrame;
this._currentFrameIndex = this._startFrame;
this._startFlag = true;
this._playing = true;
}
/**
* 停止
*/
stop() {
this._playing = false;
}
/**
* @inheritDoc
*/
protected draw() {
super.draw();
if (!this.frameAnimation) {
return;
}
const {context, frameAnimation, _currentFrameIndex, bounds} = this;
const {texture, data} = frameAnimation.getFrame(_currentFrameIndex);
if (texture) {
const {img, bounds: {x, y, width: textureWidth, height: textureHeight}} = texture;
bounds.setTo(data.x, data.y, textureWidth, textureHeight);
context.drawImage(img, x, y, textureWidth, textureHeight, data.x, data.y, textureWidth, textureHeight);
}
}
}
/**
* Created by rockyl on 2018/11/6.
*
* todo 如果isUsedToMask,就禁用缓存
*/
import Renderer from "./Renderer";
import {color} from 'scilla';
/**
* 图形渲染组件
*/
export default class GraphicRenderer extends Renderer {
fillColor: color = '#42bce4';
borderColor: color = '#0899d0';
borderWidth = 0;
//是否为mask
isUsedToMask = false;
//是否显示mask
maskVisible = false;
protected getUseCacheMode(){
return this._useCacheMode && !this.isUsedToMask;
}
/**
* 获取图形尺寸
*/
protected getRenderSize(): any {
return {width: 0, height: 0};
}
/**
* @inheritDoc
*/
protected beforeDraw() {
super.beforeDraw();
this.applyStyle();
this.context.beginPath();
}
/**
* @inheritDoc
*/
protected draw() {
super.draw();
if (this.isUsedToMask) {
this._context.clip();
this.maskVisible && this.fillAndStoke()
} else {
this.fillAndStoke()
}
}
/**
* 应用渲染样式
*/
protected applyStyle() {
const {context, fillColor, borderColor, borderWidth} = this;
context.fillStyle = fillColor;
if (borderWidth > 0) {
context.strokeStyle = borderColor;
context.lineWidth = borderWidth;
}
}
/**
* 绘制
*/
protected fillAndStoke() {
const {context, borderWidth} = this;
context.fill();
if (borderWidth > 0) {
context.stroke();
}
}
/**
* @inheritDoc
*/
protected drawClip() {
this.isUsedToMask && this.context.save();
}
/**
* @inheritDoc
*/
afterUpdate() {
this.isUsedToMask && this.context.restore();
}
measureBounds() {
if(this.entity.name == 'content'){
console.log();
}
if (!this.dirty) {
return;
}
this._margin = this.borderWidth;
const {bounds, transform: {explicitWidth: tWidth, explicitHeight: tHeight}} = this;
const {width: sWidth, height: sHeight} = this.getRenderSize();
bounds.width = isNaN(tWidth) ? sWidth : tWidth;
bounds.height = isNaN(tHeight) ? sHeight : tHeight;
super.measureBounds();
}
}
/**
* Created by rockyl on 2018/11/6.
*/
import GraphicRenderer from "./GraphicRenderer";
/**
* 线段渲染组件
*/
export default class LineRenderer extends GraphicRenderer {
x0: number = 0;
y0: number = 0;
x1: number = 0;
y1: number = 0;
/**
* @inheritDoc
*/
draw() {
super.draw();
const {context, x0, y0, x1, y1} = this;
context.moveTo(x0, y0);
context.lineTo(x1, y1);
}
/**
* @inheritDoc
*/
measureBounds() {
const {bounds} = this;
bounds.width = 0;
bounds.height = 0;
super.measureBounds();
}
}
/**
* Created by rockyl on 2018/11/6.
*/
import GraphicRenderer from "./GraphicRenderer";
import {decorators} from 'scilla'
const {dirtyFieldDetector} = decorators;
/**
* (圆角)矩形渲染器
*/
export default class RectRenderer extends GraphicRenderer {
@dirtyFieldDetector
width = 100;
@dirtyFieldDetector
height = 100;
@dirtyFieldDetector
cornerRadius = 0;
protected getRenderSize(): any {
const {width, height} = this;
return {width, height};
}
/**
* @inheritDoc
*/
protected draw() {
const {PI} = Math;
const {context, cornerRadius: r, bounds: {width, height}, _margin, _useCacheMode} = this;
let offset = _useCacheMode ? _margin : 0;
if (r) {
context.moveTo(offset + r, offset + 0);
context.lineTo(offset + width - r, offset + 0);
context.arc(offset + width - r, offset + r, r, PI * 3 / 2, PI * 2);
context.lineTo(offset + width, offset + height - r);
context.arc(offset + width - r, offset + height - r, r, 0, PI / 2);
context.lineTo(offset + r, offset + height);
context.arc(offset + r, offset + height - r, r, PI / 2, PI);
context.lineTo(offset + 0, offset + r);
context.arc(offset + r, offset + r, r, PI, PI * 3 / 2);
} else {
context.rect(offset, offset, width, height);
}
super.draw();
}
}
/**
* Created by rockyl on 2018/11/6.
*/
import {createCanvas, getContext, ScillaComponent, Bounds, Vector2D, math, decorators, EngineConfig} from "scilla";
const {dirtyFieldTrigger} = decorators;
/**
* 渲染组件基类
*/
export default class Renderer extends ScillaComponent {
protected onVector2DModify = () => {
this.makeDirty();
};
private _debugDrawColor: string;
protected dirty: boolean = true;
/**
* 是否使用缓存模式
*/
protected _useCacheMode: boolean = false;
/**
* 透明度
*/
alpha: number = 1;
//锚点:在各子render里面加,从绘制上改,将同时更改位置原点,旋转原点,缩放原点,以0到1比例形式(现用此方案)
//在该render上改transform;更改旋转和缩放原点,不改变位置原点,默认中心为位置原点,以真实数值形式
@dirtyFieldTrigger
anchor: Vector2D = new Vector2D(0.5, 0.5);
/**
* 边界
*/
protected bounds = new Bounds();
protected cacheCanvas = null;
/**
* 缓存用的渲染上下文
*/
protected cacheCanvasContext;
/**
* 锚点实际偏移
*/
protected _anchorOffset: Vector2D = new Vector2D();
//渲染上下文
protected _context = getContext();
/**
* 扩展尺寸
*/
protected _margin: number = 0;
get useCacheMode() {
return this.getUseCacheMode();
}
set useCacheMode(value) {
this._useCacheMode = value;
}
constructor(){
super();
this._debugDrawColor = `hsl(${math.makeRandomInt(360)}, ${math.makeRandomInt(100)}%, 60%)`;
}
protected getUseCacheMode() {
return this._useCacheMode;
}
/**
* 获取渲染上下文
* 如果缓存上下文存在,则返回缓存上下文
*/
get context() {
return this.cacheCanvasContext || this._context;
}
makeDirty() {
this.dirty = true;
}
/**
* @inheritDoc
*/
protected onModify(value, key, oldValue) {
super.onModify(value, key, oldValue);
this.makeDirty();
switch (key) {
case 'anchor':
value.onChange = this.onVector2DModify;
break;
}
}
onAwake() {
super.onAwake();
if (!this.transform) {
console.warn('renderer need a transform component');
}
}
/**
* @inheritDoc
*/
onUpdate(t) {
if (this.dirty) {
if(this.entity.name == 'label_status'){
console.log();
}
if (this.useCacheMode) {
this.readyCacheCanvas();
}
this.measureBounds();
if (this.useCacheMode) {
this.updateCacheCanvas();
}
}
this.transformToLocal();
this.render();
if (EngineConfig.drawRenderRect) {
const {_context, _debugDrawColor, bounds: {width, height}, _anchorOffset: {x, y}, transform: {pivot: {x: px, y: py}}} = this;
_context.globalAlpha = 0.9;
_context.strokeStyle = _debugDrawColor;
_context.fillStyle = _debugDrawColor;
_context.beginPath();
_context.rect(0, 0, width, height);
_context.stroke();
_context.beginPath();
_context.arc(width * px, height * py, 3, 0, 2 * Math.PI);
_context.fill();
}
}
/**
* 准备缓存渲染上下文
*/
protected readyCacheCanvas() {
let canvas = this.cacheCanvas;
if (!canvas) {
canvas = this.cacheCanvas = createCanvas();
this.cacheCanvasContext = canvas.getContext('2d');
}
}
/**
* 更新缓存属性
*/
protected updateCacheCanvas() {
let canvas = this.cacheCanvas;
const {width, height} = this.bounds;
canvas.width = width + this._margin * 2;
canvas.height = height + this._margin * 2;
}
/**
* 渲染过程
*/
protected render() {
this.beforeDraw();
this.drawClip();
if (this.dirty) {
if(this.useCacheMode){
this.draw();
}
this.dirty = false;
}
if (this.useCacheMode) {
this.drawCache();
} else {
this.draw();
}
}
/**
* 画之前
*/
protected beforeDraw() {
this.applyAlpha();
}
/**
* 执行矩阵转换
*/
protected transformToLocal() {
const {transform, _anchorOffset: {x: ax, y: ay}} = this;
if (transform && transform.enabled) {
const {a, b, c, d, tx, ty} = transform.getMatrix(true);
const offX = ax * a + ay * c;
const offY = ax * b + ay * d;
this._context.setTransform(a, b, c, d, tx - offX, ty - offY);
} else {
this._context.setTransform(1, 0, 0, 1, -ax, -ay);
}
}
/**
* 应用透明度
*/
protected applyAlpha() {
this._context.globalAlpha = this.alpha * this.transform.renderAlpha;
}
/**
* 绘制缓存
*/
protected drawCache() {
if (this.cacheCanvas.width > 0 && this.cacheCanvas.height > 0) {
this._context.drawImage(this.cacheCanvas, -this._margin, -this._margin);
}
}
/**
* 画遮罩
*/
protected drawClip() {
}
/**
* 画
*/
protected draw() {
}
/**
* 测量边界
*/
protected measureBounds() {
const {anchor: {x, y}, bounds, bounds: {width, height}} = this;
const anchorOffsetX = this._anchorOffset.x = width * x;
const anchorOffsetY = this._anchorOffset.y = height * y;
bounds.x = -anchorOffsetX;
bounds.y = -anchorOffsetY;
}
/**
* 碰撞检测
* @param x
* @param y
*/
hitTest(x, y) {
return this.bounds.contains(x, y);
}
}
This diff is collapsed.
/**
* Created by rockyl on 2018/11/6.
*/
import Renderer from "./Renderer";
import {Texture, decorators} from "scilla";
const {dirtyFieldDetector} = decorators;
export enum FillMode {
/**
* 正常
*/
NORMAL,
/**
* 裁切
*/
SLICED,
/**
* 瓦片
*/
TILED,
}
/**
* 纹理渲染组件
*/
export default class TextureRenderer extends Renderer {
/**
* 纹理资源
*/
@dirtyFieldDetector
texture: Texture;
/**
* 填充模式
*/
@dirtyFieldDetector
fillMode: FillMode = FillMode.NORMAL;
/**
* 滤镜数组
*/
@dirtyFieldDetector
filters = [];
private get hasFilters() {
return this.filters && this.filters.length > 0;
}
/**
* @inheritDoc
*/
draw() {
super.draw();
this.drawImage();
this.applyFilters();
/*const {context, texture, hasFilters} = this;
if (texture && hasFilters) {
const {bounds: {width: textureWidth, height: textureHeight}} = texture;
//筛选阴影滤镜Shadow
let s = this;
let cf = s.filters;
let cfLen = cf.length;
let fId = -1;
if (cfLen) {
for (let i = 0; i < cfLen; i++) {
if (s.filters[i].type == "Shadow") {
fId = i;
break;
}
}
}
if (fId >= 0) {
let ctx: any = context;
ctx.shadowBlur = cf[fId].blur;
ctx.shadowColor = cf[fId].color;
ctx.shadowOffsetX = cf[fId].offsetX;
ctx.shadowOffsetY = cf[fId].offsetY;
ctx.drawImage(this.cacheCanvas, 0, 0, textureWidth, textureHeight);
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
} else {
context.drawImage(this.cacheCanvas, 0, 0, textureWidth, textureHeight);
}
// context.drawImage(texture.img, x, y, textureWidth, textureHeight, -width * this.anchor.x, -height * this.anchor.y, width, height);
}*/
}
/**
* 应用滤镜
*/
applyFilters() {
if (!this.hasFilters) return;
const {texture, filters, context} = this;
const {bounds: {width: textureWidth, height: textureHeight}} = texture;
let imageData = context.getImageData(0, 0, textureWidth, textureHeight);
for (const filter of filters) {
filter.drawFilter(imageData);
}
context.putImageData(imageData, 0, 0);
}
/**
* 根据模式绘制图片
*/
drawImage() {
if(!this.texture){
return;
}
const {texture, fillMode, context, bounds: {width, height}} = this;
const {bounds: {x, y, width: textureWidth, height: textureHeight}} = texture;
switch (fillMode) {
case FillMode.NORMAL:
texture.drawToCanvas(context);
break;
case FillMode.SLICED:
break;
case FillMode.TILED:
const textureCanvas = texture.getCacheCanvas();
const pattern = context.createPattern(textureCanvas, 'repeat');
context.rect(0, 0, width, height);
context.fillStyle = pattern;
context.fill();
break;
}
}
/**
* @inheritDoc
*/
measureBounds() {
if (!this.dirty) {
return;
}
const {bounds, transform: {explicitWidth: tWidth, explicitHeight: tHeight}} = this;
if (this.texture) {
const {width: textureWidth, height: textureHeight} = this.texture;
bounds.width = isNaN(tWidth) ? textureWidth : tWidth;
bounds.height = isNaN(tHeight) ? textureHeight : tHeight;
} else {
bounds.width = isNaN(tWidth) ? 0 : tWidth;
bounds.height = isNaN(tHeight) ? 0 : tHeight;
}
super.measureBounds();
}
}
/**
* Created by rockyl on 2019-01-10.
*/
export {default as CircleRenderer} from './CircleRenderer'
export {default as FrameAnimationRenderer} from './FrameAnimationRenderer'
export {default as GraphicRenderer} from './GraphicRenderer'
export {default as LineRenderer} from './LineRenderer'
export {default as RectRenderer} from './RectRenderer'
export {default as Renderer} from './Renderer'
export {default as TextRenderer} from './TextRenderer'
export {default as TextureRenderer} from './TextureRenderer'
/**
* Created by rockyl on 2018/11/23.
*
* 按钮
*/
import {ScillaEvent, Texture,} from "scilla";
import TouchZoom from "../animation/TouchZoom";
import {InteractComponent} from "../base";
import {TextureRenderer} from "../renderer";
export default class Button extends InteractComponent {
upRes: Texture;
downRes: Texture;
disabledRes: Texture;
onClick: ScillaEvent;
private bgRenderer: TextureRenderer;
private currentRes: Texture;
private touchBeginWithSelf: boolean;
private touchOut: boolean;
constructor() {
super();
this.touchInterrupt = true;
}
get touchZoom(): TouchZoom{
return this.entity && this.entity.getComponent(TouchZoom);
}
onModify(value, key, oldValue) {
super.onModify(value, key, oldValue);
if (key === 'interactable') {
if(this.touchZoom){
this.touchZoom.interactable = value;
}
try {
this.changeTexture();
}catch (e) {}
}
}
onCreate() {
super.onCreate();
this.onClick = new ScillaEvent();
}
onAwake() {
super.onAwake();
this.bgRenderer = this.entity.getComponent(TextureRenderer);
this.changeTexture(this.upRes);
}
onTouchBegin(e) {
super.onTouchBegin(e);
this.touchBeginWithSelf = true;
this.changeTexture(this.downRes);
}
onTouchOver(e) {
super.onTouchOver(e);
if (this.touchBeginWithSelf) {
this.touchBeginWithSelf = true;
this.changeTexture(this.downRes);
}
this.touchOut = false;
}
onTouchOut(e) {
super.onTouchOut(e);
if (this.touchBeginWithSelf) {
this.changeTexture(this.upRes);
}
this.touchOut = true;
}
onGlobalTouchEnd(e) {
super.onGlobalTouchEnd(e);
if (this.touchBeginWithSelf && !this.touchOut) {
this.onClick.invoke();
}
this.touchBeginWithSelf = false;
this.changeTexture(this.upRes);
}
changeTexture(res?) {
if(!this.bgRenderer){
return;
}
this.currentRes = res || this.upRes;
if(this.interactable){
this.bgRenderer.texture = this.currentRes;
}else{
this.bgRenderer.texture = this.disabledRes;
}
}
}
/**
* Created by rockyl on 2018-12-26.
*
* 进度条
*/
import {Entity, ScillaComponent, decorators, createTween, ease} from "scilla";
import RectRenderer from "../renderer/RectRenderer";
import Transform from "../base/Transform";
import TextRenderer from "../renderer/TextRenderer";
const {dirtyFieldTrigger} = decorators;
function renderLabelFuncSample(value, maximum, minimum){
return Math.floor(value / (maximum - minimum) * 100) + '%';
}
export default class ProgressBar extends ScillaComponent {
viewport: Entity;
thumb: Entity;
widget: Entity;
label: Entity;
@dirtyFieldTrigger
value: number = 0;
@dirtyFieldTrigger
minimum: number = 0;
@dirtyFieldTrigger
maximum: number = 0;
@dirtyFieldTrigger
snapInterval: number = 1;
@dirtyFieldTrigger
renderLabelFunc: Function;
@dirtyFieldTrigger
fixWithRange: boolean = true;
private _mask: RectRenderer;
private _widgetTransform: Transform;
private _label: TextRenderer;
private _thumbSize: any;
onCreate() {
super.onCreate();
this.renderLabelFunc = renderLabelFuncSample;
}
onAwake() {
super.onAwake();
this._mask = this.viewport.getComponent(RectRenderer);
this._mask.width = 0;
if(this.widget){
this._widgetTransform = this.widget.getComponent(Transform);
}
this._label = this.label.getComponent(TextRenderer);
this.callOnNextTick(this.updateThumbSize);
}
private updateThumbSize=()=>{
const {width, height} = this.thumb.getComponent(Transform);
this._thumbSize = {width, height};
this.update();
};
onModify(value, key, oldValue) {
super.onModify(value, key, oldValue);
if(oldValue === undefined){
return;
}
this.callOnNextTick(this.update);
}
private update(){
const {minimum, maximum, _thumbSize} = this;
if(!_thumbSize){
return ;
}
const range = maximum - minimum;
let value = Math.max(minimum, Math.min(maximum, this.value));
const percentage = (value - minimum) / range;
const width = percentage * _thumbSize.width;
//this._mask.width = width;
createTween(this._mask, true)
.to({width}, 300, ease.cubicOut);
if(this._widgetTransform){
this._widgetTransform.position.x = width;
}
let renderValue = this.fixWithRange ? Math.max(minimum, Math.min(maximum, this.value)) : this.value;
this.value = value;
if(this._label){
let text = this.renderLabelFunc(renderValue, this.maximum, this.minimum);
if(typeof text == 'string'){
this._label.text = text;
this._label.textFlow = null;
}else{
this._label.textFlow = text;
this._label.updateTextFlow();
}
}
}
}
/**
* Created by rockyl on 2018-12-13.
*
* 滚动视图组件
*/
import {Entity, Size, createTween, createVector2D, Vector2D, ease} from "scilla";
import InteractComponent from "../base/InteractComponent";
import Transform from "../base/Transform";
enum LockingType {
NOSET,
HORIZON,
VERTICAL,
}
export default class ScrollView extends InteractComponent {
viewport: Entity;
content: Entity;
lockingType: LockingType = LockingType.NOSET;
private _beginPos: any;
private _lastPos: Vector2D = createVector2D();
private _viewportTransform: Transform;
private _contentTransform: Transform;
private _posOffset: any;
private _posRange: Size;
private _speed: Vector2D = createVector2D();
onAwake() {
super.onAwake();
this._contentTransform = this.content.getComponent(Transform);
this._viewportTransform = this.viewport.getComponent(Transform);
this.callOnNextTick(this.updatePosOffset);
}
updatePosOffset = ()=>{
const {position: {x: x, y: y}} = this._contentTransform;
this._posOffset = {x, y};
//console.log(this._posOffset);
}
updatePosRange = () => {
const {width: pWidth, height: pHeight} = this._viewportTransform;
const {width, height} = this._contentTransform;
this._posRange = new Size(pWidth - width, pHeight - height);
//console.log(this._posRange);
};
onTouchBegin(e) {
super.onTouchBegin(e);
this.updatePosRange();
const {x: tx, y: ty} = e;
const {_contentTransform: {position: {x: cx, y: cy}}} = this;
this._beginPos = {
tx,
ty,
cx,
cy,
};
this._lastPos.setXY(tx, ty);
}
onGlobalTouchMove(e) {
super.onGlobalTouchMove(e);
if (!this._beginPos) {
return;
}
const {
_beginPos: {tx, ty, cx, cy},
_posOffset: {x: offX, y: offY},
_contentTransform: {position},
lockingType,
} = this;
const {x, y} = e;
let px = x - tx + cx;
let py = y - ty + cy;
const {width: rWidth, height: rHeight} = this._posRange;
const halfWidth = Math.abs( rWidth / 2);
const paddingX = halfWidth - Math.abs(offX - halfWidth - px);
if(paddingX < 0){
px += paddingX * 0.8 * (x - tx > 0 ? 1 : -1);
}
const halfHeight = Math.abs( rHeight / 2);
const paddingY = halfHeight - Math.abs(offY - halfHeight - py);
if(paddingY < 0){
py += paddingY * 0.8 * (y - ty > 0 ? 1 : -1);
}
switch (lockingType) {
case LockingType.HORIZON:
position.y = py;
break;
case LockingType.VERTICAL:
position.x = px;
break;
default:
position.setXY(px, py);
}
this._speed.copyFrom(this._lastPos.subtract({x, y}));
this._lastPos.setXY(x, y);
}
onGlobalTouchEnd(e) {
super.onGlobalTouchEnd(e);
if (!this._beginPos) {
return;
}
this._beginPos = null;
const {x: offX, y: offY} = this._posOffset;
const {width: rWidth, height: rHeight} = this._posRange;
const {position, position: {x, y}} = this._contentTransform;
const tx = Math.min(Math.max(offX + rWidth, x), offX);
const ty = Math.min(Math.max(offY + rHeight, y), offY);
const targetPos = createVector2D(tx, ty);
const duration = Math.min(500, Math.max(targetPos.distance(position), 200));
createTween(this._contentTransform, true, {clazz: Vector2D, fields: ['x', 'y']})
.to({position: targetPos}, duration, ease.cubicOut);
}
}
/**
* Created by rockyl on 2019-01-10.
*/
export {default as Button} from './Button'
export {default as ProgressBar} from './ProgressBar'
export {default as ScrollView} from './ScrollView'
{
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"sourceMap": true,
"declarationDir": "./types",
"declaration": true,
"lib": [
"es5",
"es6",
"dom",
"es2015.promise"
],
"baseUrl": "./",
"paths": {
"scilla": ["node_modules/scilla/src"]
}
},
"include": [
"src",
"libs"
]
}
\ No newline at end of file
This diff is collapsed.
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
/.rpt2_cache/
{
"name": "scilla-core",
"version": "1.0.0",
"main": "./dist/bundle.js",
"types": "./types/index.d.ts",
"license": "MIT",
"scripts": {
"build": "rollup -c"
},
"dependencies": {
"tslib": "^1.9.3"
},
"devDependencies": {
"rollup": "^0.66.6",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-typescript2": "^0.18.0",
"rollup-plugin-uglify": "^6.0.0",
"tslib": "^1.9.3",
"typescript": "^3.1.6"
}
}
/**
* Created by rockyl on 2018/11/16.
*/
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const typescript = require('rollup-plugin-typescript2');
const {uglify} = require('rollup-plugin-uglify');
export default {
input: 'src/index.ts',
output: {
file: 'dist/bundle.js',
format: 'umd',
name: 'scilla',
//sourcemap: true,
},
plugins: [
resolve({
browser: true,
}),
typescript({
typescript: require('typescript'),
tslib: require('tslib'),
useTsconfigDeclarationDir: true,
}),
commonjs(),
uglify({}),
]
};
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
export type color = string;
export type resource = any;
export type raw = any;
This diff is collapsed.
This diff is collapsed.
/**
* Created by rockyl on 2018-11-30.
*/
import {Sheet} from "./Sheet";
const animationMap = {};
const animDataMap = {};
const textureMap = {};
/**
* 获取一个帧动画资源
* @param name
*/
export function getFrameAnimation(name): FrameAnimation {
let animation: FrameAnimation = animationMap[name];
if (!animation) {
animation = animationMap[name] = new FrameAnimationImpl(name);
animation.fillMcData(name);
}
return animation;
}
/**
* 放置帧动画图片和数据
* @param img
* @param data
*/
export function putFrameAnim(img, data) {
const {mc, res} = data;
let sheet: Sheet = new Sheet(img, res);
for (let key in mc) {
const animData = animDataMap[key] = mc[key];
animData.sheet = sheet;
}
}
/**
* 帧动画资源
*/
export interface FrameAnimation {
/**
* 填充帧数据
* @param name
*/
fillMcData(name);
/**
* 获取帧率
*/
readonly fps: number;
/**
* 获取所有帧标签
*/
readonly labels: any[];
/**
* 获取帧数
*/
readonly frameCount: number;
/**
* 根据名字获取帧标签
* @param name
*/
getLabel(name): any;
/**
* 获取帧
* @param frameIndex
*/
getFrame(frameIndex): any;
/**
* 销毁自身
*/
destroy()
}
/**
* 帧动画资源实现
*/
export class FrameAnimationImpl implements FrameAnimation {
private readonly _name: string;
private _animData;
constructor(name) {
this._name = name;
}
get name(): string {
return this._name;
}
fillMcData(name) {
const animData = animDataMap[name];
if (animData) {
this._animData = animData;
} else {
console.warn(`anim data [${name}] is not exist`)
}
}
get fps(): number {
return this._animData.frameRate;
}
get labels(): any[] {
return this._animData.labels;
}
get frameCount(): number {
return this._animData.frames.length;
}
getLabel(name): any {
let result;
for (let label of this._animData.labels) {
if (label.name == name) {
result = label;
break;
}
}
return result;
}
getFrame(frameIndex): any {
const {_animData,} = this;
let texture, frameData;
if (_animData) {
const {frames} = _animData;
frameData = frames[frameIndex];
if (frameData) {
const res = frameData.res;
texture = textureMap[res];
if (!texture) {
texture = textureMap[res] = _animData.sheet.getTexture(res);
}
}
}
return {
texture,
data: frameData,
};
}
destroy() {
this._animData = null;
}
}
/**
* Created by rockyl on 2018/11/5.
*/
let HASH_CODE_INK = 0;
function getHashCode() {
return ++HASH_CODE_INK;
}
/**
* 哈希对象
*/
export default class HashObject {
_hashCode;
constructor() {
this._hashCode = getHashCode();
}
get hashCode() {
return this._hashCode;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**
* Created by rockyl on 2018/11/5.
*/
export {ScillaComponent} from "./ScillaComponent";
export {Entity} from './Entity'
export {Scene} from './Scene'
export {ScillaEvent} from './ScillaEvent'
export {getContext, createCanvas, getStageSize, getStageScale, getStageCenter, shortcut, ScaleMode} from './context/RenderContext';
export * from './manager'
export {default as Texture, createTexture} from './Texture'
export * from './Sheet'
export * from './FrameAnimation'
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
*.js linguist-language=TypeScript
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment