Compare commits

...

105 Commits

Author SHA1 Message Date
Rick Companje
35e4877326 update version number 2021-06-06 21:18:03 +02:00
Rick Companje
d519033bd6 update colors 2021-06-06 20:56:03 +02:00
Rick Companje
7418cce606 Update package-lock.json 2021-06-01 01:09:31 +02:00
Rick Companje
de19534d9d
Update LICENSE.md 2021-05-30 22:59:07 +02:00
Rick Companje
9f84cf406b
Update README.md 2021-05-30 22:58:44 +02:00
casper
83d03e8a1a Merge branch 'master' of https://github.com/Doodle3D/Doodle3D-Core 2021-05-28 11:14:27 +02:00
casper
011d9904a7 fix bug in text utils 2021-05-28 01:34:09 +02:00
Rick Companje
353793d867 Update package.json 2021-05-27 00:32:31 +02:00
Rick Companje
395a116760 Update package.json 2021-05-27 00:22:02 +02:00
Rick Companje
e11de849dd Create LICENSE.md 2021-05-27 00:20:32 +02:00
Rick Companje
a0307f8ead
Update README.md 2021-05-26 23:37:44 +02:00
casper
80c08d7b2c move potrace options 2021-05-24 17:51:35 +02:00
casper
bb1b2b73c0 update floodfill 2021-05-24 16:49:57 +02:00
casper
f613c2b68d simplify imports 2021-05-20 04:16:53 +02:00
Casper Lamboo
87b6e9851b typo 2021-05-19 19:59:54 +02:00
Casper Lamboo
31e9ec735f Update react refs 2021-05-19 19:51:34 +02:00
Casper Lamboo
1a5f0fd9d0 Bump react version 2021-05-19 19:14:32 +02:00
casper
a6eeb3f3f6 Move font loading inside library
it was in the app-example
2021-05-14 19:32:29 +02:00
Rick Companje
f514c9da45 geen idee... 2021-05-05 22:01:53 +02:00
Rick Companje
d569a4f5b7 fonts 2021-05-05 19:44:31 +02:00
Casper Lamboo
d43c55906b remove trailing } 2021-05-05 18:58:33 +02:00
Casper Lamboo
5f7e70027a Merge branch 'master' of https://github.com/Doodle3D/Doodle3D-Core 2021-05-05 18:58:25 +02:00
Casper Lamboo
4879f47d4c remove tap event plugin 2021-05-05 18:55:43 +02:00
Casper Lamboo
fed4146aea remove unused dependecies 2020-12-11 17:09:18 +01:00
Casper Lamboo
9e5c929da5 remove pouchdb
was not used in this repo
2020-12-11 13:08:10 +01:00
Casper Lamboo
0c1cdb1580 use background image for logo 2018-11-27 17:17:31 +01:00
Casper Lamboo
6260e21c6d add react tap event plugin 2018-11-27 17:17:19 +01:00
Casper Lamboo
02e312247c remove on touch tap 2018-06-26 15:31:13 +02:00
Casper Lamboo
3670802bea bumb version 2018-06-25 12:10:29 +02:00
Casper Lamboo
b5e0d809c7 fix drag & drop 2018-06-21 16:10:27 +02:00
Casper Lamboo
023c416b5d add space to comment 2018-06-21 16:10:21 +02:00
Casper Lamboo
c55750613f rename sketch file to doodle3d 2018-06-21 16:10:13 +02:00
Casper Lamboo
853d8a5c7e bumb version 2018-05-29 15:06:19 +02:00
Casper Lamboo
b5bf5eb8c7 bumb version 2018-05-29 14:33:49 +02:00
Casper Lamboo
ac2256d2c5 fix position of pointer in brush tool and eraser pointer 2018-05-09 13:22:23 +02:00
Casper Lamboo
b0c0063039 add disable scroll 2018-05-09 11:29:00 +02:00
Casper Lamboo
ca4b886c93 add wheel 2018-05-09 10:50:18 +02:00
Casper Lamboo
582b8f8c37 use latest version of touch events 2018-05-09 10:46:52 +02:00
Casper Lamboo
fcd6bdbbf8 set drag threshold to 0 2018-04-24 16:01:42 +02:00
Casper Lamboo
0a3686d8df wait for assets to be loaded in create scene data 2018-04-23 10:26:49 +02:00
Casper Lamboo
24abade4b9 update version 2018-04-05 11:41:40 +02:00
Casper Lamboo
7a3ee5888a add change tool to undo filter 2018-03-20 13:14:19 +01:00
Casper Lamboo
ab581cf79b add open sketch to undo filter
#3
2018-03-19 10:36:33 +01:00
Casper Lamboo
efb1efe3d9 use includes instead of indexOf 2018-03-19 10:36:19 +01:00
Rick Companje
7360cdc85a keyboard shortcuts 2018-03-19 10:36:11 +01:00
Rick Companje
d98b90bb2e options (ie. lineWidth) in window.downloadStl 2018-03-09 16:03:56 +01:00
Casper Lamboo
3d63e349fe remove auth image 2018-03-01 11:49:58 +01:00
Casper Lamboo
6e1660504b remove db utils 2018-03-01 11:37:13 +01:00
Casper Lamboo
2b84cd0b11 update doc to file 2018-02-27 15:02:23 +01:00
Casper Lamboo
5032018257 recursive fetch in authimage 2018-02-27 13:45:40 +01:00
Casper Lamboo
6b6b860c4a fix opening sketches
from
- on drop
- index.js
2018-02-21 12:29:33 +01:00
Casper Lamboo
63b33c69b9 disable s to download file 2018-02-21 12:28:17 +01:00
Casper Lamboo
7d34f916ac make sure everything is loaded before generating thumb 2018-02-21 12:25:34 +01:00
Casper Lamboo
42c2b1243f scale down default text 2018-02-21 12:23:54 +01:00
Casper Lamboo
5564e8b533 add font loader 2018-02-21 11:54:25 +01:00
Casper Lamboo
eb19034e86 don't fail when null objects are present in d3sketch format
there shouldn’t be null objects
2018-02-21 11:21:35 +01:00
casperlamboo
b9ed59c8d9 fix open sketch 2018-02-15 12:32:45 +01:00
casperlamboo
9996728f9c also store app version in data object 2018-02-15 12:24:27 +01:00
casperlamboo
02a7f64d5f rename function 2018-02-15 12:12:15 +01:00
casperlamboo
1d4562e2df fix recursiveMap function 2018-02-15 12:12:04 +01:00
casperlamboo
7fd9220851 fix component did mount 2018-02-15 11:12:39 +01:00
casperlamboo
be8a49e5c7 fix importing sketch 2018-02-15 10:28:26 +01:00
casperlamboo
f387297195 cleanup v2 2018-02-14 17:23:53 +01:00
casperlamboo
07c5d0635c cleanup 2018-02-14 17:20:30 +01:00
casperlamboo
9101a6325a fix reviver 2018-02-14 17:05:50 +01:00
casperlamboo
68a36c29e3 fix import 2018-02-14 16:43:21 +01:00
casperlamboo
ec22dc0cf7 add app version to doc 2018-02-14 16:26:53 +01:00
casperlamboo
dd8ab3263c cleanup 2018-02-14 14:53:07 +01:00
casperlamboo
da12939253 update fileformat
- don’t include images guides
- don’t store sketch data and app version in object
2018-02-14 14:52:16 +01:00
casperlamboo
12ba7f624f add meta tag 2018-01-31 14:31:56 +01:00
casperlamboo
4bd5c2f679 use web pack html 2018-01-31 14:27:05 +01:00
Rick Companje
4080f0151c Merge branch 'master' of https://github.com/Doodle3D/Doodle3D-Core 2018-01-30 17:34:41 +01:00
Rick Companje
d300a31929 npm run upload 2018-01-30 17:34:37 +01:00
casperlamboo
ff09b3942a remove unused images 2018-01-30 11:04:00 +01:00
casperlamboo
4cb60940f8 format glsl files 2018-01-30 11:04:00 +01:00
Rick Companje
ad94402400 custom html, favicon and btnExport 2018-01-25 16:40:10 +01:00
Rick Companje
908050bbd0 Merge branch 'master' of https://github.com/Doodle3D/Doodle3D-Core 2018-01-25 15:40:32 +01:00
Rick Companje
509cff2eae gitignore 2018-01-25 15:40:30 +01:00
casperlamboo
36a73c233e Fix unfilled text hit area 2018-01-10 15:49:00 +01:00
casperlamboo
1b66fc21e0 linter 2018-01-10 15:24:25 +01:00
casperlamboo
b674769ef8 normalize mouse wheel 2018-01-10 14:19:57 +01:00
casperlamboo
83113e65b2 remove unused imports 2018-01-10 14:15:09 +01:00
casperlamboo
9ce8594856 Merge branch 'feature/on-screen-text' 2018-01-10 12:33:55 +01:00
casperlamboo
9ca5fd5205 Merge branch 'feature-cordova' 2018-01-10 12:33:05 +01:00
casperlamboo
e8243d84e3 Merge branch 'master' into feature-cordova 2018-01-10 12:32:55 +01:00
casperlamboo
8621ff9755 Merge branch 'master' into feature/on-screen-text 2018-01-10 12:21:25 +01:00
casperlamboo
87acf98f51 add anaglyph effect 2018-01-10 12:21:14 +01:00
casperlamboo
b007ff3f33 update font menu
font menu now places different fonts in a column instead of a row
2018-01-09 16:28:11 +01:00
casperlamboo
7b9f647f11 edit width of input based on number of characters 2018-01-09 16:02:04 +01:00
casperlamboo
a4a5afeb08 formatting 2018-01-09 15:42:30 +01:00
casperlamboo
b42c7829ca make font face updatable and add google fonts 2018-01-09 15:42:25 +01:00
casperlamboo
01bd55796e formatting 2018-01-09 12:12:35 +01:00
casperlamboo
2b5d240487 increase hit area of text shapes
Hit area of text shapes is now the boundingbox
2018-01-09 11:53:12 +01:00
casperlamboo
1464a4b74f remove empty text 2018-01-09 11:21:51 +01:00
casperlamboo
04186fd56c Text can now be edited directly on the canvas 2018-01-09 11:21:26 +01:00
casperlamboo
834ca531fd increase performance of holes 2018-01-06 20:27:23 +01:00
casperlamboo
ab27e7c8c2 update web pack config 2018-01-06 20:27:14 +01:00
casperlamboo
9d1d51d357 add example 2018-01-06 20:27:09 +01:00
casperlamboo
e3cda119ce throw error when object is empty 2017-12-21 11:16:49 +01:00
casperlamboo
0e6fd5fb1c Fix num of circle points 2017-12-18 17:05:24 +01:00
casperlamboo
0c4e410a27 fix material index 2017-12-18 10:09:09 +01:00
casperlamboo
01f4b4c1f8 each part has it's own material 2017-12-17 16:01:19 +01:00
casperlamboo
65592d6f48 move generate thumb function 2017-12-17 14:24:01 +01:00
casperlamboo
c31115aa0b update export material
export material now has side property so we can differentiate between
open and closed shapes
2017-12-17 12:07:19 +01:00
casperlamboo
162016bbc9 install jss 2017-12-17 12:04:12 +01:00
174 changed files with 26835 additions and 7597 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ plugins
platforms platforms
config.xml config.xml
.DS_Store

