Skip to content
This repository has been archived by the owner on Jun 14, 2021. It is now read-only.

Commit

Permalink
Merge pull request #130 from Ragg-/fix/project-entity-broken-on-save
Browse files Browse the repository at this point in the history
Fix project entity broken on serialization / deserialization
  • Loading branch information
Ragg committed Sep 18, 2017
2 parents 83072ee + 189432c commit 1f55300
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 20 deletions.
78 changes: 78 additions & 0 deletions src/delir-core/src/project/__spec__/keyframe-spec.ts
@@ -0,0 +1,78 @@
import Keyframe from '../keyframe'
import ColorRGB from '../../values/color-rgb'
import ColorRGBA from '../../values/color-rgba'

import assign from '../../__spec__/Utils/assign'

describe('Keyframe', () => {
const baseParam = Object.freeze({ easeInParam: [1, 1] as [number, number], easeOutParam: [1, 1] as [number, number], frameOnClip: 0, value: null })

it('Should correct toJSON / fromJSON with number value', () => {
const numberKf = assign(new Keyframe(), { ...baseParam, value: 1 })
const expected = { id: numberKf.id, config: { ...baseParam, value: 1 } }

expect(numberKf.toJSON()).to.eql(expected)
expect(Keyframe.deserialize(numberKf.toJSON()).toJSON()).to.eql(expected)
})

it('Should correct toJSON / fromJSON with boolean value', () => {
const booleanKf = assign(new Keyframe(), { ...baseParam, value: 1 })
const expected = { id: booleanKf.id , config: { ...baseParam, value: true } }

expect(booleanKf.toJSON()).to.eql(expected)
expect(Keyframe.deserialize(booleanKf.toJSON()).toJSON()).to.eql(expected)
})

it('Should correct toJSON / fromJSON with string value', () => {
const stringKf = assign(new Keyframe(), { ...baseParam, value: 'string' })
const expected = { id: stringKf.id, config: { ...baseParam, value: 'string' } }

expect(stringKf.toJSON()).to.eql(expected)
expect(Keyframe.deserialize(stringKf.toJSON()).toJSON()).to.eql(expected)
})

it('Should correct toJSON / fromJSON with AssetPointer value', () => {
const assetKf = assign(new Keyframe(), { ...baseParam, value: { assetId: 'asset-id' } })
const expected = { id: assetKf.id, config: { ...baseParam, value: { type: 'asset', value: { assetId: 'asset-id' } } } }

expect(assetKf.toJSON()).to.eql(expected)
expect(Keyframe.deserialize(assetKf.toJSON()).toJSON()).to.eql(expected)
})

it('Should correct toJSON / fromJSON with ColorRGB value', () => {
const assetKf = assign(new Keyframe(), { ...baseParam, value: new ColorRGB(0, 1, 2) })
const expected = { id: assetKf.id, config: { ...baseParam, value: { type: 'color-rgb', value: { red: 0, green: 1, blue: 2 } } } }

expect(assetKf.toJSON()).to.eql(expected)

const restoredKf = Keyframe.deserialize(assetKf.toJSON())
expect(restoredKf.toJSON()).to.eql(expected)
expect(restoredKf.value).to.eql(new ColorRGB(0, 1, 2))
})

it('Should correct toJSON / fromJSON with ColorRGBA value', () => {
const assetKf = assign(new Keyframe(), { ...baseParam, value: new ColorRGBA(0, 1, 2, 3) })
const expected = { id: assetKf.id, config: { ...baseParam, value: { type: 'color-rgba', value: { red: 0, green: 1, blue: 2, alpha: 3 } } } }

expect(assetKf.toJSON()).to.eql(expected)

const restoredKf = Keyframe.deserialize(assetKf.toJSON())
expect(restoredKf.toJSON()).to.eql(expected)
expect(restoredKf.value).to.eql(new ColorRGBA(0, 1, 2, 3))
})

it('Should failed fromJSON with unexpected input', () => {
expect(() => {
Keyframe.deserialize({
id: 'kfid',
config: {
...baseParam,
value: {
type: 'あたまわるわる〜',
value: '✌(´◓q◔`)✌'
} as any
}
})
}).throwError()
})
})
63 changes: 56 additions & 7 deletions src/delir-core/src/project/keyframe.ts
@@ -1,24 +1,53 @@
// @flow
import * as _ from 'lodash'
import * as uuid from 'uuid'
import toJSON from '../helper/toJSON'

import {KeyframeValueTypes, KeyframeScheme, KeyframeConfigScheme} from './scheme/keyframe'
// import Point2D from '../values/point-2d'
// import Point3D from '../values/point-3d'
// import Size2D from '../values/size-2d'
// import Size3D from '../values/size-3d'
import ColorRGB from '../values/color-rgb'
import ColorRGBA from '../values/color-rgba'

import {JSONKeyframeValueTypes, KeyframeScheme, KeyframeConfigScheme, AssetPointerScheme} from './scheme/keyframe'

type KeyframeValueTypes = number|boolean|string|ColorRGB|ColorRGBA|AssetPointerScheme

