Commit 5352e9ee authored by rockyl's avatar rockyl

1.1版本

parent 8249e2a1
......@@ -3,7 +3,7 @@
*/
import HashObject from "./HashObject";
import {Entity,} from "./Entity";
import {Node,} from "./Node";
import {EngineConfig} from "../engine-config";
const interactiveMap = [
......@@ -17,9 +17,9 @@ const interactiveMap = [
*/
export class Component extends HashObject {
/**
* 所依附的实体
* 所依附的节点
*/
entity: Entity;
node: Node;
protected delayCallbacks = [];
//是否有效
......@@ -37,7 +37,7 @@ export class Component extends HashObject {
set enabled(value: boolean) {
if (this._enabled !== value) {
this._enabled = value;
if (this.entity && this.entity.isActive) {
if (this.node && this.node.isActive) {
if (!EngineConfig.editorMode) {
if (this._enabled) {
this.onEnable();
......@@ -50,18 +50,18 @@ export class Component extends HashObject {
}
/**
* 装配实体
* @param entity
* 装配节点
* @param node
*/
_setup(entity: Entity) {
this.entity = entity;
_setup(node: Node) {
this.node = node;
}
/**
* 卸载实体
* 卸载节点
*/
_unSetup() {
this.entity = null;
this.node = null;
}
/**
......@@ -111,12 +111,12 @@ export class Component extends HashObject {
this.onEditorUpdate(t);
}
$afterUpdate() {
this.afterUpdate();
$onRegression() {
this.onRegression();
}
$afterEditorUpdate() {
this.afterEditorUpdate();
$onEditorRegression() {
this.onEditorRegression();
}
private invokeDelayCallback(t) {
......@@ -144,13 +144,13 @@ export class Component extends HashObject {
}
/**
* 当子实体的时钟更新结束后
* 当子节点的时钟更新结束后
*/
afterUpdate() {
onRegression() {
}
afterEditorUpdate() {
onEditorRegression() {
}
......@@ -273,7 +273,7 @@ export class Component extends HashObject {
* @param params 参数
*/
broadcast(method, level = -1, ...params) {
this.entity.broadcast(method, level, ...params);
this.node.broadcast(method, level, ...params);
}
/**
......@@ -283,6 +283,6 @@ export class Component extends HashObject {
* @param params 参数
*/
bubbling(method, ...params) {
this.entity.bubbling(method, ...params);
this.node.bubbling(method, ...params);
}
}
This diff is collapsed.
......@@ -4,7 +4,7 @@
* 引擎
*/
import {Entity, RootEntity} from "./Entity";
import {Node, RootNode} from "./Node";
import {injectProp} from "../tools/utils";
import InteractContext from "./context/InteractContext";
import RenderContext, {ScaleMode} from "./context/RenderContext";
......@@ -36,7 +36,7 @@ export class ScillaEngine {
*/
readonly dataCenterConfig: any = {};
private _root: Entity;
private _root: RootNode;
private _canvasElement: HTMLCanvasElement;
private _flush = 0;
......@@ -139,7 +139,7 @@ export class ScillaEngine {
onUpdateScale: this.onUpdateScale.bind(this),
});
this._root = new RootEntity(this);
this._root = new RootNode(this);
this._root._restrict();
}
......@@ -163,19 +163,19 @@ export class ScillaEngine {
}
/**
* 获取根Entity
* 获取根Node
*/
get root(): Entity {
get root(): Node {
return this._root;
}
/**
* 获取实体路径
* @param entity
* 获取节点路径
* @param node
*/
getEntityPath(entity?: Entity): string {
getNodePath(node?: Node): string {
let path = '';
let current = entity || this._root;
let current = node || this._root;
while (current.parent) {
path = current.parent.children.indexOf(current) + (path.length > 0 ? '|' : '') + path;
current = current.parent;
......@@ -184,10 +184,10 @@ export class ScillaEngine {
}
/**
* 根据实体路径获取实体
* 根据节点路径获取节点
* @param path
*/
getEntityByPath(path?: string): Entity {
getNodeByPath(path?: string): Node {
let target = this._root;
if (path.length > 0) {
......@@ -308,7 +308,7 @@ export class ScillaEngine {
return true;
}
}, -1, true, function (current) {
current.$afterUpdate();
current.onRegression();
});
for (let i = 0, li = this.nextTicks.length; i < li; i++) {
......@@ -356,7 +356,7 @@ export class ScillaEngine {
}
/**
* 射线测试获取实体
* 射线测试获取节点
* 注:暂时只用在编辑器内
*/
getEntitiesByRayTest(x, y, ignoreMask = true) {
......@@ -365,7 +365,7 @@ export class ScillaEngine {
let rendererDef = this.getDefByName('components/renderer/Renderer');
traversePostorder(this._root, function (child) {
const transform = child.components[0];
const matrix = transform['getMatrix'](true, true, true);
const matrix = transform['getMatrix'](true, true);
matrix.transformPoint(x, y, localPos);
const renderers = child.getComponents(rendererDef);
......
......@@ -105,8 +105,6 @@ export default class RenderContext {
this.engine = engine;
}
//todo
private onModify(value, key, oldValue) {
if (!this.dirtyFieldTriggerLock) {
this.updateScaleModeSelf();
......
......@@ -3,7 +3,7 @@
*/
export {Component} from "./Component";
export {Entity} from './Entity'
export {Node, RootNode} from './Node'
export {ScillaEvent} from './ScillaEvent'
export {createCanvas, ScaleMode} from './context/RenderContext';
export {default as engine, ScillaEngine} from './ScillaEngine'
......@@ -13,3 +13,4 @@ export * from './Sheet'
export * from './FrameAnimation'
export * from './interpreter'
export * from './nodes'
......@@ -4,13 +4,13 @@
* 配置文件解释器
*/
import {Entity} from "../core/Entity";
import {Node} from "../core/Node";
import {ScillaEvent} from "../core/ScillaEvent";
import {EngineConfig} from "../engine-config";
import engine from "./ScillaEngine";
import {traverse} from "./utils";
let entityMap = {};
let nodeMap = {};
let prefabID: number = 0;
let _getResProxy: Function;
......@@ -24,89 +24,80 @@ export function setGetResProxy(func: Function) {
* @param root
* @param getResProxy
*/
export function setupScene(config: any, root: Entity, getResProxy: Function) {
export function setupScene(config: any, root: Node, getResProxy: Function) {
setGetResProxy(getResProxy);
instantiateConfig(config, root);
}
/**
* 清空实体
* @param entity
*/
export function cleanEntity(entity: Entity) {
entity.removeAllComponents();
entity.removeChildren();
}
/**
* 装配预制体
* @param config
*/
export function instantiate(config: any): Entity {
export function instantiate(config: any): Node {
let pid = ++prefabID;
const entity = instantiateConfig(config, null, pid);
const node = instantiateConfig(config, null, pid);
return entity.children[0];
return node.children[0];
}
/**
* 装配树实体
* 装配树节点
* @param config
* @param root
* @param pid
*/
function instantiateConfig(config, root?: Entity, pid?: number): Entity {
function instantiateConfig(config, root?: Node, pid?: number): Node {
let rootConfig = config.root;
const entity = setupEntity(rootConfig, root, pid);
setupComponent(rootConfig, entity, true);
injectComponent(rootConfig, entity, true, pid);
const node = setupNode(rootConfig, root, pid);
setupComponent(rootConfig, node, true);
injectComponent(rootConfig, node, true, pid);
traverse(entity, child => {
traverse(node, child => {
child.active();
return false;
});
entityMap = {};
nodeMap = {};
return entity;
return node;
}
/**
* 装配实体
* 装配节点
* @param config
* @param root
* @param pid
*/
function setupEntity(config, root?: Entity, pid?: number): Entity {
let entity: Entity = null;
function setupNode(config, root?: Node, pid?: number): Node {
let node: Node = null;
if (config) {
let {name, uuid, children} = config;
if (pid !== undefined && uuid !== undefined) {
uuid = pid + '_' + uuid;
}
entity = root || new Entity(name, uuid);
node = root || new Node(name, uuid);
entityMap[uuid] = entity;
nodeMap[uuid] = node;
if (children) {
for (let i = 0, li = children.length; i < li; i++) {
let child = children[i];
const childEntity = setupEntity(child, null, pid);
entity.addChild(childEntity);
const childNode = setupNode(child, null, pid);
node.addChild(childNode);
}
}
if (!root) {
entity.enabled = !config.disabled;
node.enabled = !config.disabled;
}
}
return entity;
return node;
}
/**
......@@ -115,18 +106,18 @@ function setupEntity(config, root?: Entity, pid?: number): Entity {
* @param root
* @param includeSelf
*/
function setupComponent(config, root: Entity, includeSelf: boolean = false) {
function setupComponent(config, root: Node, includeSelf: boolean = false) {
if (includeSelf) {
instantiateComponents(root, config);
}
if (config && config.children) {
for (let i = 0, li = root.children.length; i < li; i++) {
const child = config.children[i];
const entity = root.children[i];
const node = root.children[i];
instantiateComponents(entity, child);
instantiateComponents(node, child);
setupComponent(child, entity);
setupComponent(child, node);
}
}
}
......@@ -138,44 +129,44 @@ function setupComponent(config, root: Entity, includeSelf: boolean = false) {
* @param includeSelf
* @param pid
*/
function injectComponent(config, root: Entity, includeSelf = false, pid?: number) {
function injectComponent(config, root: Node, includeSelf = false, pid?: number) {
if (includeSelf) {
injectComponents(root, config, pid);
}
if (config && config.children) {
for (let i = 0, li = root.children.length; i < li; i++) {
const child = config.children[i];
const entity = root.children[i];
const node = root.children[i];
injectComponents(entity, child, pid);
injectComponents(node, child, pid);
injectComponent(child, entity, false, pid);
injectComponent(child, node, false, pid);
}
}
}
/**
* 实例化组件列表
* @param entity
* @param node
* @param config
*/
function instantiateComponents(entity: Entity, config: any) {
function instantiateComponents(node: Node, config: any) {
if (config.components) {
for (const component of config.components) {
instantiateComponent(entity, component);
instantiateComponent(node, component);
}
}
}
/**
* 注入组件列表参数
* @param entity
* @param node
* @param config
* @param pid
*/
function injectComponents(entity: Entity, config: any, pid?: number) {
function injectComponents(node: Node, config: any, pid?: number) {
if (config.components) {
const components = entity.components;
const components = node.components;
for (let i = 0, li = config.components.length; i < li; i++) {
const component = config.components[i];
......@@ -200,10 +191,10 @@ export function injectComponentProperties(component, config, pid?: number) {
/**
* 实例化组件
* @param entity
* @param node
* @param config
*/
export function instantiateComponent(entity: Entity, config: any) {
export function instantiateComponent(node: Node, config: any) {
const {script,} = config;
let def = engine.getDefByName(script);
......@@ -214,7 +205,7 @@ export function instantiateComponent(entity: Entity, config: any) {
const instance: any = new def();
instance.enabled = !config.disabled;
entity.addComponent(instance);
node.addComponent(instance);
return instance;
}
......@@ -223,13 +214,13 @@ const skipKeys = ['_type_', '_constructor_'];
/**
* 属性注入
* @param entity
* @param node
* @param propertiesConfig
* @param pid
*/
function injectProperties(entity, propertiesConfig, pid?: number) {
if (!entity) {
console.warn('entity is null.');
function injectProperties(node, propertiesConfig, pid?: number) {
if (!node) {
console.warn('node is null.');
return;
}
for (const key in propertiesConfig) {
......@@ -237,22 +228,22 @@ function injectProperties(entity, propertiesConfig, pid?: number) {
continue;
}
const propertyOfConfig: any = propertiesConfig[key];
let propertyOfInstance = entity[key];
let propertyOfInstance = node[key];
if (typeof propertyOfConfig === 'object') {
if (propertyOfInstance instanceof ScillaEvent) {
if (!EngineConfig.editorMode) {
injectEvent(propertyOfInstance, propertyOfConfig, pid);
}
} else if (propertyOfConfig._type_ === 'raw') {
entity[key] = propertyOfInstance = propertyOfConfig.data;
node[key] = propertyOfInstance = propertyOfConfig.data;
} else {
if (Array.isArray(propertyOfConfig) && !propertyOfInstance) {
entity[key] = propertyOfInstance = []
node[key] = propertyOfInstance = []
}
entity[key] = injectObject(propertyOfInstance, propertyOfConfig, pid);
node[key] = injectObject(propertyOfInstance, propertyOfConfig, pid);
}
} else {
injectBaseType(entity, key, propertyOfConfig, pid);
injectBaseType(node, key, propertyOfConfig, pid);
}
}
}
......@@ -277,7 +268,7 @@ function injectObject(propertyOfInstance, propertyOfConfig, pid?: number) {
return propertyOfInstance;
}
function injectBaseType(entity, key, propertyOfConfig, pid?: number) {
function injectBaseType(node, key, propertyOfConfig, pid?: number) {
let propertyValue;
if (typeof propertyOfConfig === 'string') {
propertyValue = getLink(propertyOfConfig, pid);
......@@ -291,23 +282,23 @@ function injectBaseType(entity, key, propertyOfConfig, pid?: number) {
}
if (typeof propertyValue === 'function') {
Object.defineProperty(entity, keyAvatar, {
Object.defineProperty(node, keyAvatar, {
get() {
return this[`func_${keyAvatar}`](entity, engine.dataCenter)
return this[`func_${keyAvatar}`](node, engine.dataCenter)
},
set(v) {
this[`func_${keyAvatar}`] = v;
}
})
}
entity[keyAvatar] = propertyValue;
node[keyAvatar] = propertyValue;
}
function injectEvent(event: ScillaEvent, config, pid?) {
for (const {entity: entityName, component: componentIndex, method: methodName, param} of config) {
if (entityName && componentIndex >= 0 && methodName) {
const entity = getLink(entityName, pid);
const component = entity.components[componentIndex];
for (const {node: nodeName, component: componentIndex, method: methodName, param} of config) {
if (nodeName && componentIndex >= 0 && methodName) {
const node = getLink(nodeName, pid);
const component = node.components[componentIndex];
const method = component[methodName];
if (method) {
if (param == undefined) {
......@@ -325,9 +316,9 @@ function getLink(str: string, pid?: number) {
if (str.indexOf('res|') == 0) { //res uuid
const uuid = str.substr(4);
result = _getResProxy(uuid);
} else if (str.indexOf('entity|') == 0) { //entity uuid
} else if (str.indexOf('node|') == 0) { //node uuid
const uuid = transPrefabUUID(str.substr(7), pid);
result = entityMap[uuid];
result = nodeMap[uuid];
} else if (str.indexOf('dynamic|') == 0) { //dynamic
const [_, type, expression] = str.split('|');
result = () => {
......
/**
* Created by rockyl on 2019-07-05.
*
* (圆角)矩形
*/
import {GraphicNode} from "./GraphicNode";
import {dirtyFieldDetector} from "../../tools/decorators";
export class Circle extends GraphicNode {
/**
* 开始角度
*/
@dirtyFieldDetector
startAngle: number = 0;
/**
* 结束角度
*/
@dirtyFieldDetector
endAngle: number = 360;
/**
* 是否回归到圆心
*/
@dirtyFieldDetector
backToCenter: boolean = true;
/**
* @inheritDoc
*/
protected draw() {
const {currentCanvasContext, 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){
currentCanvasContext.arc(pos, pos, radius, 0, 2 * Math.PI);
}else{
if(backToCenter){
currentCanvasContext.moveTo(pos, pos);
}
currentCanvasContext.arc(pos, pos, radius, startAngle * Math.PI / 180, endAngle * Math.PI / 180);
if(backToCenter){
currentCanvasContext.lineTo(pos, pos);
}
}
super.draw();
}
}
/**
* Created by rockyl on 2019-07-05.
*
* 绘制节点
*/
import {Node} from "../Node";
import {dirtyFieldDetector} from "../../tools/decorators";
import {color} from "../../ReType";
export class GraphicNode extends Node {
/**
* 填充颜色
*/
@dirtyFieldDetector
fillColor: color = '#42bce4';
/**
* 边框颜色
*/
@dirtyFieldDetector
borderColor: color = 'white';
/**
* 边框宽度
*/
@dirtyFieldDetector
borderWidth = 0;
/**
* 是否为mask
*/
@dirtyFieldDetector
isMask = false;
/**
* 是否显示mask
*/
@dirtyFieldDetector
maskVisible = false;
useCacheMode = true;
protected getUseCacheMode(){
return this._useCacheMode && !this.isMask;
}
/**
* @inheritDoc
*/
protected beforeDraw() {
super.beforeDraw();
this.applyStyle();
this.currentCanvasContext.beginPath();
}
/**
* @inheritDoc
*/
protected draw(context) {
super.draw(context);
if (this.isMask) {
this._context.clip();
this.maskVisible && this.fillAndStoke()
} else {
this.fillAndStoke()
}
}
/**
* 应用渲染样式
*/
protected applyStyle() {
const {currentCanvasContext, fillColor, borderColor, borderWidth} = this;
currentCanvasContext.fillStyle = fillColor;
if (borderWidth > 0) {
currentCanvasContext.strokeStyle = borderColor;
currentCanvasContext.lineWidth = borderWidth;
}
}
/**
* 绘制
*/
protected fillAndStoke() {
const {currentCanvasContext, borderWidth} = this;
currentCanvasContext.fill();
if (borderWidth > 0) {
currentCanvasContext.stroke();
}
}
/**
* @inheritDoc
*/
protected drawClip() {
this.isMask && this.currentCanvasContext.save();
}
/**
* @inheritDoc
*/
onRegression() {
this.isMask && this.currentCanvasContext.restore();
}
onEditorRegression(){
this.onRegression();
}
}
/**
* Created by rockyl on 2019-07-05.
*
* (圆角)矩形
*/
import {GraphicNode} from "./GraphicNode";
import {dirtyFieldDetector} from "../../tools/decorators";
export class Rect extends GraphicNode {
/**
* 圆角
*/
@dirtyFieldDetector
cornerRadius = 0;
/**
* @inheritDoc
*/
protected draw(context) {
const {PI} = Math;
const {cornerRadius: r, bounds: {width, height}, _margin, _useCacheMode} = this;
let offset = _useCacheMode ? _margin : 0;
if (r) {
context.moveTo(offset + r, offset);
context.lineTo(offset + width - r, offset);
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, offset + r);
context.arc(offset + r, offset + r, r, PI, PI * 3 / 2);
} else {
context.rect(offset, offset, width, height);
}
super.draw(context);
}
}
/**
* Created by rockyl on 2019-07-05.
*/
export * from './GraphicNode'
export * from './Rect'
export * from './Circle'
/**
* Created by rockyl on 2019-04-22.
*
* 实体相关工具
* 节点相关工具
*/
import {Entity} from "./Entity";
import {Component} from "./Component";
import {Node} from "./Node";
/**
* 实体遍历(先序遍历)
* @param target 目标实体
* @param hitChild 遇到子实体回调
* 节点遍历(先序遍历)
* @param target 目标节点
* @param hitChild 遇到子节点回调
* @param level 深度,默认全部遍历
* @param includeSelf 是否包括自身
* @param fullCallback 子实体遍历完后回调
* @param fullCallback 子节点遍历完后回调
* @param params 其他参数
*/
export function traverse(target: Entity, hitChild: (child: Entity, ...params) => boolean, level = -1, includeSelf = false, fullCallback?: (current: Entity) => void, ...params) {
export function traverse(target: Node, hitChild: (child: Node, ...params) => boolean, level = -1, includeSelf = false, fullCallback?: (current: Node) => void, ...params) {
let interrupt;
if (includeSelf) {
hitChild(target, ...params);
......@@ -38,15 +37,15 @@ export function traverse(target: Entity, hitChild: (child: Entity, ...params) =>
}
/**
* 实体遍历(后序遍历且倒序)
* @param target 目标实体
* @param hitChild 遇到子实体回调
* 节点遍历(后序遍历且倒序)
* @param target 目标节点
* @param hitChild 遇到子节点回调
* @param level 深度,默认全部遍历
* @param includeSelf 是否包括自身
* @param fullCallback 子实体遍历完后回调
* @param fullCallback 子节点遍历完后回调
* @param params 其他参数
*/
export function traversePostorder(target: Entity, hitChild: (child: Entity, ...params) => boolean, level = -1, includeSelf = false, fullCallback?: (current: Entity) => void, ...params) {
export function traversePostorder(target: Node, hitChild: (child: Node, ...params) => boolean, level = -1, includeSelf = false, fullCallback?: (current: Node) => void, ...params) {
let interrupt;
if (level !== 0) {
......@@ -73,19 +72,19 @@ export function traversePostorder(target: Entity, hitChild: (child: Entity, ...p
}
/**
* 实体冒泡
* @param target 目标实体
* @param hitParent 遇到父实体回调
* 节点冒泡
* @param target 目标节点
* @param hitParent 遇到父节点回调
* @param includeSelf 是否包括自身
* @param params 其他参数
*/
export function bubbling(target: Entity, hitParent: (parent: Entity, ...params) => boolean, includeSelf = false, ...params) {
export function bubbling(target: Node, hitParent: (parent: Node, ...params) => boolean, includeSelf = false, ...params) {
if (includeSelf) {
hitParent(target, ...params);
}
let entity = target;
while (entity = entity.parent) {
if (hitParent(entity, ...params)) {
let node = target;
while (node = node.parent) {
if (hitParent(node, ...params)) {
break;
}
}
......
......@@ -15,19 +15,19 @@ export const EngineConfig = {
*/
lineHeightRatio: 1.2,
/**
* 实体实例化时enabled的初始值
* 节点实例化时enabled的初始值
*/
entityEnabled: true,
nodeEnabled: true,
/**
* 组件实例化时enabled的初始值
*/
componentEnabled: true,
/**
* 组件被添加到实体树上时是否执行onAwake方法
* 组件被添加到节点树上时是否执行onAwake方法
*/
awakeComponentWhenAdded: true,
/**
* 组件从实体树上被移除时是否执行onSleep方法
* 组件从节点树上被移除时是否执行onSleep方法
*/
sleepComponentWhenRemoved: true,
/**
......
......@@ -18,7 +18,7 @@ export default class Bounds {
@dirtyFieldTrigger
height: number;
_onChange: Function;
onChange: Function;
constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0, onChange?) {
this.x = x;
......@@ -26,11 +26,11 @@ export default class Bounds {
this.width = width;
this.height = height;
this._onChange = onChange;
this.onChange = onChange;
}
onModify(value, key, oldValue){
this._onChange && this._onChange(value, key, oldValue);
this.onChange && this.onChange(value, key, oldValue);
}
get left(): number {
......
......@@ -68,11 +68,11 @@ export default class DataCenter extends EventEmitter {
* @param expression
*/
public parse(type: string, expression: string) {
let entity = this.store[type];
let node = this.store[type];
let result = null;
try {
result = utils.dotEval(expression, entity);
result = utils.dotEval(expression, node);
} catch (e) {
}
......
......@@ -8,7 +8,7 @@ import HashObject from "../core/HashObject";
/**
* 尺寸类
*/
export default class Size extends HashObject{
export default class Size extends HashObject {
/**
* 宽度
*/
......@@ -32,18 +32,26 @@ export default class Size extends HashObject{
this.height = height;
}
onModify(value, key, oldValue) {
this.onChange && this.onChange(value, key, oldValue);
}
/**
* 置空
*/
setNaN(){
setNaN() {
this.width = NaN;
this.height = NaN;
}
isNaN() {
return isNaN(this.width) && isNaN(this.height);
}
/**
* 是否空尺寸
*/
get isEmpty(){
get isEmpty() {
return this.width === 0 && this.height === 0;
}
......@@ -77,8 +85,4 @@ export default class Size extends HashObject{
this.width = target.width;
this.height = target.height;
}
onModify(value, key, oldValue) {
this.onChange && this.onChange(value, key, oldValue);
}
}
......@@ -5,6 +5,7 @@
import {get, recycle, register} from "./ObjectPool";
import HashObject from "../core/HashObject";
import {dirtyFieldTrigger} from "../tools/decorators";
const name = 'Vector2D';
register(name, function () {
......@@ -34,9 +35,18 @@ export function releaseVector2D(target) {
* 2D矢量
*/
export default class Vector2D extends HashObject {
private _x: number;
private _y: number;
private onChange: Function;
/**
* x分量
*/
@dirtyFieldTrigger
x: number;
/**
* y分量
*/
@dirtyFieldTrigger
y: number;
onChange: Function;
/**
* 创建一个2D矢量
......@@ -49,41 +59,11 @@ export default class Vector2D extends HashObject {
this.onChange = onChange;
this._x = 0;
this._y = 0;
this.setXY(x, y);
}
/**
* x分量
*/
get x(): number {
return this._x;
}
set x(v: number) {
if (this._x !== v) {
const old = this._x;
this._x = v;
this.onChange && this.onChange(v, 'x', old);
}
}
/**
* y分量
*/
get y(): number {
return this._y;
}
set y(v: number) {
if (this._y !== v) {
const old = this._y;
this._y = v;
this.onChange && this.onChange(v, 'y', old);
}
onModify(value, key, oldValue) {
this.onChange && this.onChange(value, key, oldValue);
}
/**
......
......@@ -6,9 +6,9 @@
/**
* 属性修改时触发
* @param onChange
* @param onModify
*/
export function fieldChanged(onChange) {
export function fieldChanged(onModify) {
return function (target: any, key: string) {
const privateKey = '_' + key;
Object.defineProperty(target, key, {
......@@ -20,7 +20,7 @@ export function fieldChanged(onChange) {
const oldValue = this[privateKey];
if (oldValue !== v) {
this[privateKey] = v;
onChange.apply(this, [v, key, oldValue]);
onModify.apply(this, [v, key, oldValue]);
}
}
})
......@@ -36,6 +36,21 @@ export const dirtyFieldDetector = fieldChanged(
}
);
/**
* 深度属性变脏时设置宿主的dirty属性为true
*/
export const deepDirtyFieldDetector = fieldChanged(
function (value, key, oldValue) {
const scope = this;
scope['dirty'] = true;
if (typeof value === 'object') {
value['onModify'] = function(){
scope['dirty'] = true;
};
}
}
);
/**
* 属性变脏时触发onModify方法
*/
......@@ -44,3 +59,18 @@ export const dirtyFieldTrigger = fieldChanged(
this['onModify'] && this['onModify'](value, key, oldValue);
}
);
/**
* 深入属性变脏时触发onModify方法
*/
export const deepDirtyFieldTrigger = fieldChanged(
function (value: any, key, oldValue) {
if (this['onModify']) {
this['onModify'](value, key, oldValue);
if (typeof value === 'object') {
value['onModify'] = this['onModify'];
}
}
}
);
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