22
LICENSE.md Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2015-2021 Doodle3D
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,14 @@
This repository contains the core functionality of Doodle3D Transform.
## Build & run locally
```bash
git clone git@github.com:Doodle3D/Doodle3D-Core.git
cd Doodle3D-Core
npm install # Make sure you have installed NPM / NodeJS first
npm run start
# visit http://localhost:8080
```
## Doodle3D-Transform
The Doodle3D-Core repo just contains the core drawing features of Doodle3D Transform. To get the other features like file management, exporting and slicing you should visit the Doodle3D Transform repository: https://github.com/Doodle3D/Doodle3D-Transform

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

View File

@ -11,6 +11,7 @@ import thunkMiddleware from 'redux-thunk';
import promiseMiddleware from 'redux-promise-middleware'; import promiseMiddleware from 'redux-promise-middleware';
import { createLogger } from 'redux-logger'; import { createLogger } from 'redux-logger';
import sketcherReducer from './src/reducer/index.js'; import sketcherReducer from './src/reducer/index.js';
const reducer = combineReducers({ sketcher: sketcherReducer }); const reducer = combineReducers({ sketcher: sketcherReducer });
const enhancer = compose(applyMiddleware(thunkMiddleware, promiseMiddleware(), createLogger({ collapsed: true }))); const enhancer = compose(applyMiddleware(thunkMiddleware, promiseMiddleware(), createLogger({ collapsed: true })));
const store = createStore(reducer, enhancer); const store = createStore(reducer, enhancer);
@ -23,16 +24,37 @@ import { saveAs as saveAsLib } from 'file-saver';
// download file // download file
import { createFile } from './src/utils/exportUtils.js'; import { createFile } from './src/utils/exportUtils.js';
window.downloadStl = () => { import sketchDataToJSON from './src/shape/sketchDataToJSON.js';
import { JSONToBlob } from './src/utils/binaryUtils.js';
// usage: downloadStl({lineWidth:20})
window.downloadStl = (options) => {
store.dispatch(async (dispatch, getState) => { store.dispatch(async (dispatch, getState) => {
const state = getState(); const state = getState();
const blob = await createFile(state.sketcher.present, 'stl-blob'); const blob = await createFile(state.sketcher.present, 'stl-blob', options);
saveAsLib(blob, 'doodle.stl'); saveAsLib(blob, 'doodle.stl');
}); });
}; };
window.downloadSketch = () => {
store.dispatch((dispatch, getState) => {
const state = getState();
const json = sketchDataToJSON(state.sketcher.present);
const blob = JSONToBlob(json);
saveAsLib(blob, 'doodle.doodle3d');
});
};
// import keycode from 'keycode';
// window.addEventListener('keydown', (event) => {
// // downloadSketch
// const key = keycode(event);
// if (key === 's') window.downloadSketch();
// });
// add model to store // add model to store
import modelData from './models/simple_hole.d3sketch'; import modelData from './models/circle_error.d3sketch';
import JSONToSketchData from './src/shape/JSONToSketchData.js'; import JSONToSketchData from './src/shape/JSONToSketchData.js';
JSONToSketchData(JSON.parse(modelData)).then(data => { JSONToSketchData(JSON.parse(modelData)).then(data => {
store.dispatch(actions.openSketch({ data })); store.dispatch(actions.openSketch({ data }));
@ -42,10 +64,11 @@ JSONToSketchData(JSON.parse(modelData)).then(data => {
import jss from 'jss'; import jss from 'jss';
import preset from 'jss-preset-default'; import preset from 'jss-preset-default';
import normalize from 'normalize-jss'; import normalize from 'normalize-jss';
jss.setup(preset()); jss.setup(preset());
jss.createStyleSheet(normalize).attach(); jss.createStyleSheet(normalize).attach();
jss.createStyleSheet({ jss.createStyleSheet({
'@global': { '@global': {
'*': { margin: 0, padding: 0 }, '*': { margin: 0, padding: 0 },
'#app, body, html': { height: '100%', fontFamily: 'sans-serif' }, '#app, body, html': { height: '100%', fontFamily: 'sans-serif' },
body: { overflow: 'auto' }, body: { overflow: 'auto' },

View File

@ -0,0 +1 @@
{"data":"{\"spaces\":[{\"matrix\":{\"metadata\":{\"type\":\"Matrix4\",\"library\":\"three.js\"},\"elements\":[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},\"objects\":[{\"height\":20,\"transform\":{\"metadata\":{\"library\":\"CAL\",\"type\":\"Matrix\"},\"matrix\":[1,0,-16.42969984202213,0,1,-10.74249605055293]},\"z\":0,\"sculpt\":[{\"pos\":0,\"scale\":1},{\"pos\":1,\"scale\":1}],\"twist\":0,\"fill\":true,\"solid\":true,\"circle\":{\"radius\":31.061842611644483,\"segment\":6.283185307179586},\"color\":6873597,\"type\":\"CIRCLE\"},{\"height\":20,\"transform\":{\"metadata\":{\"library\":\"CAL\",\"type\":\"Matrix\"},\"matrix\":[1,0,-3.1595576619273373,0,1,-2.5276461295418784]},\"z\":0,\"sculpt\":[{\"pos\":0,\"scale\":1},{\"pos\":1,\"scale\":1}],\"twist\":0,\"fill\":true,\"solid\":false,\"circle\":{\"radius\":30.41228120273779,\"segment\":6.283185307179586},\"color\":6873597,\"type\":\"CIRCLE\"}]}]}","appVersion":"0.17.4"}

32720
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@doodle3d/doodle3d-core", "name": "@doodle3d/doodle3d-core",
"version": "0.17.5", "version": "0.23.0",
"description": "Core functions of Doodle3D Transform", "description": "Core functions of Doodle3D Transform",
"main": "lib", "main": "lib",
"module": "module", "module": "module",
@ -10,46 +10,50 @@
"ios": "TARGET=app webpack -p && cordova run ios", "ios": "TARGET=app webpack -p && cordova run ios",
"prepare": "npm run build", "prepare": "npm run build",
"lint": "eslint src", "lint": "eslint src",
"dist": "NODE_ENV=production webpack -p",
"build": "npm run build:main && npm run build:module ", "build": "npm run build:main && npm run build:module ",
"build:main": "BABEL_ENV=main babel src -s -d lib", "build:main": "BABEL_ENV=main babel src -s -d lib",
"build:module": "BABEL_ENV=module babel src -s -d module" "build:module": "BABEL_ENV=module babel src -s -d module"
}, },
"dependencies": { "dependencies": {
"@doodle3d/cal": "0.0.8", "@doodle3d/cal": "0.0.8",
"@doodle3d/clipper-js": "^1.0.7", "@doodle3d/clipper-js": "^1.0.11",
"@doodle3d/fill-path": "^1.0.7",
"@doodle3d/potrace-js": "0.0.6", "@doodle3d/potrace-js": "0.0.6",
"@doodle3d/threejs-export-obj": "0.0.8", "@doodle3d/threejs-export-obj": "0.0.8",
"@doodle3d/threejs-export-stl": "0.0.5", "@doodle3d/threejs-export-stl": "0.0.5",
"@doodle3d/touch-events": "0.0.7", "@doodle3d/touch-events": "0.0.9",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"bezier-js": "^2.2.3", "bezier-js": "^2.2.3",
"blueimp-canvas-to-blob": "^3.14.0", "blueimp-canvas-to-blob": "^3.14.0",
"bowser": "^1.8.1", "bowser": "^1.8.1",
"file-loader": "^0.11.2",
"fill-path": "^1.0.11",
"fit-curve": "^0.1.6", "fit-curve": "^0.1.6",
"font-loaded": "^1.0.0",
"imports-loader": "^0.7.1", "imports-loader": "^0.7.1",
"jss": "^9.4.0",
"keycode": "^2.1.9", "keycode": "^2.1.9",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"memoizee": "^0.3.9", "memoizee": "^0.3.9",
"pouchdb": "^6.3.4", "normalize-wheel": "^1.0.1",
"proptypes": "^1.1.0", "proptypes": "^1.1.0",
"raf": "^3.4.0", "raf": "^3.4.0",
"ramda": "^0.21.0", "ramda": "^0.21.0",
"react": "^16.0.0", "react": "^16.0.1",
"react-addons-update": "^15.6.2", "react-addons-update": "^15.6.2",
"react-jss": "^7.0.2", "react-jss": "^7.0.2",
"react-notification-system-redux": "^1.2.0", "react-notification-system-redux": "^1.2.0",
"react-redux": "^5.0.6", "react-redux": "^5.0.6",
"react-resize-detector": "^1.1.0", "react-resize-detector": "^1.1.0",
"react-svg-inline": "^2.0.1", "react-svg-inline": "^2.0.1",
"react-tap-event-plugin": "^3.0.3",
"redux-form": "^7.1.2", "redux-form": "^7.1.2",
"redux-undo": "^1.0.0-beta9-9-7", "redux-undo": "^1.0.0-beta9-9-7",
"reselect": "^3.0.1", "reselect": "^3.0.1",
"semver": "^5.4.1", "semver": "^5.4.1",
"shortid": "^2.2.8", "shortid": "^2.2.8",
"three": "^0.88.0", "three": "^0.88.0",
"three-js-csg": "github:Doodle3D/three-js-csg", "three-js-csg": "github:Doodle3D/three-js-csg"
"valid-url": "^1.0.9"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "6.24.1", "babel-cli": "6.24.1",
@ -81,8 +85,6 @@
"normalize-jss": "^4.0.0", "normalize-jss": "^4.0.0",
"raw-loader": "^0.5.1", "raw-loader": "^0.5.1",
"react-dom": "^16.1.1", "react-dom": "^16.1.1",
"react-router-redux": "^4.0.8",
"react-tap-event-plugin": "^3.0.2",
"redux": "^3.7.2", "redux": "^3.7.2",
"redux-action-wrapper": "^1.0.1", "redux-action-wrapper": "^1.0.1",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
@ -94,16 +96,15 @@
"webpack-bundle-analyzer": "^2.9.1", "webpack-bundle-analyzer": "^2.9.1",
"webpack-cordova-plugin": "^0.1.6", "webpack-cordova-plugin": "^0.1.6",
"webpack-dev-server": "^2.9.4", "webpack-dev-server": "^2.9.4",
"worker-loader": "^1.1.0", "worker-loader": "^1.1.0"
"yml-loader": "^2.1.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/Doodle3D/Doodle3D-Core.git" "url": "git+https://github.com/Doodle3D/Doodle3D-Core.git"
}, },
"author": "Casper @Doodle3D", "author": "Casper @Doodle3D",
"license": "UNLICENSED", "license": "MIT",
"private": true, "private": false,
"bugs": { "bugs": {
"url": "https://github.com/Doodle3D/Doodle3D-Core/issues" "url": "https://github.com/Doodle3D/Doodle3D-Core/issues"
}, },

View File

@ -0,0 +1,29 @@
uniform sampler2D mapLeft;
uniform sampler2D mapRight;
varying vec2 vUv;
uniform mat3 colorMatrixLeft;
uniform mat3 colorMatrixRight;
float lin(float c) {
return c <= 0.04045 ? c * 0.0773993808 : pow(c * 0.9478672986 + 0.0521327014, 2.4);
}
vec4 lin(vec4 c) {
return vec4(lin(c.r), lin(c.g), lin(c.b), c.a);
}
float dev(float c) {
return c <= 0.0031308 ? c * 12.92 : pow(c, 0.41666) * 1.055 - 0.055;
}
void main() {
vec2 uv = vUv;
vec4 colorL = lin(texture2D(mapLeft, uv));
vec4 colorR = lin(texture2D(mapRight, uv));
vec3 color = clamp(colorMatrixLeft * colorL.rgb + colorMatrixRight * colorR.rgb, 0., 1.);
gl_FragColor = vec4(dev(color.r), dev(color.g), dev(color.b), max(colorL.a, colorR.a));
}

View File

@ -0,0 +1,6 @@
varying vec2 vUv;
void main() {
vUv = vec2(uv.x, uv.y);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

View File

@ -1,6 +1,5 @@
import { ActionCreators as undo } from 'redux-undo'; import { ActionCreators as undo } from 'redux-undo';
import * as notification from 'react-notification-system-redux'; import * as notification from 'react-notification-system-redux';
import { routerActions as router } from 'react-router-redux';
import * as selectionUtils from '../utils/selectionUtils.js'; import * as selectionUtils from '../utils/selectionUtils.js';
import { calculatePointInImage, decomposeMatrix } from '../utils/matrixUtils.js'; import { calculatePointInImage, decomposeMatrix } from '../utils/matrixUtils.js';
import { loadImage, prepareImage } from '../utils/imageUtils.js'; import { loadImage, prepareImage } from '../utils/imageUtils.js';
@ -9,7 +8,7 @@ import { createThrottle } from '../utils/async.js';
import { tween } from '../utils/tweenUtils.js'; import { tween } from '../utils/tweenUtils.js';
import { DEFAULT_TRACE_TOLERANCE, MAX_TRACE_TOLERANCE } from '../constants/d2Constants.js'; import { DEFAULT_TRACE_TOLERANCE, MAX_TRACE_TOLERANCE } from '../constants/d2Constants.js';
import * as d2Tools from '../constants/d2Tools.js'; import * as d2Tools from '../constants/d2Tools.js';
import { Matrix } from 'cal'; import { Matrix } from '@doodle3d/cal';
// import createDebug from 'debug'; // import createDebug from 'debug';
// const debug = createDebug('d3d:actions'); // const debug = createDebug('d3d:actions');
@ -74,7 +73,6 @@ export const ALIGN = 'ALIGN';
export const ADD_IMAGE = 'ADD_IMAGE'; export const ADD_IMAGE = 'ADD_IMAGE';
export const D2_TEXT_INIT = 'D2_TEXT_INIT'; export const D2_TEXT_INIT = 'D2_TEXT_INIT';
export const D2_TEXT_INPUT_CHANGE = 'D2_TEXT_INPUT_CHANGE'; export const D2_TEXT_INPUT_CHANGE = 'D2_TEXT_INPUT_CHANGE';
export const D2_TEXT_ADD = 'D2_TEXT_ADD';
export const UNION = 'UNION'; export const UNION = 'UNION';
export const INTERSECT = 'INTERSECT'; export const INTERSECT = 'INTERSECT';
export const MOVE_SELECTION = 'MOVE_SELECTION'; export const MOVE_SELECTION = 'MOVE_SELECTION';
@ -86,6 +84,8 @@ export const TRACE_FLOOD_FILL = 'TRACE_FLOOD_FILL';
export const MENU_OPEN = 'MENU_OPEN'; export const MENU_OPEN = 'MENU_OPEN';
export const MENU_CLOSE = 'MENU_CLOSE'; export const MENU_CLOSE = 'MENU_CLOSE';
export const OPEN_SKETCH = 'OPEN_SKETCH'; export const OPEN_SKETCH = 'OPEN_SKETCH';
export const SET_PREVENT_SCROLL = 'SET_PREVENT_SCROLL';
export const SET_DISABLE_SCROLL = 'SET_DISABLE_SCROLL';
// CATEGORIES // CATEGORIES
// actions that influence selected objects // actions that influence selected objects
@ -390,14 +390,10 @@ export function addImage(file) {
export function d2textInit(position, textId, screenMatrixContainer, screenMatrixZoom) { export function d2textInit(position, textId, screenMatrixContainer, screenMatrixZoom) {
return (dispatch) => { return (dispatch) => {
dispatch({ type: D2_TEXT_INIT, position, textId, screenMatrixContainer, screenMatrixZoom }); dispatch({ type: D2_TEXT_INIT, position, textId, screenMatrixContainer, screenMatrixZoom });
dispatch(router.push('/sketch/inputtext'));
}; };
} }
export function d2textInputChange(text, family, weight, style, fill) { export function d2textInputChange(text) {
return { type: D2_TEXT_INPUT_CHANGE, text, family, weight, style, fill }; return { type: D2_TEXT_INPUT_CHANGE, text };
}
export function d2textAdd() {
return { type: D2_TEXT_ADD };
} }
const traceDragThrottle = createThrottle(); const traceDragThrottle = createThrottle();
@ -422,25 +418,25 @@ export function traceDrag(position, start, id, screenMatrixContainer, screenMatr
}); });
}; };
} }
export function traceTap(position, objects, screenMatrixContainer, screenMatrixZoom) { // export function traceTap(position, objects, screenMatrixContainer, screenMatrixZoom) {
return async (dispatch, getState) => { // return async (dispatch, getState) => {
dispatch({ type: TRACE_TAP }); // dispatch({ type: TRACE_TAP });
//
const state = getState(); // const state = getState();
const id = objects.find(_id => state.sketcher.present.objectsById[_id].type === 'IMAGE_GUIDE'); // const id = objects.find(_id => state.sketcher.present.objectsById[_id].type === 'IMAGE_GUIDE');
//
if (id) { // if (id) {
const shapeData = state.sketcher.present.objectsById[id]; // const shapeData = state.sketcher.present.objectsById[id];
const traceStart = calculatePointInImage(position, shapeData, screenMatrixZoom); // const traceStart = calculatePointInImage(position, shapeData, screenMatrixZoom);
//
const { value: traceData } = await dispatch(floodFill(DEFAULT_TRACE_TOLERANCE, shapeData, traceStart)); // const { value: traceData } = await dispatch(floodFill(DEFAULT_TRACE_TOLERANCE, shapeData, traceStart));
//
return dispatch(traceFloodFill(traceData, shapeData)); // return dispatch(traceFloodFill(traceData, shapeData));
} else { // } else {
return dispatch(importImage()); // return dispatch(importImage());
} // }
}; // };
} // }
export function importImage() { export function importImage() {
return dispatch => { return dispatch => {
@ -502,3 +498,11 @@ export function menuClose(menuValue) {
export function openSketch(data) { export function openSketch(data) {
return { type: OPEN_SKETCH, data }; return { type: OPEN_SKETCH, data };
} }
export function setPreventScroll(preventScroll) {
return { type: SET_PREVENT_SCROLL, preventScroll };
}
export function setDisableScroll(disableScroll) {
return { type: SET_DISABLE_SCROLL, disableScroll };
}

View File

@ -16,6 +16,10 @@ import JSONToSketchData from '../shape/JSONToSketchData.js';
import keycode from 'keycode'; import keycode from 'keycode';
import bowser from 'bowser'; import bowser from 'bowser';
import * as d2Tools from '../constants/d2Tools.js'; import * as d2Tools from '../constants/d2Tools.js';
import { isLoaded, load } from '../utils/loaded.js';
import { setConfig } from '@doodle3d/touch-events';
setConfig({ DRAG_THRESHOLD: 0 });
const styles = { const styles = {
container: { container: {
@ -71,23 +75,45 @@ class App extends React.Component {
selectAll: PropTypes.func.isRequired, selectAll: PropTypes.func.isRequired,
d2ChangeTool: PropTypes.func.isRequired, d2ChangeTool: PropTypes.func.isRequired,
moveSelection: PropTypes.func.isRequired, moveSelection: PropTypes.func.isRequired,
selectedPen: PropTypes.string.isRequired selectedPen: PropTypes.string.isRequired,
preventScroll: PropTypes.bool.isRequired
};
constructor(props) {
super(props);
this.container = React.createRef();
}
state = {
loaded: isLoaded()
}; };
componentDidMount() { componentDidMount() {
const { container } = this.refs; if (!this.state.loaded) load.then(() => this.setState({ loaded: true }));
container.addEventListener('dragover', event => event.preventDefault()); if (this.container.current) {
container.addEventListener('drop', this.onDrop); this.container.current.addEventListener('dragover', this.dragOver);
window.addEventListener('keydown', this.onKeyDown); this.container.current.addEventListener('drop', this.onDrop);
this.container.current.addEventListener('wheel', this.onWheel);
window.addEventListener('keydown', this.onKeyDown);
}
} }
componentWillUnmount() { componentWillUnmount() {
const { container } = this.refs; if (this.container.current) {
container.removeEventListener('drop', this.onDrop);
window.removeEventListener('keydown', this.onKeyDown); this.container.current.addEventListener('dragover', this.dragOver);
this.container.current.removeEventListener('drop', this.onDrop);
this.container.current.addEventListener('wheel', this.onWheel);
window.removeEventListener('keydown', this.onKeyDown);
}
} }
dragOver = event => {
event.preventDefault();
};
onDrop = async event => { onDrop = async event => {
const { openSketch, addImage } = this.props; const { openSketch, addImage } = this.props;
event.preventDefault(); event.preventDefault();
@ -96,12 +122,13 @@ class App extends React.Component {
const extentions = file.name.split('.').pop(); const extentions = file.name.split('.').pop();
switch (extentions.toUpperCase()) { switch (extentions.toUpperCase()) {
case 'DOODLE3D':
case 'D3SKETCH': case 'D3SKETCH':
case 'JSON': case 'JSON':
const url = URL.createObjectURL(file); const url = URL.createObjectURL(file);
const data = await fetch(url).then(result => result.json()); const json = await fetch(url).then(result => result.json());
const sketchData = await JSONToSketchData(data); const data = await JSONToSketchData(json);
openSketch({ data: sketchData }); openSketch({ data });
break; break;
case 'JPG': case 'JPG':
case 'JPEG': case 'JPEG':
@ -145,6 +172,29 @@ class App extends React.Component {
} }
break; break;
case 's': {
if (!commandKey) d2ChangeTool(d2Tools.TRANSFORM);
break;
}
case 'e': {
if (!commandKey) {
event.preventDefault();
d2ChangeTool(d2Tools.ERASER);
}
break;
}
case 'c': {
if (!commandKey) d2ChangeTool(d2Tools.CIRCLE);
break;
}
case 'l': {
if (!commandKey) d2ChangeTool(d2Tools.POLYGON);
break;
}
case 't': { case 't': {
if (!commandKey) d2ChangeTool(d2Tools.TEXT); if (!commandKey) d2ChangeTool(d2Tools.TEXT);
break; break;
@ -176,16 +226,27 @@ class App extends React.Component {
} }
} }
onWheel = (event) => {
const { preventScroll } = this.props;
if (preventScroll) event.preventDefault();
};
dragover = (event) => {
event.preventDefault();
};
render() { render() {
const { classes, undo, redo } = this.props; const { classes, undo, redo } = this.props;
const { loaded } = this.state;
return ( return (
<div ref="container" className={classes.container}> <div ref={this.container} className={classes.container}>
<InlineIconsLoader /> <InlineIconsLoader />
<div className={classes.appContainer}> {loaded && <div className={classes.appContainer}>
<D2Panel /> <D2Panel />
<div className={classes.vLine} /> <div className={classes.vLine} />
<D3Panel /> <D3Panel />
</div> </div>}
<Logo /> <Logo />
<div className={classes.undoMenu}> <div className={classes.undoMenu}>
<Button onSelect={undo} className={classes.undo} /> <Button onSelect={undo} className={classes.undo} />
@ -198,6 +259,7 @@ class App extends React.Component {
} }
export default injectSheet(styles)(connect(state => ({ export default injectSheet(styles)(connect(state => ({
preventScroll: state.sketcher.present.preventScroll,
selectedPen: state.sketcher.present.menus['pen-tools'].selected selectedPen: state.sketcher.present.menus['pen-tools'].selected
}), { }), {
undo: actions.undo.undo, undo: actions.undo.undo,

View File

@ -1,65 +0,0 @@
import React from 'react';
import PropTypes from 'proptypes';
import { connect } from 'react-redux';
import { isWebUri } from 'valid-url';
import PouchDB from 'pouchdb';
// import createDebug from 'debug';
// const debug = createDebug('d3d:FileThumb');
class AuthImage extends React.Component {
static propTypes = {
dispatch: PropTypes.func,
src: PropTypes.string.isRequired,
token: PropTypes.string,
password: PropTypes.string
};
state = {
src: null
};
componentWillMount() {
const { src, token, password } = this.props;
if (src.startsWith('/') || src.startsWith('./')) {
this.setState({ src });
} else if (isWebUri(src)) {
if (token && password) {
const filteredSrc = src.replace(/:\/\/.+?@/, '://');
const headers = {
Authorization: `Basic ${btoa(`${token}:${password}`)}`
};
fetch(filteredSrc, { headers })
.then(response => response.blob())
.then(blob => this.setState({ src: URL.createObjectURL(blob) }));
} else {
this.setState({ src });
}
} else {
const [dbName, docName, attachmentName] = src.split('/');
const db = new PouchDB(dbName);
db.getAttachment(docName, attachmentName).then((blob) => {
this.setState({ src: URL.createObjectURL(blob) });
});
}
}
componentWillUnmount() {
URL.revokeObjectURL(this.state.src);
}
render() {
// filter props before passing them to img element
const props = { ...this.props };
delete props.dispatch;
delete props.token;
delete props.password;
delete props.src;
return (<img { ...props } src={this.state.src} />);
}
}
export default connect(state => ({
token: state.user.session.token,
password: state.user.session.password
}))(AuthImage);

View File

@ -37,7 +37,7 @@ export default class Button extends React.Component {
if (className) combinedClassName += ` ${className}`; if (className) combinedClassName += ` ${className}`;
return ( return (
<div id={id} className={combinedClassName} onTouchTap={this.onClick}> <div id={id} className={combinedClassName} onClick={this.onClick}>
{svg && <svg> {svg && <svg>
<use xlinkHref={svg}/> <use xlinkHref={svg}/>
</svg>} </svg>}

View File

@ -2,7 +2,7 @@ import React from 'react';
import injectSheet from 'react-jss'; import injectSheet from 'react-jss';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as CAL from 'cal'; import * as CAL from '@doodle3d/cal';
import * as toolNames from '../constants/d2Tools'; import * as toolNames from '../constants/d2Tools';
import { PIPETTE } from '../constants/contextTools.js'; import { PIPETTE } from '../constants/contextTools.js';
import { CANVAS_SIZE } from '../constants/d2Constants'; import { CANVAS_SIZE } from '../constants/d2Constants';
@ -22,7 +22,7 @@ import { PIXEL_RATIO } from '../constants/general';
import ShapesManager from '../d2/ShapesManager.js'; import ShapesManager from '../d2/ShapesManager.js';
import EventGroup from '../d2/EventGroup.js'; import EventGroup from '../d2/EventGroup.js';
import ReactResizeDetector from 'react-resize-detector'; import ReactResizeDetector from 'react-resize-detector';
import { load as loadPattern } from '../d2/Shape.js'; import InputText from './InputText.js';
// import createDebug from 'debug'; // import createDebug from 'debug';
// const debug = createDebug('d3d:d2'); // const debug = createDebug('d3d:d2');
@ -63,9 +63,17 @@ class D2Panel extends React.Component {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
classes: PropTypes.objectOf(PropTypes.string) classes: PropTypes.objectOf(PropTypes.string)
}; };
state = {
screenMatrix: new CAL.Matrix()
};
activeNeedRender = false; activeNeedRender = false;
inactiveNeedRender = false; inactiveNeedRender = false;
constructor(props) {
super(props);
this.canvasContainer = React.createRef();
}
componentWillMount() { componentWillMount() {
// Scene space // Scene space
this.sceneActive = new EventGroup({ this.sceneActive = new EventGroup({
@ -89,22 +97,17 @@ class D2Panel extends React.Component {
this.objectContainerInactive.add(new Grid(new CAL.Color(0xdddddd))); this.objectContainerInactive.add(new Grid(new CAL.Color(0xdddddd)));
this.shapesManager = new ShapesManager(this.objectContainerActive, this.objectContainerInactive); this.shapesManager = new ShapesManager(this.objectContainerActive, this.objectContainerInactive);
loadPattern.then(() => {
this.activeNeedRender = true;
this.inactiveNeedRender = true;
this.renderRequest();
});
this.DOM = null; this.DOM = null;
} }
componentDidMount() { componentDidMount() {
const { canvasContainer } = this.refs; if (this.canvasContainer.current) {
this.container = canvasContainer; this.container = this.canvasContainer.current;
this.container.appendChild(this.sceneInactive.image);
this.container.appendChild(this.sceneActive.image);
this.container.appendChild(this.sceneInactive.image);
this.container.appendChild(this.sceneActive.image);
}
this.sceneActive.onClick = (event) => event.stopPropagation(); this.sceneActive.onClick = (event) => event.stopPropagation();
} }
@ -117,7 +120,7 @@ class D2Panel extends React.Component {
} }
switchTool(toolName) { switchTool(toolName) {
if (this.state && toolName === this.state.d2.tool) return; if (this.state.state && toolName === this.state.state.d2.tool) return;
// cleanup & remove previous tool // cleanup & remove previous tool
if (this.tool) { if (this.tool) {
this.tool.destroy(); this.tool.destroy();
@ -135,18 +138,18 @@ class D2Panel extends React.Component {
this.objectContainerActive.add(this.tool); this.objectContainerActive.add(this.tool);
} }
update(newState) { update(state) {
if (this.state === newState) return; if (this.state.state === state) return;
this.updateTool(newState); this.updateTool(state);
const shapesNeedRender = this.shapesManager.update(newState); const shapesNeedRender = this.shapesManager.update(state);
if (shapesNeedRender.active) this.activeNeedRender = true; if (shapesNeedRender.active) this.activeNeedRender = true;
if (shapesNeedRender.inactive) this.inactiveNeedRender = true; if (shapesNeedRender.inactive) this.inactiveNeedRender = true;
// Update Objects Container Space with zoom & panning // Update Objects Container Space with zoom & panning
const newCanvasMatrix = newState.d2.canvasMatrix; const newCanvasMatrix = state.d2.canvasMatrix;
if (this.state && newCanvasMatrix !== this.state.d2.canvasMatrix) { if (this.state.state && newCanvasMatrix !== this.state.state.d2.canvasMatrix) {
this.objectContainerActive.copyMatrix(newCanvasMatrix); this.objectContainerActive.copyMatrix(newCanvasMatrix);
this.objectContainerInactive.copyMatrix(newCanvasMatrix); this.objectContainerInactive.copyMatrix(newCanvasMatrix);
@ -154,9 +157,9 @@ class D2Panel extends React.Component {
this.inactiveNeedRender = true; this.inactiveNeedRender = true;
} }
const selection = (this.state) ? this.state.selection : null; const selection = (this.state.state) ? this.state.state.selection : null;
const newSelection = newState.selection; const newSelection = state.selection;
if (!this.state || newSelection !== selection) { if (!this.state.state || newSelection !== selection) {
const newSelectedObjects = newSelection.objects; const newSelectedObjects = newSelection.objects;
if (!selection || selection.objects !== newSelectedObjects) { if (!selection || selection.objects !== newSelectedObjects) {
const selected = newSelectedObjects.map((object) => object.id); const selected = newSelectedObjects.map((object) => object.id);
@ -167,25 +170,29 @@ class D2Panel extends React.Component {
} }
} }
const dragSelect = (this.state) ? this.state.d2.transform.dragSelect : null; const dragSelect = (this.state.state) ? this.state.state.d2.transform.dragSelect : null;
const newDragSelect = newState.d2.transform.dragSelect; const newDragSelect = state.d2.transform.dragSelect;
if (!dragSelect || dragSelect !== newDragSelect) { if (!dragSelect || dragSelect !== newDragSelect) {
this.activeNeedRender = true; this.activeNeedRender = true;
} }
this.state = newState; this.setState({ state });
} }
resizeHandler = (width, height) => { resizeHandler = (width, height) => {
this.sceneActive.setSize(width, height, PIXEL_RATIO); this.sceneActive.setSize(width, height, PIXEL_RATIO);
this.sceneInactive.setSize(width, height, PIXEL_RATIO); this.sceneInactive.setSize(width, height, PIXEL_RATIO);
this.sceneInactive.x = this.sceneActive.x = Math.round(width / 2 * PIXEL_RATIO); const x = Math.round(width / 2 * PIXEL_RATIO);
this.sceneInactive.y = this.sceneActive.y = Math.round(height / 2 * PIXEL_RATIO); const y = Math.round(height / 2 * PIXEL_RATIO);
const scale = Math.min(width * PIXEL_RATIO / CANVAS_WIDTH, height * PIXEL_RATIO / CANVAS_HEIGHT); const scale = Math.min(width * PIXEL_RATIO / CANVAS_WIDTH, height * PIXEL_RATIO / CANVAS_HEIGHT);
this.sceneInactive.scale = this.sceneActive.scale = scale; const screenMatrix = new CAL.Matrix({ sx: scale, sy: scale, x, y });
this.sceneInactive.copyMatrix(screenMatrix);
this.sceneActive.copyMatrix(screenMatrix);
this.setState({ screenMatrix });
this.inactiveNeedRender = this.activeNeedRender = true; this.inactiveNeedRender = this.activeNeedRender = true;
this.renderRequest(); this.renderRequest();
@ -210,12 +217,14 @@ class D2Panel extends React.Component {
render() { render() {
// debug('this.props.state: ', this.props.state); // debug('this.props.state: ', this.props.state);
const { state, classes } = this.props; const { state, classes } = this.props;
const { screenMatrix } = this.state;
this.update(state); this.update(state);
this.renderCanvas(); this.renderCanvas();
return ( return (
<div className={classes.container}> <div className={classes.container}>
<ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} /> <ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} />
<div className={classes.canvasContainer} ref="canvasContainer" /> <div className={classes.canvasContainer} ref={this.canvasContainer} />
<InputText screenMatrix={screenMatrix} />
</div> </div>
); );
} }

View File

@ -16,11 +16,10 @@ import TwistTransformer from '../d3/transformers/TwistTransformer.js';
import SculptTransformer from '../d3/transformers/SculptTransformer.js'; import SculptTransformer from '../d3/transformers/SculptTransformer.js';
import StampTransformer from '../d3/transformers/StampTransformer.js'; import StampTransformer from '../d3/transformers/StampTransformer.js';
import SelectionBox from '../d3/SelectionBox.js'; import SelectionBox from '../d3/SelectionBox.js';
import RenderChain from '../d3/RenderChain'; import RenderChain, { TOONSHADER_OUTLINE, TOONSHADER } from '../d3/RenderChain';
import BaseTransformer from '../d3/transformers/BaseTransformer.js'; import BaseTransformer from '../d3/transformers/BaseTransformer.js';
import Camera from '../d3/Camera.js'; import Camera from '../d3/Camera.js';
import ReactResizeDetector from 'react-resize-detector'; import ReactResizeDetector from 'react-resize-detector';
import { load as loadMatcapMaterial } from '../d3/MatcapMaterial.js';
// import createDebug from 'debug'; // import createDebug from 'debug';
// const debug = createDebug('d3d:d3'); // const debug = createDebug('d3d:d3');
@ -51,6 +50,10 @@ const styles = {
}; };
class D3Panel extends React.Component { class D3Panel extends React.Component {
constructor(props) {
super(props);
this.canvasContainer = React.createRef();
}
static propTypes = { static propTypes = {
state: PropTypes.object.isRequired, state: PropTypes.object.isRequired,
@ -62,23 +65,23 @@ class D3Panel extends React.Component {
componentWillMount() { componentWillMount() {
this.createScene(); this.createScene();
const toonShader = hasExtensionsFor.toonShaderPreview; const shader = hasExtensionsFor.toonShaderPreview ? TOONSHADER_OUTLINE : TOONSHADER;
this.renderChain = new RenderChain(this.renderer, this.scene, this.camera, toonShader, { this.renderChain = new RenderChain(this.renderer, this.scene, this.camera, shader, {
UI: this.UIContainer, UI: this.UIContainer,
shapes: this.shapesManager, shapes: this.shapesManager,
boundingBox: this.selectionBox, boundingBox: this.selectionBox,
plane: this.plane plane: this.plane
}); });
loadMatcapMaterial.then(this.renderRequest);
this.DOM = null; this.DOM = null;
} }
componentDidMount() { componentDidMount() {
this.container = this.refs.canvasContainer; if (this.canvasContainer.current) {
this.container.appendChild(this.renderer.domElement); this.container = this.canvasContainer.current;
this.container.appendChild(this.renderer.domElement);
this.renderScene(); // immidiatly render because when THREE.JS inits, a black screen is generated this.renderScene(); // immidiatly render because when THREE.JS inits, a black screen is generated
}
} }
componentWillUnmount() { componentWillUnmount() {
@ -223,7 +226,7 @@ class D3Panel extends React.Component {
return ( return (
<div className={classes.container}> <div className={classes.container}>
<ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} /> <ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} />
<div className={classes.canvasContainer} ref="canvasContainer"/> <div className={classes.canvasContainer} ref={this.canvasContainer}/>
</div> </div>
); );
} }

View File

@ -8,7 +8,6 @@ import createScene from '../d3/createScene.js';
import injectSheet from 'react-jss'; import injectSheet from 'react-jss';
import ReactResizeDetector from 'react-resize-detector'; import ReactResizeDetector from 'react-resize-detector';
import requestAnimationFrame from 'raf'; import requestAnimationFrame from 'raf';
import { load as loadMatcapMaterial } from '../d3/MatcapMaterial.js';
import createRAFOnce from '../utils/rafOnce.js'; import createRAFOnce from '../utils/rafOnce.js';
const rafOnce = createRAFOnce(); const rafOnce = createRAFOnce();
@ -29,6 +28,11 @@ class DoodlePreview extends React.Component {
pixelRatio: 1 pixelRatio: 1
}; };
constructor(props) {
super(props);
this.canvas = React.createRef();
}
static propTypes = { static propTypes = {
classes: PropTypes.objectOf(PropTypes.string), classes: PropTypes.objectOf(PropTypes.string),
width: PropTypes.number.isRequired, width: PropTypes.number.isRequired,
@ -37,7 +41,7 @@ class DoodlePreview extends React.Component {
sketchData: PropTypes.object, // TODO sketchData: PropTypes.object, // TODO
docData: PropTypes.shape({ docData: PropTypes.shape({
appVersion: PropTypes.string, appVersion: PropTypes.string,
data: PropTypes.string data: PropTypes.oneOf([PropTypes.string, PropTypes.object])
}) })
}; };
@ -48,19 +52,15 @@ class DoodlePreview extends React.Component {
async componentDidMount() { async componentDidMount() {
let { docData, sketchData } = this.props; let { docData, sketchData } = this.props;
if (docData) sketchData = await JSONToSketchData(this.props.docData); if (docData) sketchData = await JSONToSketchData(docData);
const { canvas } = this.refs; const sceneData = await createSceneData(sketchData);
const sceneData = createSceneData(sketchData); const scene = createScene(sceneData, this.canvas.current);
const scene = createScene(sceneData, canvas);
this.setState(scene); this.setState(scene);
this.editorControls = new THREE.EditorControls(scene.camera, canvas); this.editorControls = new THREE.EditorControls(scene.camera, this.canvas.current);
this.editorControls.addEventListener('change', () => rafOnce(scene.render)); this.editorControls.addEventListener('change', () => rafOnce(scene.render));
loadMatcapMaterial.then(scene.render);
} }
componentWillUnmount() { componentWillUnmount() {
@ -81,7 +81,7 @@ class DoodlePreview extends React.Component {
return ( return (
<div className={classes.container}> <div className={classes.container}>
<ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} /> <ReactResizeDetector handleWidth handleHeight onResize={this.resizeHandler} />
<canvas className={classes.canvas} ref="canvas" /> <canvas className={classes.canvas} ref={this.canvas} />
</div> </div>
); );
} }

106
src/components/InputText.js Normal file
View File

@ -0,0 +1,106 @@
import React from 'react';
import injectSheet from 'react-jss';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as actions from '../actions/index.js';
import * as CAL from '@doodle3d/cal';
import { TEXT_TOOL_FONT_SIZE } from '../constants/d2Constants.js';
const CONTEXT = document.createElement('canvas').getContext('2d');
const styles = {
textInputContainer: {
position: 'absolute',
display: 'flex'
},
textInput: {
position: 'absolute',
fontSize: `${TEXT_TOOL_FONT_SIZE}px`,
background: 'transparent',
border: 'none',
color: 'black',
textFillColor: 'transparent',
outline: 'none'
}
};
class InputText extends React.Component {
constructor(props) {
super(props);
this.text = React.createRef();
}
static propTypes = {
state: PropTypes.object.isRequired,
classes: PropTypes.objectOf(PropTypes.string),
changeText: PropTypes.func.isRequired,
screenMatrix: PropTypes.instanceOf(CAL.Matrix).isRequired
};
onInputChange = () => {
const shapeData = this.getShapeData();
if (!shapeData) return;
const { changeText } = this.props;
const text = this.text.current.value;
changeText(text);
};
getShapeData = () => {
const { state } = this.props;
if (!state.d2.activeShape) return null;
const shapeData = state.objectsById[state.d2.activeShape];
if (shapeData.type !== 'TEXT') return null;
return shapeData;
}
componentWillUpdate() {
if (this.text.current) this.text.current.focus();
}
render() {
const { classes, state, screenMatrix } = this.props;
const shapeData = this.getShapeData();
if (shapeData) {
const { _matrix: m } = shapeData.transform
.multiplyMatrix(state.d2.canvasMatrix)
.multiplyMatrix(screenMatrix);
const { family, style, weight, text } = shapeData.text;
CONTEXT.font = `${style} normal ${weight} ${TEXT_TOOL_FONT_SIZE}px ${family}`;
const width = Math.max(10, CONTEXT.measureText(shapeData.text.text).width);
return (
<div
className={classes.textInputContainer}
style={{ transform: `matrix(${m[0]}, ${m[3]}, ${m[1]}, ${m[4]}, ${m[2]}, ${m[5]})` }}
>
<input
className={classes.textInput}
style={{
fontFamily: family,
fontStyle: style,
fontWeight: weight,
width: `${width}px`
}}
value={text}
ref={this.text}
spellCheck="false"
autoFocus
onChange={this.onInputChange}
/>
</div>
);
}
return null;
}
}
export default injectSheet(styles)(connect(state => ({
state: state.sketcher.present
}), {
changeText: actions.d2textInputChange
})(InputText));

View File

@ -8,11 +8,12 @@ const styles = {
top: '0px', top: '0px',
right: '15%', right: '15%',
width: '19%', width: '19%',
backgroundImage: `url("${doodleSignImageURL}")`,
maxWidth: '290px',
height: '140px',
backgroundSize: '100%',
backgroundRepeat: 'no-repeat',
pointerEvents: 'none', // enable clicking through logo pointerEvents: 'none', // enable clicking through logo
'& img': {
width: '100%',
maxWidth: '290px'
}
}, },
'@media (max-width: 555px)': { '@media (max-width: 555px)': {
container: { container: {
@ -22,8 +23,6 @@ const styles = {
}; };
const Logo = ({ classes }) => ( const Logo = ({ classes }) => (
<div className={classes.container}> <div className={classes.container} />
<img src={doodleSignImageURL} />
</div>
); );
export default injectSheet(styles)(Logo); export default injectSheet(styles)(Logo);

View File

@ -1,7 +1,5 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import initialMenuStructure from '../constants/menu.js';
import { connect } from 'react-redux';
// import createDebug from 'debug'; // import createDebug from 'debug';
// const debug = createDebug('d3d:menu'); // const debug = createDebug('d3d:menu');
@ -14,7 +12,7 @@ class Menu extends React.Component {
value: PropTypes.string, value: PropTypes.string,
className: PropTypes.string, className: PropTypes.string,
children: PropTypes.node, children: PropTypes.node,
stateMenu: PropTypes.object id: PropTypes.string
}; };
onSelect = (event) => { onSelect = (event) => {
const { onSelect, value } = this.props; const { onSelect, value } = this.props;
@ -23,7 +21,7 @@ class Menu extends React.Component {
if (onSelect) onSelect({ ...event, menuValue }); if (onSelect) onSelect({ ...event, menuValue });
}; };
render() { render() {
const { className = '', id, selectedValue, onOpen, onClose, value, children, stateMenu } = this.props; const { className = '', id, selectedValue, onOpen, onClose, children } = this.props;
return ( return (
<ul id={id} className={`menu ${className}`}> <ul id={id} className={`menu ${className}`}>
{React.Children.map(children, (child) => { {React.Children.map(children, (child) => {
@ -39,6 +37,4 @@ class Menu extends React.Component {
} }
} }
export default connect(state => ({ export default Menu;
stateMenu: state.sketcher.present.menus
}))(Menu);

View File

@ -9,6 +9,8 @@ import * as contextTools from '../constants/contextTools.js';
import * as d2Tools from '../constants/d2Tools.js'; import * as d2Tools from '../constants/d2Tools.js';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import injectSheet from 'react-jss'; import injectSheet from 'react-jss';
import { FONT_TOOLS } from '../constants/contextTools.js';
import { FONT_FACE } from '../constants/general.js';
// TODO move this to jss instead of css // TODO move this to jss instead of css
import '../../styles/styles.css'; import '../../styles/styles.css';
// import createDebug from 'debug'; // import createDebug from 'debug';
@ -120,6 +122,7 @@ function renderChildren(children) {
for (const child of children) { for (const child of children) {
let component; let component;
if (child.children.length > 0) { if (child.children.length > 0) {
component = ( component = (
<SubMenu <SubMenu
@ -135,6 +138,18 @@ function renderChildren(children) {
{renderChildren(child.children)} {renderChildren(child.children)}
</SubMenu> </SubMenu>
); );
} else if (FONT_TOOLS.includes(child.value)) {
component = (
<MenuItem
id={child.value}
value={child.value}
key={child.value}
svg={child.svg}
disabled={child.disabled}
>
<p style={{ fontFamily: FONT_FACE[child.value] }}>{FONT_FACE[child.value]}</p>
</MenuItem>
);
} else { } else {
component = ( component = (
<MenuItem <MenuItem
@ -151,7 +166,7 @@ function renderChildren(children) {
return components; return components;
} }
function filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, menus) { function filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, selectionIncludesText, menus) {
const showUnion = activeTool === d2Tools.TRANSFORM && numFilledObjects && numSelectedObjects >= 2; const showUnion = activeTool === d2Tools.TRANSFORM && numFilledObjects && numSelectedObjects >= 2;
const showIntersect = activeTool === d2Tools.TRANSFORM && numSelectedObjects >= 1; const showIntersect = activeTool === d2Tools.TRANSFORM && numSelectedObjects >= 1;
return { return {
@ -191,11 +206,14 @@ function filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidO
case contextTools.HOLE_TOGGLE: case contextTools.HOLE_TOGGLE:
return numSelectedObjects > 0; return numSelectedObjects > 0;
case contextTools.FONT:
return selectionIncludesText || activeTool === d2Tools.TEXT;
default: default:
return true; return true;
} }
}).map(child => { }).map(child => {
return filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, child); return filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, selectionIncludesText, child);
}) })
}; };
} }
@ -216,12 +234,19 @@ const getMenus = createSelector([
state => state.sketcher.present.menus, state => state.sketcher.present.menus,
state => state.sketcher.present.d2.tool, state => state.sketcher.present.d2.tool,
state => state.sketcher.present.selection.objects.length, state => state.sketcher.present.selection.objects.length,
state => state.sketcher.present.selection.objects.filter(({ id }) => state.sketcher.present.objectsById[id].fill).length, state => state.sketcher.present.selection.objects.filter(({ id }) => {
state => state.sketcher.present.selection.objects.filter(({ id }) => state.sketcher.present.objectsById[id].solid).length return state.sketcher.present.objectsById[id].fill;
], (menus, activeTool, numSelectedObjects, numFilledObjects, numSolidObjects) => ({ }).length,
toolbar2d: filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, nestChildren(menus, menus[TOOLBAR2D])), state => state.sketcher.present.selection.objects.filter(({ id }) => {
toolbar3d: filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, nestChildren(menus, menus[TOOLBAR3D])), return state.sketcher.present.objectsById[id].solid;
context: filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidObjects, nestChildren(menus, menus[CONTEXT])) }).length,
state => state.sketcher.present.selection.objects.some(({ id }) => {
return state.sketcher.present.objectsById[id].type === 'TEXT';
})
], (menus, ...args) => ({
toolbar2d: filterMenus(...args, nestChildren(menus, menus[TOOLBAR2D])),
toolbar3d: filterMenus(...args, nestChildren(menus, menus[TOOLBAR3D])),
context: filterMenus(...args, nestChildren(menus, menus[CONTEXT]))
})); }));
export default injectSheet(styles)(connect(getMenus)(SketcherToolbars)); export default injectSheet(styles)(connect(getMenus)(SketcherToolbars));

View File

@ -8,6 +8,11 @@ import { hexToStyle } from '../utils/colorUtils.js';
// const debug = createDebug('d3d:ui:submenu'); // const debug = createDebug('d3d:ui:submenu');
class SubMenu extends React.Component { class SubMenu extends React.Component {
constructor(props) {
super(props);
this.li = React.createRef();
}
static propTypes = { static propTypes = {
onSelect: PropTypes.func, onSelect: PropTypes.func,
onOpen: PropTypes.func, onOpen: PropTypes.func,
@ -61,13 +66,15 @@ class SubMenu extends React.Component {
const { open, onClose, value } = this.props; const { open, onClose, value } = this.props;
if (open && onClose) { if (open && onClose) {
// was click on this submenu? // was click on this submenu?
const onSubmenu = this.refs.li.contains(event.target); const onSubmenu = this.li.current.contains(event.target);
// debug(`onDocumentClick ${event.type} ${onSubmenu ? 'onSubmenu' : ''}`); // debug(`onDocumentClick ${event.type} ${onSubmenu ? 'onSubmenu' : ''}`);
if (!onSubmenu) onClose({ menuValue: value }); if (!onSubmenu) onClose({ menuValue: value });
} }
}; };
render() { render() {
const { id, value, selected, open, selectedValue, children, svg, toggleBehavior, color, solid } = this.props; const {
id, value, selected, open, selectedValue, children, svg, toggleBehavior, color, solid
} = this.props;
const style = {}; const style = {};
if (id === 'color-picker-tool') { if (id === 'color-picker-tool') {
@ -77,7 +84,7 @@ class SubMenu extends React.Component {
let className = 'submenu'; let className = 'submenu';
if (open) className += ' open'; if (open) className += ' open';
return ( return (
<li id={id} className={className} ref="li" style={style}> <li id={id} className={className} ref={this.li} style={style}>
<Button <Button
id={`${selectedValue}-menu`} id={`${selectedValue}-menu`}
value={selectedValue} value={selectedValue}

View File

@ -8,6 +8,7 @@ export const HOLE_TOGGLE = 'hole-toggle-tool';
export const ALIGN = 'align-tool'; export const ALIGN = 'align-tool';
export const UNION = 'union-tool'; export const UNION = 'union-tool';
export const INTERSECT = 'intersect-tool'; export const INTERSECT = 'intersect-tool';
export const FONT = 'font-tool';
export const LIGHT_BLUE_A = 'color-light-blue-a'; export const LIGHT_BLUE_A = 'color-light-blue-a';
export const LIGHT_BLUE_B = 'color-light-blue-b'; export const LIGHT_BLUE_B = 'color-light-blue-b';
@ -79,3 +80,23 @@ export const ALIGN_TOOLS = [
ALIGN_VERTICAL, ALIGN_VERTICAL,
ALIGN_BOTTOM ALIGN_BOTTOM
]; ];
export const OSWALD = 'oswald';
export const RANGA = 'ranga';
export const JOTI_ONE = 'joti-one';
export const BELLEFAIR = 'bellefair';
export const LOBSTER = 'lobster';
export const ABRIL_FATFACE = 'abril-fatface';
export const PLAY = 'play';
export const FASCINATE = 'fascinate';
export const FONT_TOOLS = [
OSWALD,
RANGA,
JOTI_ONE,
BELLEFAIR,
LOBSTER,
ABRIL_FATFACE,
PLAY,
FASCINATE
];

View File

@ -21,13 +21,6 @@ export const SNAPPING_DISTANCE = 7.0;
export const MAX_TRACE_TOLERANCE = 256; export const MAX_TRACE_TOLERANCE = 256;
export const SELECTION_VIEW_MIN_SCALE = 50; export const SELECTION_VIEW_MIN_SCALE = 50;
export const SELECTION_VIEW_MIN_AXIS_SCALE = 80; export const SELECTION_VIEW_MIN_AXIS_SCALE = 80;
export const POTRACE_OPTIONS = {
turnpolicy: 'black',
turdsize: 5.0,
optcurve: false,
alphamax: 0.5,
opttolerance: 0.2
};
export const ERASER_SIZES = { export const ERASER_SIZES = {
[contextTools.ERASER_SIZE_SMALL]: 10, [contextTools.ERASER_SIZE_SMALL]: 10,
[contextTools.ERASER_SIZE_MEDIUM]: 30, [contextTools.ERASER_SIZE_MEDIUM]: 30,
@ -41,3 +34,4 @@ export const BRUSH_SIZES = {
}; };
export const CLIPPER_PRECISION = 100; // accurate to the hundredth export const CLIPPER_PRECISION = 100; // accurate to the hundredth
export const TEXT_TOOL_FONT_SIZE = 40;

View File

@ -1,6 +1,6 @@
import * as contextTools from './contextTools.js'; import * as contextTools from './contextTools.js';
export const VERSION = '0.17.4'; export const VERSION = '0.23.0';
export const SHAPE_CACHE_LIMIT = 50; export const SHAPE_CACHE_LIMIT = 50;
export const PIXEL_RATIO = 1.0; export const PIXEL_RATIO = 1.0;
@ -37,3 +37,14 @@ export const COLOR_STRING_TO_HEX = {
[contextTools.BLACK_B]: 0xAAAAAA, [contextTools.BLACK_B]: 0xAAAAAA,
[contextTools.BLACK_C]: 0x444444 [contextTools.BLACK_C]: 0x444444
}; };
export const FONT_FACE = {
[contextTools.OSWALD]: 'Oswald',
[contextTools.RANGA]: 'Ranga',
[contextTools.JOTI_ONE]: 'Joti One',
[contextTools.BELLEFAIR]: 'Bellefair',
[contextTools.LOBSTER]: 'Lobster',
[contextTools.ABRIL_FATFACE]: 'Abril Fatface',
[contextTools.PLAY]: 'Play',
[contextTools.FASCINATE]: 'Fascinate'
};

Some files were not shown because too many files have changed in this diff Show More