export default class Keyframe
{
static deserialize(keyframeJson: KeyframeScheme)
public static deserialize(keyframeJson: KeyframeScheme)
{
const keyframe = new Keyframe()

const config = _.pick(keyframeJson.config, [
'value',
'frameOnClip',
'easeInParam',
'easeOutParam',
]) as KeyframeConfigScheme

const jsonValue: JSONKeyframeValueTypes = config.value
let realValue: KeyframeValueTypes

if (jsonValue == null || typeof jsonValue === 'number' || typeof jsonValue === 'string' || typeof jsonValue === 'boolean') {
realValue = jsonValue
} else if (_.isObject(jsonValue)) {
if (jsonValue.type === 'color-rgb') {
realValue = ColorRGB.fromJSON(jsonValue.value)
} else if (jsonValue.type === 'color-rgba') {
realValue = ColorRGBA.fromJSON(jsonValue.value)
} else if (jsonValue.type === 'asset') {
realValue = jsonValue.value
} else {
const __NEVER__: never = jsonValue
throw new Error(`Deserialization failed, unexpected object value on Keyframe#${keyframeJson.id}`)
}
} else {
throw new Error(`Deserialization failed, unexpected value type on Keyframe#${keyframeJson.id}`)
}

Object.defineProperty(keyframe, '_id', {value: keyframeJson.id || uuid.v4()})
Object.assign(keyframe._config, config)
Object.assign(keyframe._config, config, { value: realValue })

return keyframe
}
Expand Down Expand Up @@ -62,18 +91,38 @@ export default class Keyframe
constructor()
{
Object.seal(this)
Object.seal(this._config)
}

public toPreBSON(): Object
public toPreBSON(): KeyframeScheme
{
return this.toJSON()
}

public toJSON(): Object
public toJSON(): KeyframeScheme
{
let value: JSONKeyframeValueTypes

if (this.value instanceof ColorRGB) {
value = { type: 'color-rgb', value: this.value.toJSON() }
} else if (this.value instanceof ColorRGBA) {
value = { type: 'color-rgba', value: this.value.toJSON() }
} else if (_.isObject(this.value) && _.has(this.value as AssetPointerScheme, 'assetId')) {
value = { type: 'asset', value: toJSON(this.value as AssetPointerScheme) }
} else if (_.isObject(this.value)) {
throw new Error(`Serialization failed, unexpected value type on Keyframe#${this.id}`)
} else {
value = this.value as string|number|boolean
}

return {
id: this.id,
config: toJSON(this._config),
config: {
value,
easeInParam: toJSON(this.easeInParam),
easeOutParam: toJSON(this.easeOutParam),
frameOnClip: this.frameOnClip,
},
}
}
}
28 changes: 17 additions & 11 deletions src/delir-core/src/project/scheme/keyframe.ts
@@ -1,25 +1,31 @@
import Point2D from '../../values/point-2d'
import Point3D from '../../values/point-3d'
import Size2D from '../../values/size-2d'
import Size3D from '../../values/size-3d'
import ColorRGB from '../../values/color-rgb'
import ColorRGBA from '../../values/color-rgba'
// import Point2D from '../../values/point-2d'
// import Point3D from '../../values/point-3d'
// import Size2D from '../../values/size-2d'
// import Size3D from '../../values/size-3d'
import {ColorRgbJSON} from '../../values/color-rgb'
import {ColorRgbaJSON} from '../../values/color-rgba'

export interface AssetPointerScheme {
assetId: string
}

export type KeyframeValueTypes =
Point2D|Point3D|Size2D|Size3D|ColorRGB|ColorRGBA|number|boolean|string|AssetPointerScheme
export type JSONKeyframeValueTypes =
| number
| boolean
| string
| {type: 'color-rgb', value: ColorRgbJSON}
| {type: 'color-rgba', value: ColorRgbaJSON}
| {type: 'asset', value: AssetPointerScheme}
// Point2D|Point3D|Size2D|Size3D

export interface KeyframeConfigScheme {
value: KeyframeValueTypes
frameOnClip: number|null
value: JSONKeyframeValueTypes
frameOnClip: number
easeInParam: [number, number]
easeOutParam: [number, number]
}

export interface KeyframeScheme {
id: string|null
id: string
config: KeyframeConfigScheme
}
7 changes: 6 additions & 1 deletion src/delir-core/src/values/color-rgb.ts
Expand Up @@ -5,6 +5,11 @@ export interface ColorRgbJSON {
}

export default class ColorRGB {
public static fromJSON(json: ColorRgbJSON)
{
return new ColorRGB(json.red, json.green, json.blue)
}

private _red: number
private _green: number
private _blue: number
Expand Down Expand Up @@ -40,7 +45,7 @@ export default class ColorRGB {
)
}

public toJSON()
public toJSON(): ColorRgbJSON
{
return {
red: this.r,
Expand Down
7 changes: 6 additions & 1 deletion src/delir-core/src/values/color-rgba.ts
Expand Up @@ -6,6 +6,11 @@ export interface ColorRgbaJSON {
}

export default class ColorRGBA {
public static fromJSON(json: ColorRgbaJSON)
{
return new ColorRGBA(json.red, json.green, json.blue, json.alpha)
}

private _red: number
private _green: number
private _blue: number
Expand Down Expand Up @@ -48,7 +53,7 @@ export default class ColorRGBA {
)
}

public toJSON()
public toJSON(): ColorRgbaJSON
{
return {
red: this.r,
Expand Down

0 comments on commit 1f55300

Please sign in to comment.