├── .gitignore ├── docs ├── favicon.png ├── global.css ├── index.html ├── build │ ├── bundle.css │ ├── bundle.js │ └── bundle.css.map └── logo.svg ├── public ├── favicon.png ├── global.css ├── index.html └── logo.svg ├── src ├── main.js └── App.svelte ├── package.json ├── README.md └── rollup.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /docs/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lettier/blender-keymap-trainer/HEAD/docs/favicon.png -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lettier/blender-keymap-trainer/HEAD/public/favicon.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: {} 6 | }); 7 | 8 | export default app; 9 | -------------------------------------------------------------------------------- /docs/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | (C) 2020 David Lettier 3 | lettier.com 4 | */ 5 | 6 | html, body { 7 | position: relative; 8 | width: 100%; 9 | height: 100%; 10 | } 11 | 12 | body { 13 | background-color: #2e222f; 14 | color: #333; 15 | margin: 0; 16 | padding: 8px; 17 | box-sizing: border-box; 18 | font-family: Roboto, sans-serif; 19 | font-weight: bold; 20 | } 21 | 22 | .logo-background { 23 | background-size: cover; 24 | background-repeat: no-repeat; 25 | background-image: url('logo-background.svg'); 26 | } 27 | -------------------------------------------------------------------------------- /public/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | (C) 2020 David Lettier 3 | lettier.com 4 | */ 5 | 6 | html, body { 7 | position: relative; 8 | width: 100%; 9 | height: 100%; 10 | } 11 | 12 | body { 13 | background-color: #2e222f; 14 | color: #333; 15 | margin: 0; 16 | padding: 8px; 17 | box-sizing: border-box; 18 | font-family: Roboto, sans-serif; 19 | font-weight: bold; 20 | } 21 | 22 | .logo-background { 23 | background-size: cover; 24 | background-repeat: no-repeat; 25 | background-image: url('logo-background.svg'); 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blender-keymap-trainer", 3 | "author": "David Lettier", 4 | "private": true, 5 | "version": "0.0.0", 6 | "scripts": { 7 | "build": "rollup -c", 8 | "dev": "rollup -c -w", 9 | "start": "sirv public" 10 | }, 11 | "devDependencies": { 12 | "@rollup/plugin-commonjs": "^14.0.0", 13 | "@rollup/plugin-node-resolve": "^8.0.0", 14 | "rollup": "^2.3.4", 15 | "rollup-plugin-livereload": "^1.0.0", 16 | "rollup-plugin-svelte": "^6.0.0", 17 | "rollup-plugin-terser": "^7.0.0", 18 | "svelte": "^3.0.0" 19 | }, 20 | "dependencies": { 21 | "sirv-cli": "^1.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Blender Keymap Trainer 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Blender Keymap Trainer 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Blender Keymap Trainer 3 |

4 | 5 | # Blender Keymap Trainer 6 | 7 | A digital flashcards application for memorizing Blender's shortcut keys or keymap. 8 | Click [here](https://lettier.github.io/blender-keymap-trainer) to use Blender Keymap Trainer. 9 | 10 | ## Features 11 | 12 |

13 | 14 |

15 | 16 | - It remembers your progress and settings. 17 | - You can upload your own keymap. 18 | - Filter the available cards you wish to memorize. 19 | - The cards you miss are more likely to be chosen next. 20 | - You can switch between the key or action side. 21 | - Skip the cards you're not interested in. 22 | 23 | ## Uploading Your Own Keymap 24 | 25 |

26 | 27 |

28 | 29 | From Blender, select `Edit > Preferences > Keymap > Export`. 30 | 31 | Open the exported Python file and replace (located at the bottom) 32 | 33 | ```python 34 | if __name__ == "__main__": 35 | import os 36 | from bl_keymap_utils.io import keyconfig_import_from_data 37 | keyconfig_import_from_data(os.path.splitext(os.path.basename(__file__))[0], keyconfig_data) 38 | ``` 39 | 40 | with the following: 41 | 42 | ```python 43 | if __name__ == "__main__": 44 | import json 45 | with open('./keymap.json', 'w') as file: 46 | file.write(json.dumps(keyconfig_data)) 47 | ``` 48 | 49 | Now run the file with `python exported-file.py`. 50 | 51 |

52 | 53 |

54 | 55 | You can now upload the JSON file from Blender Keymap Trainer. 56 | 57 | ## Filtering 58 | 59 |

60 | 61 |

62 | 63 | You can filter by key/action, section, space, or region. 64 | This allows you to focus only on the node editor keys for example. 65 | 66 | ## Copyright 67 | 68 | (C) 2020 David Lettier 69 |
70 | [lettier.com](https://www.lettier.com) 71 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | 7 | const production = !process.env.ROLLUP_WATCH; 8 | 9 | function serve() { 10 | let server; 11 | 12 | function toExit() { 13 | if (server) server.kill(0); 14 | } 15 | 16 | return { 17 | writeBundle() { 18 | if (server) return; 19 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 20 | stdio: ['ignore', 'inherit', 'inherit'], 21 | shell: true 22 | }); 23 | 24 | process.on('SIGTERM', toExit); 25 | process.on('exit', toExit); 26 | } 27 | }; 28 | } 29 | 30 | export default { 31 | input: 'src/main.js', 32 | output: { 33 | sourcemap: true, 34 | format: 'iife', 35 | name: 'app', 36 | file: 'public/build/bundle.js' 37 | }, 38 | plugins: [ 39 | svelte({ 40 | // enable run-time checks when not in production 41 | dev: !production, 42 | // we'll extract any component CSS out into 43 | // a separate file - better for performance 44 | css: css => { 45 | css.write('bundle.css'); 46 | } 47 | }), 48 | 49 | // If you have external dependencies installed from 50 | // npm, you'll most likely need these plugins. In 51 | // some cases you'll need additional configuration - 52 | // consult the documentation for details: 53 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 54 | resolve({ 55 | browser: true, 56 | dedupe: ['svelte'] 57 | }), 58 | commonjs(), 59 | 60 | // In dev mode, call `npm run start` once 61 | // the bundle has been generated 62 | !production && serve(), 63 | 64 | // Watch the `public` directory and refresh the 65 | // browser on changes when not in production 66 | !production && livereload('public'), 67 | 68 | // If we're building for production (npm run build 69 | // instead of npm run dev), minify 70 | production && terser() 71 | ], 72 | watch: { 73 | clearScreen: false 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /docs/build/bundle.css: -------------------------------------------------------------------------------- 1 | main.svelte-13rm61t{border:0px solid transparent;margin:0px;width:100%;height:100%}input[type="file"].svelte-13rm61t{display:none}.main-container-column.svelte-13rm61t{display:flex;flex-direction:column;align-items:center;align-content:center;justify-content:center;height:100%}.logo.svelte-13rm61t{width:90%}.main-container-row.svelte-13rm61t{width:100%;height:60%;display:flex;flex-direction:row;justify-content:space-between}.card.svelte-13rm61t{width:50%;display:flex;flex-direction:column;perspective:1000px}.card-content-container.svelte-13rm61t{display:flex;flex-direction:row;justify-content:center;align-items:center;height:20vh;cursor:pointer;position:relative;transition:transform 0.5s;transform-style:preserve-3d;margin-top:5px;margin-bottom:5px;height:100%}.card-content.svelte-13rm61t{display:flex;flex-direction:column;align-items:center;justify-content:center;align-self:center;font-size:6vh;position:absolute;height:40%;width:100%;text-align:center;width:100%;height:100%;overflow-y:auto}.card-content-text.svelte-13rm61t{padding:1px}.card-content-front.svelte-13rm61t{background-color:#c7dcd0}.card-content-back.svelte-13rm61t{color:white;background-color:#7f708a}.flip-card.svelte-13rm61t{transform:rotateY(180deg)}.rotated.svelte-13rm61t{transform:rotateY(180deg);z-index:100}.count.svelte-13rm61t{color:white;text-align:center;margin-bottom:5px;color:#625565}.section-title.svelte-13rm61t{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center;align-items:center;background-color:#4d9be6;padding:10px;color:white;font-size:3.2vh;margin-bottom:5px}.breadcrumbs.svelte-13rm61t{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center;align-items:center;background-color:#484a77;padding:10px}.breadcrumb.svelte-13rm61t{color:white;font-size:3vh;margin-left:10px;margin-right:10px}.arrow-right.svelte-13rm61t{width:0;height:0;margin-left:10px;margin-right:10px;border-top:10px solid transparent;border-bottom:10px solid transparent;border-left:10px solid white}.answers.svelte-13rm61t{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-around;align-items:center;height:15%;min-height:4vh}.button.svelte-13rm61t{display:flex;flex-direction:column;justify-content:center;text-align:center;cursor:pointer;color:white;font-size:3vh;padding-left:10px;padding-right:10px;height:100%;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.positive-answer.svelte-13rm61t{background-color:#0eaf9b}.negative-answer.svelte-13rm61t{background-color:#e83b3b}.skip-answer.svelte-13rm61t{background-color:#f04f78;margin-right:5px;margin-left:5px}.controls.svelte-13rm61t{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-around;align-items:center;margin-top:5px;height:15%;min-height:4vh}.reverse-control.svelte-13rm61t{background-color:#fb6b1d}.upload-control.svelte-13rm61t{background-color:#4d65b4;cursor:pointer}.upload-label.svelte-13rm61t{cursor:pointer}.filter-control.svelte-13rm61t{background-color:#905ea9}.delete-control.svelte-13rm61t{background-color:#c32454}.properties.svelte-13rm61t{font-size:2vh}.filtering-container.svelte-13rm61t{display:flex;flex-direction:column;width:50%;height:60%;overflow-y:auto;overflow-x:hidden}.filter-lines-container.svelte-13rm61t{display:flex;flex-direction:column;overflow-y:auto;overflow-x:hidden}.filtering-controls.svelte-13rm61t{margin-top:5px;width:100%}.filter-line.svelte-13rm61t{display:flex;flex-direction:row;justify-content:stretch;width:100%;color:white;padding:5px;margin-bottom:5px}.filter-line-item.svelte-13rm61t{width:25%;padding-left:5px;cursor:pointer}.filter-line-item.svelte-13rm61t:hover{color:#2e222f;background-color:#a884f3}.filter-lines-header.svelte-13rm61t{background-color:#753c54}.filter-line-a.svelte-13rm61t{background-color:#3e3546}.filter-line-b.svelte-13rm61t{background-color:#625565}.done-control.svelte-13rm61t{height:6vh;background-color:#905ea9}.disabled.svelte-13rm61t{cursor:default;background-color:#3e3546;color:#625565}.margin-right.svelte-13rm61t{margin-right:5px}.fade-in.svelte-13rm61t{opacity:1;animation:svelte-13rm61t-fadeIn ease-in-out 1s}.fade-out.svelte-13rm61t{opacity:0;animation:svelte-13rm61t-fadeOut ease-in-out 2s}@keyframes svelte-13rm61t-fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes svelte-13rm61t-fadeOut{0%{opacity:1}60%{opacity:0.9}100%{opacity:0}}@media screen and (max-width: 1280px){.main-container-column.svelte-13rm61t{height:100%;width:100%}.main-container-row.svelte-13rm61t{width:100%;height:80%}.card.svelte-13rm61t{width:85%}.filtering-container.svelte-13rm61t{width:90%;height:90%}.section-title.svelte-13rm61t{font-size:3vw}.breadcrumb.svelte-13rm61t{font-size:2vw}.card-content.svelte-13rm61t{font-size:4vw}.button.svelte-13rm61t{font-size:3vw}}@media screen and (max-width: 600px){.filter-line.svelte-13rm61t{font-size:2.8vw}.section-title.svelte-13rm61t{font-size:4vw}.breadcrumb.svelte-13rm61t{font-size:4vw}.button.svelte-13rm61t{font-size:4.5vw}}@media screen and (max-width: 470px){.button.svelte-13rm61t{font-size:4vw}} 2 | 3 | /*# sourceMappingURL=bundle.css.map */ -------------------------------------------------------------------------------- /docs/build/bundle.js: -------------------------------------------------------------------------------- 1 | var app=function(){"use strict";function e(){}function t(e){return e()}function n(){return Object.create(null)}function l(e){e.forEach(t)}function r(e){return"function"==typeof e}function i(e,t){return e!=e?t==t:e!==t||e&&"object"==typeof e||"function"==typeof e}function c(e,t){e.appendChild(t)}function s(e,t,n){e.insertBefore(t,n||null)}function o(e){e.parentNode.removeChild(e)}function d(e,t){for(let n=0;ne.removeEventListener(t,n,l)}function p(e,t,n){null==n?e.removeAttribute(t):e.getAttribute(t)!==n&&e.setAttribute(t,n)}function v(e,t){t=""+t,e.wholeText!==t&&(e.data=t)}let h;function g(e){h=e}function b(e){(function(){if(!h)throw new Error("Function called outside component initialization");return h})().$$.on_mount.push(e)}const y=[],k=[],$=[],w=[],_=Promise.resolve();let E=!1;function x(e){$.push(e)}let S=!1;const C=new Set;function I(){if(!S){S=!0;do{for(let e=0;e{const l=n.length?n[0]:t;return v.ctx&&a(v.ctx[e],v.ctx[e]=l)&&(!v.skip_bound&&v.bound[e]&&v.bound[e](l),b&&O(i,e)),t}):[],v.update(),b=!0,l(v.before_update),v.fragment=!!d&&d(v.ctx),c.target){if(c.hydrate){const e=function(e){return Array.from(e.childNodes)}(c.target);v.fragment&&v.fragment.l(e),e.forEach(o)}else v.fragment&&v.fragment.c();c.intro&&((y=i.$$.fragment)&&y.i&&(N.delete(y),y.i(k))),function(e,n,i){const{fragment:c,on_mount:s,on_destroy:o,after_update:d}=e.$$;c&&c.m(n,i),x(()=>{const n=s.map(t).filter(r);o?o.push(...n):l(n),e.$$.on_mount=[]}),d.forEach(x)}(i,c.target,c.anchor),I()}var y,k;g(m)}function T(e,t,n){const l=e.slice();return l[31]=t[n],l[33]=n,l}function K(e,t,n){const l=e.slice();return l[34]=t[n],l}function L(e){let t,n;return{c(){t=a("img"),p(t,"id","logo"),p(t,"class","logo fade-out svelte-13rm61t"),t.src!==(n="logo.svg")&&p(t,"src","logo.svg"),p(t,"alt","logo")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function j(e){let t,n,r,i,d,v,h,g,b,y,k,$,w,_,E,x,S,C,I,M,N,O,A,T,K=e[2]&&P(e),L=e[5]&&H(),j=e[6]&&U();return{c(){t=a("div"),n=a("div"),r=f(),i=a("div"),K&&K.c(),d=f(),v=a("div"),h=a("div"),L&&L.c(),g=u(" Reverse"),y=f(),k=a("div"),$=a("label"),w=a("input"),_=u("\n 📂 Upload"),E=f(),x=a("div"),x.textContent="📝 Filter",S=f(),C=a("div"),j&&j.c(),I=u(" Clear"),N=f(),O=a("div"),p(h,"class",b="button reverse-control margin-right "+(e[5]?"":"disabled")+" svelte-13rm61t"),p(w,"type","file"),p(w,"accept","application/json"),p(w,"class","svelte-13rm61t"),p($,"class","upload-label svelte-13rm61t"),p(k,"class","button upload-control margin-right svelte-13rm61t"),p(x,"class","button filter-control margin-right svelte-13rm61t"),p(C,"class",M="button delete-control "+(e[6]?"":"disabled")+" svelte-13rm61t"),p(v,"class","controls svelte-13rm61t"),p(i,"class","card svelte-13rm61t"),p(t,"class","main-container-row fade-in svelte-13rm61t")},m(l,o){s(l,t,o),c(t,n),c(t,r),c(t,i),K&&K.m(i,null),c(i,d),c(i,v),c(v,h),L&&L.m(h,null),c(h,g),c(v,y),c(v,k),c(k,$),c($,w),e[19](w),c($,_),c(v,E),c(v,x),c(v,S),c(v,C),j&&j.m(C,null),c(C,I),c(t,N),c(t,O),A||(T=[m(h,"click",e[18]),m(w,"change",e[20]),m(x,"click",e[21]),m(C,"click",e[22])],A=!0)},p(e,t){e[2]?K?K.p(e,t):(K=P(e),K.c(),K.m(i,d)):K&&(K.d(1),K=null),e[5]?L||(L=H(),L.c(),L.m(h,g)):L&&(L.d(1),L=null),32&t[0]&&b!==(b="button reverse-control margin-right "+(e[5]?"":"disabled")+" svelte-13rm61t")&&p(h,"class",b),e[6]?j||(j=U(),j.c(),j.m(C,I)):j&&(j.d(1),j=null),64&t[0]&&M!==(M="button delete-control "+(e[6]?"":"disabled")+" svelte-13rm61t")&&p(C,"class",M)},d(n){n&&o(t),K&&K.d(),L&&L.d(),e[19](null),j&&j.d(),A=!1,l(T)}}}function P(e){let t,n,r,i,d,h,g,b,y,k,$,w,_,E,x,S,C,I,M,N,O,A,T,K,L,j,P,R,Y,G,H,U=e[3]+1+"",Q=e[2].section.title+"",V=e[2].section.region+"",W="EMPTY"!==e[2].section.space&&F(e),X=(!e[5]&&!e[7]||e[5]&&e[7])&&J(e),Z=(e[5]||e[7])&&B(e),ee=e[5]&&q(),te=!e[5]&&z(),ne=e[5]&&D();return{c(){t=a("div"),n=u(U),r=u(" / "),i=u(e[1]),d=f(),h=a("div"),g=u(Q),b=f(),y=a("div"),k=a("div"),$=u(V),w=f(),W&&W.c(),_=f(),E=a("div"),X&&X.c(),x=f(),Z&&Z.c(),C=f(),I=a("div"),M=a("div"),ee&&ee.c(),N=u(" Got it!"),A=f(),T=a("div"),te&&te.c(),K=u(" Skip"),j=f(),P=a("div"),ne&&ne.c(),R=u(" Missed it!"),p(t,"class","count svelte-13rm61t"),p(h,"class","section-title svelte-13rm61t"),p(k,"class","breadcrumb svelte-13rm61t"),p(y,"class","breadcrumbs svelte-13rm61t"),p(E,"class",S="card-content-container "+(e[5]?"flip-card":"")+" svelte-13rm61t"),p(M,"class",O="button positive-answer "+(e[5]?"":"disabled")+" svelte-13rm61t"),p(T,"class",L="button skip-answer "+(e[5]?"disabled":"")+" svelte-13rm61t"),p(P,"class",Y="button negative-answer "+(e[5]?"":"disabled")+" svelte-13rm61t"),p(I,"class","answers svelte-13rm61t")},m(l,o){s(l,t,o),c(t,n),c(t,r),c(t,i),s(l,d,o),s(l,h,o),c(h,g),s(l,b,o),s(l,y,o),c(y,k),c(k,$),c(y,w),W&&W.m(y,null),s(l,_,o),s(l,E,o),X&&X.m(E,null),c(E,x),Z&&Z.m(E,null),s(l,C,o),s(l,I,o),c(I,M),ee&&ee.m(M,null),c(M,N),c(I,A),c(I,T),te&&te.m(T,null),c(T,K),c(I,j),c(I,P),ne&&ne.m(P,null),c(P,R),G||(H=[m(E,"click",e[14]),m(M,"click",e[15]),m(T,"click",e[16]),m(P,"click",e[17])],G=!0)},p(e,t){8&t[0]&&U!==(U=e[3]+1+"")&&v(n,U),2&t[0]&&v(i,e[1]),4&t[0]&&Q!==(Q=e[2].section.title+"")&&v(g,Q),4&t[0]&&V!==(V=e[2].section.region+"")&&v($,V),"EMPTY"!==e[2].section.space?W?W.p(e,t):(W=F(e),W.c(),W.m(y,null)):W&&(W.d(1),W=null),!e[5]&&!e[7]||e[5]&&e[7]?X?X.p(e,t):(X=J(e),X.c(),X.m(E,x)):X&&(X.d(1),X=null),e[5]||e[7]?Z?Z.p(e,t):(Z=B(e),Z.c(),Z.m(E,null)):Z&&(Z.d(1),Z=null),32&t[0]&&S!==(S="card-content-container "+(e[5]?"flip-card":"")+" svelte-13rm61t")&&p(E,"class",S),e[5]?ee||(ee=q(),ee.c(),ee.m(M,N)):ee&&(ee.d(1),ee=null),32&t[0]&&O!==(O="button positive-answer "+(e[5]?"":"disabled")+" svelte-13rm61t")&&p(M,"class",O),e[5]?te&&(te.d(1),te=null):te||(te=z(),te.c(),te.m(T,K)),32&t[0]&&L!==(L="button skip-answer "+(e[5]?"disabled":"")+" svelte-13rm61t")&&p(T,"class",L),e[5]?ne||(ne=D(),ne.c(),ne.m(P,R)):ne&&(ne.d(1),ne=null),32&t[0]&&Y!==(Y="button negative-answer "+(e[5]?"":"disabled")+" svelte-13rm61t")&&p(P,"class",Y)},d(e){e&&o(t),e&&o(d),e&&o(h),e&&o(b),e&&o(y),W&&W.d(),e&&o(_),e&&o(E),X&&X.d(),Z&&Z.d(),e&&o(C),e&&o(I),ee&&ee.d(),te&&te.d(),ne&&ne.d(),G=!1,l(H)}}}function F(e){let t,n,l,r,i=e[2].section.space+"";return{c(){t=a("div"),n=f(),l=a("div"),r=u(i),p(t,"class","breadcrumb arrow-right svelte-13rm61t"),p(l,"class","breadcrumb svelte-13rm61t")},m(e,i){s(e,t,i),s(e,n,i),s(e,l,i),c(l,r)},p(e,t){4&t[0]&&i!==(i=e[2].section.space+"")&&v(r,i)},d(e){e&&o(t),e&&o(n),e&&o(l)}}}function J(e){let t,n,l,r,i,d,m=e[2].key+"",h=e[2].ctrl&&R(),g=e[2].shift&&Y();return{c(){t=a("div"),n=a("div"),h&&h.c(),l=f(),g&&g.c(),r=f(),i=u(m),p(n,"class","card-content-text svelte-13rm61t"),p(t,"class",d="card-content card-content-front "+(e[7]?"rotated":"")+" svelte-13rm61t")},m(e,o){s(e,t,o),c(t,n),h&&h.m(n,null),c(n,l),g&&g.m(n,null),c(n,r),c(n,i)},p(e,c){e[2].ctrl?h||(h=R(),h.c(),h.m(n,l)):h&&(h.d(1),h=null),e[2].shift?g||(g=Y(),g.c(),g.m(n,r)):g&&(g.d(1),g=null),4&c[0]&&m!==(m=e[2].key+"")&&v(i,m),128&c[0]&&d!==(d="card-content card-content-front "+(e[7]?"rotated":"")+" svelte-13rm61t")&&p(t,"class",d)},d(e){e&&o(t),h&&h.d(),g&&g.d()}}}function R(e){let t;return{c(){t=u("Ctrl +")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function Y(e){let t;return{c(){t=u("Shift +")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function B(e){let t,n,l,r,i,m,h=e[2].action+"",g=e[2].properties,b=[];for(let t=0;t0&&Z();return{c(){t=a("div"),n=a("div"),l=u(e[1]),r=f(),i=a("div");for(let e=0;e0?x||(x=Z(),x.c(),x.m(b,y)):x&&(x.d(1),x=null),2&t[0]&&k!==(k="button done-control "+(e[1]<=0?"disabled":"")+" svelte-13rm61t")&&p(b,"class",k)},d(e){e&&o(t),d(E,e),x&&x.d(),$=!1,w()}}}function V(e){let t;return{c(){t=u("Ctrl +")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function W(e){let t;return{c(){t=u("Shift +")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function X(e){let t,n,r,i,d,h,g,b,y,k,$,w,_,E,x,S,C,I,M,N,O,A,T,K=e[31].key+"",L=e[31].action+"",j=e[31].section.title+"",P=e[31].section.space+"",F=e[31].section.region+"",J=0===e[33]&&function(e){let t;return{c(){t=a("div"),t.innerHTML='
KEY ACTION
\n
SECTION
\n
SPACE
\n
REGION
',p(t,"class","filter-line filter-lines-header svelte-13rm61t")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}(),R=e[31].ctrl&&V(),Y=e[31].shift&&W();function B(...t){return e[23](e[31],...t)}function G(...t){return e[24](e[31],...t)}function q(...t){return e[25](e[31],...t)}function z(...t){return e[26](e[31],...t)}return{c(){J&&J.c(),t=f(),n=a("div"),r=a("div"),R&&R.c(),i=f(),Y&&Y.c(),d=f(),h=u(K),g=f(),b=a("br"),y=f(),k=u(L),$=f(),w=a("div"),_=u(j),E=f(),x=a("div"),S=u(P),C=f(),I=a("div"),M=u(F),N=f(),p(r,"class","filter-line-item svelte-13rm61t"),p(w,"class","filter-line-item svelte-13rm61t"),p(x,"class","filter-line-item svelte-13rm61t"),p(I,"class","filter-line-item svelte-13rm61t"),p(n,"class",O="filter-line "+(e[31].hidden?"disabled":"")+" "+(e[33]%2==0?"filter-line-a":"filter-line-b")+" svelte-13rm61t")},m(e,l){J&&J.m(e,l),s(e,t,l),s(e,n,l),c(n,r),R&&R.m(r,null),c(r,i),Y&&Y.m(r,null),c(r,d),c(r,h),c(r,g),c(r,b),c(r,y),c(r,k),c(n,$),c(n,w),c(w,_),c(n,E),c(n,x),c(x,S),c(n,C),c(n,I),c(I,M),c(n,N),A||(T=[m(r,"click",B),m(w,"click",G),m(x,"click",q),m(I,"click",z)],A=!0)},p(t,l){(e=t)[31].ctrl?R||(R=V(),R.c(),R.m(r,i)):R&&(R.d(1),R=null),e[31].shift?Y||(Y=W(),Y.c(),Y.m(r,d)):Y&&(Y.d(1),Y=null),16&l[0]&&K!==(K=e[31].key+"")&&v(h,K),16&l[0]&&L!==(L=e[31].action+"")&&v(k,L),16&l[0]&&j!==(j=e[31].section.title+"")&&v(_,j),16&l[0]&&P!==(P=e[31].section.space+"")&&v(S,P),16&l[0]&&F!==(F=e[31].section.region+"")&&v(M,F),16&l[0]&&O!==(O="filter-line "+(e[31].hidden?"disabled":"")+" "+(e[33]%2==0?"filter-line-a":"filter-line-b")+" svelte-13rm61t")&&p(n,"class",O)},d(e){J&&J.d(e),e&&o(t),e&&o(n),R&&R.d(),Y&&Y.d(),A=!1,l(T)}}}function Z(e){let t;return{c(){t=u("📝")},m(e,n){s(e,t,n)},d(e){e&&o(t)}}}function ee(t){let n,l,r,i,d,u=!t[0]&&L(),m=t[0]&&t[4].length>0&&!t[8]&&j(t),v=t[0]&&t[4].length&&t[8]&&Q(t);return{c(){n=a("main"),l=a("div"),u&&u.c(),r=f(),m&&m.c(),i=f(),v&&v.c(),p(l,"class",d="main-container-column "+(t[0]?"logo-background fade-in":"")+" svelte-13rm61t"),p(n,"class","svelte-13rm61t")},m(e,t){s(e,n,t),c(n,l),u&&u.m(l,null),c(l,r),m&&m.m(l,null),c(l,i),v&&v.m(l,null)},p(e,t){e[0]?u&&(u.d(1),u=null):u||(u=L(),u.c(),u.m(l,r)),e[0]&&e[4].length>0&&!e[8]?m?m.p(e,t):(m=j(e),m.c(),m.m(l,i)):m&&(m.d(1),m=null),e[0]&&e[4].length&&e[8]?v?v.p(e,t):(v=Q(e),v.c(),v.m(l,null)):v&&(v.d(1),v=null),1&t[0]&&d!==(d="main-container-column "+(e[0]?"logo-background fade-in":"")+" svelte-13rm61t")&&p(l,"class",d)},i:e,o:e,d(e){e&&o(n),u&&u.d(),m&&m.d(),v&&v.d()}}}function te(e,t,n){let l,r=!1,i=0,c=null,s=0,o=[],d=!1,a=!1,u=!1,f=!1;function m(){n(1,i=o.reduce((e,t)=>t.hidden?e:e+1,0)),i<=0&&n(8,f=!0)}function p(){m();let e=0;n(3,s=0);for(let t=0;t{let n={};n.title=e[0],n.space=e[1].space_type.replace(/_/g," "),n.region=e[1].region_type.replace(/_/g," "),e[2].items.forEach(e=>{if(e[1]&&e[1].value&&("press"===e[1].value.toLowerCase()||"click"===e[1].value.toLowerCase())){let l={},r=e[0];r=r.split("."),r[1]?(r[0]=`(${r[0]})`,r[1]=r[1].replace(/_/g," "),l.action=`${r[0]} ${r[1]}`):l.action=r[0].replace(/_/g," "),l.key=e[1].type.replace(/_/g," "),l.ctrl=!!e[1].ctrl,l.shift=!!e[1].shift,l.properties=[],e[2]&&e[2].properties&&e[2].properties.length>0&&e[2].properties.forEach(e=>{if(""===e[1])return;let t=String(e[0]).replace(/_/g," "),n=String(e[1]).replace(/_/g," ").replace(/\./g," ");l.properties.push(`${t}: ${n}`)}),l.section=n,l.passed=0,l.failed=0,l.hidden=!1,l.id=t.length,t.push(l)}})}),n(4,o=t),n(3,s=Math.floor(Math.random()*o.length)),n(2,c=o[s])}function h(e,t){if(1==e?n(2,c.passed+=1,c):-1==e&&n(2,c.failed+=1,c),m(),1===i)for(let e=0;e1){if(t){let e=c.id;for(;;){e+=1,e>=o.length&&(e=0);let t=o[e];if(!t.hidden&&t.id!==c.id){n(2,c=t);break}}}else{let e=o.reduce((e,t)=>(t.hidden||t.id===c.id||e.push(t),e),[]),t=e.reduce((e,t)=>{if(t.hidden)return e;let n=t.failed-t.passed;return n<0&&(n=0),e+n+1},0),l=Math.floor(Math.random()*(t+1)),r=0;for(let t=0;t{try{v(JSON.parse(t.result)),p(),g(!0),window.alert("Keymap uploaded.")}catch{window.alert("Could not process upload.")}}}function $(e,t){if("key"===e)t.hidden=!t.hidden,t=t;else if("section.title"===e){let e=!t.hidden;o.forEach(n=>{n.section.title===t.section.title&&(n.hidden=e,n=n)})}else if("section.region"===e){let e=!t.hidden;o.forEach(n=>{n.section.region===t.section.region&&(n.hidden=e,n=n)})}else if("section.space"===e){let e=!t.hidden;o.forEach(n=>{n.section.space===t.section.space&&(n.hidden=e,n=n)})}n(4,o),h(0,!1)}b(async()=>{let e=document.getElementById("logo"),t=()=>{n(0,r=!0)};e.addEventListener("animationend",t),e.addEventListener("webkitAnimationend",t);let l=window.localStorage.getItem("blender-keymap-trainer");try{l=JSON.parse(l)}catch{l=null}if(l&&l.currentKey&&l.keymap)n(4,o=l.keymap),n(2,c=l.currentKey),n(3,s=l.currentKeyIndex),n(7,u=!0===l.reverse),c.hidden&&h(0,!1),n(6,a=!0);else{const e=await fetch("keymap.json");v(await e.json())}p()});return[r,i,c,s,o,d,a,u,f,l,h,g,y,$,()=>n(5,d=!d),()=>{d&&h(1,!1)},()=>{d||h(0,!0)},()=>{d&&h(-1,!1)},()=>{d&&n(7,u=!u)},function(e){k[e?"unshift":"push"](()=>{l=e,n(9,l)})},()=>y(),()=>n(8,f=!0),()=>{a&&g(!1)},e=>$("key",e),e=>$("section.title",e),e=>$("section.space",e),e=>$("section.region",e),()=>{i>0&&(n(8,f=!1),h(0,!1))}]}return new class extends class{$destroy(){!function(e,t){const n=e.$$;null!==n.fragment&&(l(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}(this,1),this.$destroy=e}$on(e,t){const n=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return n.push(t),()=>{const e=n.indexOf(t);-1!==e&&n.splice(e,1)}}$set(e){var t;this.$$set&&(t=e,0!==Object.keys(t).length)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}{constructor(e){super(),A(this,e,te,ee,i,{},[-1,-1])}}({target:document.body,props:{}})}(); 2 | //# sourceMappingURL=bundle.js.map 3 | -------------------------------------------------------------------------------- /src/App.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 302 | 303 |
304 |
305 | {#if !show} 306 | 307 | {/if} 308 | {#if show && keymap.length > 0 && !filtering} 309 |
310 |
311 |
312 | {#if currentKey} 313 |
314 | {currentKeyIndex + 1} / {totalVisibleKeys} 315 |
316 |
317 | {currentKey.section.title} 318 |
319 | 331 |
332 | {#if (!flip && !reverse) || (flip && reverse)} 333 |
334 |
335 | {#if currentKey.ctrl} 336 | Ctrl + 337 | {/if} 338 | {#if currentKey.shift} 339 | Shift + 340 | {/if} 341 | {currentKey.key} 342 |
343 |
344 | {/if} 345 | {#if flip || reverse} 346 |
347 |
348 |
349 | {currentKey.action} 350 |
351 | {#each currentKey.properties as property} 352 |
353 | {property} 354 |
355 | {/each} 356 |
357 |
358 | {/if} 359 |
360 |
361 |
363 | {#if flip}👏{/if} Got it! 364 |
365 |
366 | {#if !flip}💤{/if} Skip 367 |
368 |
370 | {#if flip}🤕{/if} Missed it! 371 |
372 |
373 | {/if} 374 |
375 |
377 | {#if flip}➰{/if} Reverse 378 |
379 |
380 | 384 |
385 |
386 | 📝 Filter 387 |
388 |
390 | {#if dataSaved}🗑{/if} Clear 391 |
392 |
393 |
394 |
395 |
396 | {/if} 397 | {#if show && keymap.length && filtering} 398 |
399 |
400 | {totalVisibleKeys} 401 |
402 |
403 | {#each keymap as key, i} 404 | {#if i === 0} 405 |
406 |
407 | KEY ACTION 408 |
409 |
410 | SECTION 411 |
412 |
413 | SPACE 414 |
415 |
416 | REGION 417 |
418 |
419 | {/if} 420 |
421 |
422 | {#if key.ctrl} 423 | Ctrl + 424 | {/if} 425 | {#if key.shift} 426 | Shift + 427 | {/if} 428 | {key.key} 429 |
430 | {key.action} 431 |
432 |
433 | {key.section.title} 434 |
435 |
436 | {key.section.space} 437 |
438 |
439 | {key.section.region} 440 |
441 |
442 | {/each} 443 |
444 |
445 |
447 | {#if totalVisibleKeys > 0}📝{/if} Done 448 |
449 |
450 |
451 | {/if} 452 |
453 |
454 | 455 | 834 | -------------------------------------------------------------------------------- /docs/build/bundle.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "file": "bundle.css", 4 | "sources": [ 5 | "App.svelte" 6 | ], 7 | "sourcesContent": [ 8 | "\n\n\n\n
\n
\n {#if !show}\n \n {/if}\n {#if show && keymap.length > 0 && !filtering}\n
\n
\n
\n {#if currentKey}\n
\n {currentKeyIndex + 1} / {totalVisibleKeys}\n
\n
\n {currentKey.section.title}\n
\n
\n
\n {currentKey.section.region}\n
\n {#if currentKey.section.space !== \"EMPTY\"}\n
\n
\n
\n {currentKey.section.space}\n
\n {/if}\n
\n
flip = !flip}\">\n {#if (!flip && !reverse) || (flip && reverse)}\n
\n
\n {#if currentKey.ctrl}\n Ctrl +\n {/if}\n {#if currentKey.shift}\n Shift +\n {/if}\n {currentKey.key}\n
\n
\n {/if}\n {#if flip || reverse}\n
\n
\n
\n {currentKey.action}\n
\n {#each currentKey.properties as property}\n
\n {property}\n
\n {/each}\n
\n
\n {/if}\n
\n
\n
{ if (flip) nextKey(1, false); }}\">\n {#if flip}👏{/if} Got it!\n
\n
{ if (!flip) nextKey(0, true); } }\">\n {#if !flip}💤{/if} Skip\n
\n
{ if (flip) nextKey(-1, false); }}\">\n {#if flip}🤕{/if} Missed it!\n
\n
\n {/if}\n
\n
{ if (flip) reverse = !reverse } }\">\n {#if flip}➰{/if} Reverse\n
\n
\n \n
\n
filtering = true }\">\n 📝 Filter\n
\n
{ if (dataSaved) clearData(false); } }\">\n {#if dataSaved}🗑{/if} Clear\n
\n
\n
\n
\n
\n {/if}\n {#if show && keymap.length && filtering}\n
\n
\n {totalVisibleKeys}\n
\n
\n {#each keymap as key, i}\n {#if i === 0}\n
\n
\n KEY ACTION\n
\n
\n SECTION\n
\n
\n SPACE\n
\n
\n REGION\n
\n
\n {/if}\n
\n
updateHidden('key', key) }\">\n {#if key.ctrl}\n Ctrl +\n {/if}\n {#if key.shift}\n Shift +\n {/if}\n {key.key}\n
\n {key.action}\n
\n
updateHidden('section.title', key) }\">\n {key.section.title}\n
\n
updateHidden('section.space', key) }\">\n {key.section.space}\n
\n
updateHidden('section.region', key) }\">\n {key.section.region}\n
\n
\n {/each}\n
\n
\n
{ if (totalVisibleKeys > 0) { filtering = false; nextKey(0, false); } } }\">\n {#if totalVisibleKeys > 0}📝{/if} Done\n
\n
\n
\n {/if}\n
\n
\n\n\n" 9 | ], 10 | "names": [], 11 | "mappings": "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" 12 | } -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | David Lettier 12 | 13 | 14 | 15 | 16 | (C) 2020 David Lettier 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | David Lettier 12 | 13 | 14 | 15 | 16 | (C) 2020 David Lettier 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------