Add files via upload

This commit is contained in:
JannisX11 2017-10-26 19:00:52 +02:00 committed by GitHub
parent c157504ab7
commit 6c3b305cc5
67 changed files with 63816 additions and 0 deletions

BIN
assets/armor_stand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
assets/brush.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

BIN
assets/hud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/inventory_full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

BIN
assets/inventory_nine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

BIN
assets/item_frame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

BIN
assets/missing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

BIN
assets/north.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
assets/player_skin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
assets/zombie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
build/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
build/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

BIN
build/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

5
css/font-awesome.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
css/jquery-ui.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1888
css/style.css Normal file

File diff suppressed because it is too large Load Diff

210
css/w3.css Normal file
View File

@ -0,0 +1,210 @@
/* W3.CSS 4.04 Apr 2017 by Jan Egil and Borge Refsnes */
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
a{background-color:transparent;-webkit-text-decoration-skip:objects}
a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
dfn{font-style:italic}mark{background:#ff0;color:#000}
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}svg:not(:root){overflow:hidden}
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold}
button,input{overflow:visible}button,select{text-transform:none}
button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}
button::-moz-focus-inner, [type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner{border-style:none;padding:0}
button:-moz-focusring, [type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring{outline:1px dotted ButtonText}
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
[type=checkbox],[type=radio]{padding:0}
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}
::-webkit-input-placeholder{color:inherit;opacity:0.54}
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
/* End extract */
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}.w3-serif{font-family:serif}
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
hr{border:0;border-top:1px solid #eee;margin:20px 0}
.w3-image{max-width:100%;height:auto}img{margin-bottom:-5px}a{color:inherit}
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
.w3-btn,.w3-button{border:none;display:inline-block;outline:0;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
.w3-dropdown-hover:hover .w3-dropdown-content{display:block;z-index:1}
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0}
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
.w3-main,#main{transition:margin-left .4s}
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;outline:none;display:block}
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
.w3-bar .w3-button{white-space:normal}
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;outline:none;white-space:normal;float:none}
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
.w3-responsive{overflow-x:auto}
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
.w3-content{max-width:980px;margin:auto}.w3-rest{overflow:hidden}
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}}
.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
.w3-display-position{position:absolute}
.w3-circle{border-radius:50%}
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
.w3-left{float:left!important}.w3-right{float:right!important}
.w3-button:hover{color:#000!important;background-color:#ccc!important}
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
.w3-hover-none:hover{box-shadow:none!important}
/* Colors */
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#bbb!important}
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#ffeb3b!important}
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
.w3-text-amber{color:#ffc107!important}
.w3-text-aqua{color:#00ffff!important}
.w3-text-light-blue{color:#87CEEB!important}
.w3-text-brown{color:#795548!important}
.w3-text-cyan{color:#00bcd4!important}
.w3-text-blue-grey,.w3-text-blue-gray{color:#607d8b!important}
.w3-text-light-green{color:#8bc34a!important}
.w3-text-indigo{color:#3f51b5!important}
.w3-text-khaki{color:#b4aa50!important}
.w3-text-lime{color:#cddc39!important}
.w3-text-orange{color:#ff9800!important}
.w3-text-deep-orange{color:#ff5722!important}
.w3-text-pink{color:#e91e63!important}
.w3-text-purple{color:#9c27b0!important}
.w3-text-deep-purple{color:#673ab7!important}
.w3-text-sand{color:#fdf5e6!important}
.w3-text-teal{color:#009688!important}
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#bbb!important}

BIN
favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
font/FontAwesome.otf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
font/Montserrat-Regular.ttf Normal file

Binary file not shown.

Binary file not shown.

2671
font/fontawesome-webfont.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
font/icomoon.eot Normal file

Binary file not shown.

21
font/icomoon.svg Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="x11" d="M95.492 339.172h244.617v-354.968h-244.617v354.968zM391.492 205.172h244.617v-217.789h-244.617v217.789zM683.492 870.048h244.617v-883.876h-244.617v883.876z" />
<glyph unicode="&#xe901;" glyph-name="baby_zombie" d="M357.625 933.25l-14-483.375 130.125-14-5.25-12.125c-141.25 9.173-231.492 14.842-271.25 17.25-21.675 1.313-32.936 1.94-38.875 2.25-2.97 0.155-4.531 0.208-5.625 0.25s-4.875 0-4.875 0l-32-2.5-0.625-157.375 344.25-24.875 2.875-284.375h228.5l12.25 443.875h168.125l14 511.375z" />
<glyph unicode="&#xe902;" glyph-name="armor_stand" d="M455.514 567.482h104.385v161.959l2.821 105.862-107.206-0.905zM264.723 486.552h476.677l-5.309 86.908c-142.18-0.098-314.246-0.196-471.368-0.294zM350.114-41.974h105.841v329.148l2.861 215.141-108.702-1.839zM559.398-41.993h105.88v324.041l2.861 211.803-108.742-1.81zM861.295-4.873l82.656 23.311-81.12 329.569-50.789 216.047-84.437-25.782zM63.46 11.515l84.107-17.365 79.735 329.907 54.391 215.168-86.825 15.991zM259.066-59.334h476.677l-5.309 86.908c-142.18-0.096-314.246-0.198-471.368-0.294z" />
<glyph unicode="&#xe903;" glyph-name="armor_stand_small" d="M479.778 452.094h82.515v189.025l2.23 123.553-84.745-1.056zM327.961 371.667h378.741l-4.218 94.8c-112.968-0.107-249.682-0.214-374.523-0.321zM381.959 57.137h97.532v206.337l2.636 134.868-100.168-1.153zM562.27 57.213h93.76v203.030l2.534 132.707-96.294-1.134zM836.627 10.238l86.879 19.613-85.264 277.283-53.383 181.771-88.751-21.692zM97.998 23.838l93.728-14.563 88.856 276.676 60.613 180.451-96.757 13.411zM323.191 1.42h379.279l-4.224 71.322c-113.129-0.077-250.037-0.16-375.056-0.243z" />
<glyph unicode="&#xe904;" glyph-name="ground" d="M501.5 550.875c-33.116-2.315-53.035-4.943-95.25-29.25-15.568-8.964-30.113-23.073-47.25-41.625s-35.618-41.233-52.75-65.625c-34.264-48.785-65.701-100.914-64-150.875 0.844-24.773 12.521-46.84 29-62.875s37.425-27.263 60.5-35.875c50.816-14.145 52.303-18.359 147.125-24.25l0.625-0.128c25.804-0.64 42.145-1.3 80.25-2.125 78.857 1.225 134.386 16.463 172.875 39s60.511 49.945 62.75 80.625c2.101 28.792-10.411 55.18-26.25 85.878s-36.78 63.148-58 91.25l-0.75 1-0.75 0.875c-36.096 39.749-68.488 93.859-135.125 110.875-19.978 5.102-38.802 5.516-73 3.125zM74.5 84.875c0-33.292 0-66.583 0-99.875h860.75v99.875z" />
<glyph unicode="&#xe905;" glyph-name="hud" d="M8.75 177.75v-188.125h1012v188.125zM43 143.5h943.625v-119.625h-943.625zM10.75 323v-74.375h473.625v74.375zM520.5 322v-73.125h499.25v73.125zM9 409.625c0-22.333 0-44.667 0-67h473.25v67zM7.5 232.875v-42.25h1012.625v42.25z" />
<glyph unicode="&#xe906;" glyph-name="inventory_full" d="M756.75 725.625v-108.5h105.75v108.5zM781.125 701.25h57v-59.75h-57zM89.125 164.125v-32h842.875v32zM182 884.875v-432.625h32v432.625zM517.125 759.625v-173.625h179.125v173.625zM541.5 735.25h130.375v-124.875h-130.375zM380.25 922.75c0-165.042 0-330.083 0-495.125h587.625v495.125zM437.875 865.25h472.375v-380h-472.375zM47.625 920.75v-493.125h390.25v493.125zM105.125 863.25h275.125v-378h-275.125zM47.625 485.25v-493.25h920.25v493.25zM105.125 427.625h805.125v-378h-805.125z" />
<glyph unicode="&#xe907;" glyph-name="inventory_nine" d="M376.25 308.25h293.5v284.125c-349.612 19.848-293.5 0.814-293.5-284.125zM365.125 907.625l7.5-900.125 306.875 2.625-7.375 886.375-16.5 0.625zM399.75 872l238.125-8.75 6.875-819-238-2zM90 598.375l-0.75-16.5-12.875-293h891.875v309.5zM122.875 563.875h811v-240.625h-821.625zM67.625 910.375v-915.25h910.125v915.25zM123.625 854.375h798.125v-803.25h-798.125z" />
<glyph unicode="&#xe908;" glyph-name="inventory_single" d="M86.75 887.25v-873h875.75v873zM164.5 809.5h720.375v-717.5h-720.375z" />
<glyph unicode="&#xe909;" glyph-name="player_head" d="M146 216.25l-91.625-282.875 912.5-2.003-71.25 284.875zM302.625 646l-15.875-414.625h28.5l469.625 0.625-11.875 414zM355.25 591.25h364.625l8.75-304.5-385-0.627z" />
<glyph unicode="&#xe90a;" glyph-name="zombie" d="M428.375 922.875l-8.5-404.75 81.625-4.125-5.625-14.25c-289.841 20.179-359.5 23.25-359.5 23.25l-37.875-0.875-0.75-169.25 409.375-32.375-3.125-375h212l34.5 552.25 109.125 3.375 12.125 417.375z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
font/icomoon.ttf Normal file

Binary file not shown.

BIN
font/icomoon.woff Normal file

Binary file not shown.

BIN
icon.icns Normal file

Binary file not shown.

BIN
icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

1142
index.php Normal file

File diff suppressed because it is too large Load Diff

552
js/JSONLoader.js Normal file
View File

@ -0,0 +1,552 @@
import { Loader } from './Loader';
import { AnimationClip } from '../animation/AnimationClip';
import { Vector3 } from '../math/Vector3';
import { Vector4 } from '../math/Vector4';
import { Color } from '../math/Color';
import { Vector2 } from '../math/Vector2';
import { Face3 } from '../core/Face3';
import { Geometry } from '../core/Geometry';
import { FileLoader } from './FileLoader';
import { DefaultLoadingManager } from './LoadingManager';
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*/
function JSONLoader( manager ) {
if ( typeof manager === 'boolean' ) {
console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
manager = undefined;
}
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
this.withCredentials = false;
}
Object.assign( JSONLoader.prototype, {
load: function( url, onLoad, onProgress, onError ) {
var scope = this;
var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : Loader.prototype.extractUrlBase( url );
var loader = new FileLoader( this.manager );
loader.setWithCredentials( this.withCredentials );
loader.load( url, function ( text ) {
var json = JSON.parse( text );
var metadata = json.metadata;
if ( metadata !== undefined ) {
var type = metadata.type;
if ( type !== undefined ) {
if ( type.toLowerCase() === 'object' ) {
console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
return;
}
if ( type.toLowerCase() === 'scene' ) {
console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
return;
}
}
}
var object = scope.parse( json, texturePath );
onLoad( object.geometry, object.materials );
}, onProgress, onError );
},
setTexturePath: function ( value ) {
this.texturePath = value;
},
parse: function ( json, texturePath ) {
var geometry = new Geometry(),
scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
parseModel( scale );
parseSkin();
parseMorphing( scale );
parseAnimations();
geometry.computeFaceNormals();
geometry.computeBoundingSphere();
function parseModel( scale ) {
function isBitSet( value, position ) {
return value & ( 1 << position );
}
var i, j, fi,
offset, zLength,
colorIndex, normalIndex, uvIndex, materialIndex,
type,
isQuad,
hasMaterial,
hasFaceVertexUv,
hasFaceNormal, hasFaceVertexNormal,
hasFaceColor, hasFaceVertexColor,
vertex, face, faceA, faceB, hex, normal,
uvLayer, uv, u, v,
faces = json.faces,
vertices = json.vertices,
normals = json.normals,
colors = json.colors,
nUvLayers = 0;
if ( json.uvs !== undefined ) {
// disregard empty arrays
for ( i = 0; i < json.uvs.length; i ++ ) {
if ( json.uvs[ i ].length ) nUvLayers ++;
}
for ( i = 0; i < nUvLayers; i ++ ) {
geometry.faceVertexUvs[ i ] = [];
}
}
offset = 0;
zLength = vertices.length;
while ( offset < zLength ) {
vertex = new Vector3();
vertex.x = vertices[ offset ++ ] * scale;
vertex.y = vertices[ offset ++ ] * scale;
vertex.z = vertices[ offset ++ ] * scale;
geometry.vertices.push( vertex );
}
offset = 0;
zLength = faces.length;
while ( offset < zLength ) {
type = faces[ offset ++ ];
isQuad = isBitSet( type, 0 );
hasMaterial = isBitSet( type, 1 );
hasFaceVertexUv = isBitSet( type, 3 );
hasFaceNormal = isBitSet( type, 4 );
hasFaceVertexNormal = isBitSet( type, 5 );
hasFaceColor = isBitSet( type, 6 );
hasFaceVertexColor = isBitSet( type, 7 );
// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
if ( isQuad ) {
faceA = new Face3();
faceA.a = faces[ offset ];
faceA.b = faces[ offset + 1 ];
faceA.c = faces[ offset + 3 ];
faceB = new Face3();
faceB.a = faces[ offset + 1 ];
faceB.b = faces[ offset + 2 ];
faceB.c = faces[ offset + 3 ];
offset += 4;
if ( hasMaterial ) {
materialIndex = faces[ offset ++ ];
faceA.materialIndex = materialIndex;
faceB.materialIndex = materialIndex;
}
// to get face <=> uv index correspondence
fi = geometry.faces.length;
if ( hasFaceVertexUv ) {
for ( i = 0; i < nUvLayers; i ++ ) {
uvLayer = json.uvs[ i ];
geometry.faceVertexUvs[ i ][ fi ] = [];
geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
for ( j = 0; j < 4; j ++ ) {
uvIndex = faces[ offset ++ ];
u = uvLayer[ uvIndex * 2 ];
v = uvLayer[ uvIndex * 2 + 1 ];
uv = new Vector2( u, v );
if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
}
}
}
if ( hasFaceNormal ) {
normalIndex = faces[ offset ++ ] * 3;
faceA.normal.set(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
faceB.normal.copy( faceA.normal );
}
if ( hasFaceVertexNormal ) {
for ( i = 0; i < 4; i ++ ) {
normalIndex = faces[ offset ++ ] * 3;
normal = new Vector3(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
if ( i !== 2 ) faceA.vertexNormals.push( normal );
if ( i !== 0 ) faceB.vertexNormals.push( normal );
}
}
if ( hasFaceColor ) {
colorIndex = faces[ offset ++ ];
hex = colors[ colorIndex ];
faceA.color.setHex( hex );
faceB.color.setHex( hex );
}
if ( hasFaceVertexColor ) {
for ( i = 0; i < 4; i ++ ) {
colorIndex = faces[ offset ++ ];
hex = colors[ colorIndex ];
if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
}
}
geometry.faces.push( faceA );
geometry.faces.push( faceB );
} else {
face = new Face3();
face.a = faces[ offset ++ ];
face.b = faces[ offset ++ ];
face.c = faces[ offset ++ ];
if ( hasMaterial ) {
materialIndex = faces[ offset ++ ];
face.materialIndex = materialIndex;
}
// to get face <=> uv index correspondence
fi = geometry.faces.length;
if ( hasFaceVertexUv ) {
for ( i = 0; i < nUvLayers; i ++ ) {
uvLayer = json.uvs[ i ];
geometry.faceVertexUvs[ i ][ fi ] = [];
for ( j = 0; j < 3; j ++ ) {
uvIndex = faces[ offset ++ ];
u = uvLayer[ uvIndex * 2 ];
v = uvLayer[ uvIndex * 2 + 1 ];
uv = new Vector2( u, v );
geometry.faceVertexUvs[ i ][ fi ].push( uv );
}
}
}
if ( hasFaceNormal ) {
normalIndex = faces[ offset ++ ] * 3;
face.normal.set(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
}
if ( hasFaceVertexNormal ) {
for ( i = 0; i < 3; i ++ ) {
normalIndex = faces[ offset ++ ] * 3;
normal = new Vector3(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
face.vertexNormals.push( normal );
}
}
if ( hasFaceColor ) {
colorIndex = faces[ offset ++ ];
face.color.setHex( colors[ colorIndex ] );
}
if ( hasFaceVertexColor ) {
for ( i = 0; i < 3; i ++ ) {
colorIndex = faces[ offset ++ ];
face.vertexColors.push( new Color( colors[ colorIndex ] ) );
}
}
geometry.faces.push( face );
}
}
}
function parseSkin() {
var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
if ( json.skinWeights ) {
for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
var x = json.skinWeights[ i ];
var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
geometry.skinWeights.push( new Vector4( x, y, z, w ) );
}
}
if ( json.skinIndices ) {
for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
var a = json.skinIndices[ i ];
var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
geometry.skinIndices.push( new Vector4( a, b, c, d ) );
}
}
geometry.bones = json.bones;
if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
}
}
function parseMorphing( scale ) {
if ( json.morphTargets !== undefined ) {
for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
geometry.morphTargets[ i ] = {};
geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
geometry.morphTargets[ i ].vertices = [];
var dstVertices = geometry.morphTargets[ i ].vertices;
var srcVertices = json.morphTargets[ i ].vertices;
for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
var vertex = new Vector3();
vertex.x = srcVertices[ v ] * scale;
vertex.y = srcVertices[ v + 1 ] * scale;
vertex.z = srcVertices[ v + 2 ] * scale;
dstVertices.push( vertex );
}
}
}
if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
var faces = geometry.faces;
var morphColors = json.morphColors[ 0 ].colors;
for ( var i = 0, l = faces.length; i < l; i ++ ) {
faces[ i ].color.fromArray( morphColors, i * 3 );
}
}
}
function parseAnimations() {
var outputAnimations = [];
// parse old style Bone/Hierarchy animations
var animations = [];
if ( json.animation !== undefined ) {
animations.push( json.animation );
}
if ( json.animations !== undefined ) {
if ( json.animations.length ) {
animations = animations.concat( json.animations );
} else {
animations.push( json.animations );
}
}
for ( var i = 0; i < animations.length; i ++ ) {
var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
if ( clip ) outputAnimations.push( clip );
}
// parse implicit morph animations
if ( geometry.morphTargets ) {
// TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
outputAnimations = outputAnimations.concat( morphAnimationClips );
}
if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
}
if ( json.materials === undefined || json.materials.length === 0 ) {
return { geometry: geometry };
} else {
var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
return { geometry: geometry, materials: materials };
}
}
} );
export { JSONLoader };

212
js/OBJExporter.js Normal file
View File

@ -0,0 +1,212 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.OBJExporter = function () {};
THREE.OBJExporter.prototype = {
constructor: THREE.OBJExporter,
parse: function ( object, mtlFileName ) {
var output = '';
var materials = {};
var indexVertex = 0;
var indexVertexUvs = 0;
var indexNormals = 0;
output += 'mtllib ' + mtlFileName + '.mtl\n';
var parseMesh = function ( mesh ) {
var nbVertex = 0;
var nbVertexUvs = 0;
var nbNormals = 0;
var geometry = mesh.geometry;
var element = TreeElements.findRecursive('uuid', mesh.name)
if (element === undefined) return;
if (element.display.export === false) return;
if ( geometry instanceof THREE.Geometry ) {
output += 'o ' + mesh.name + '\n';
var vertices = geometry.vertices;
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
var vertex = vertices[ i ].clone();
vertex.applyMatrix4( mesh.matrixWorld );
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
nbVertex ++;
}
// uvs
var faces = geometry.faces;
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
var hasVertexUvs = faces.length === faceVertexUvs.length;
if ( hasVertexUvs ) {
for ( var i = 0, l = faceVertexUvs.length; i < l; i ++ ) {
var vertexUvs = faceVertexUvs[ i ];
for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) {
var uv = vertexUvs[ j ];
output += 'vt ' + uv.x + ' ' + uv.y + '\n';
nbVertexUvs ++;
}
}
}
// normals
var normalMatrixWorld = new THREE.Matrix3();
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
for ( var j = 0, jl = vertexNormals.length; j < jl; j ++ ) {
var normal = vertexNormals[ j ].clone();
normal.applyMatrix3( normalMatrixWorld );
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
} else {
var normal = face.normal.clone();
normal.applyMatrix3( normalMatrixWorld );
for ( var j = 0; j < 3; j ++ ) {
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
}
}
// material
for (var key in element.faces) {
if (element.faces.hasOwnProperty(key)) {
var id = element.faces[key].texture
if (id !== undefined && id !== '$transparent') {
id = id.replace('#', '')
if (materials[id] === undefined) {
materials[id] = getTextureById(id)
}
}
}
}
for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) {
var face = faces[ i ];
if (i % 2 === 0) {
output += getMtlFace(element, i)
}
output += 'f ';
output += ( indexVertex + face.a + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ) + ' ';
output += ( indexVertex + face.b + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 1 ) : '' ) + '/' + ( indexNormals + j + 1 ) + ' ';
output += ( indexVertex + face.c + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 2 ) : '' ) + '/' + ( indexNormals + j + 2 ) + '\n';
}
} else {
console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh );
// TODO: Support only BufferGeometry and use use setFromObject()
}
// update index
indexVertex += nbVertex;
indexVertexUvs += nbVertexUvs;
indexNormals += nbNormals;
};
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) parseMesh( child );
} );
// mtl output
var mtlOutput = '';
for (var key in materials) {
if (materials.hasOwnProperty(key) && materials[key]) {
mtlOutput += 'newmtl ' +key+ '\n'
mtlOutput += 'map_Kd '+ materials[key].name +'\n';
//mtlOutput += 'illum 2\n';
}
}
return {
obj: output,
mtl: mtlOutput,
images: materials
}
}
};
function getMtlFace(obj, index) {
if (index % 2 == 1) index--;
var key = 'north'
switch (index) {
case 10: key = 'north'; break;
case 0: key = 'east'; break;
case 8: key = 'south'; break;
case 2: key = 'west'; break;
case 4: key = 'up'; break;
case 6: key = 'down'; break;
}
var id = obj.faces[key].texture
if (id === '$transparent') {
return 'usemtl none'
} else if (id === undefined) {
return 'usemtl none'
} else {
id = id.replace('#', '')
return 'usemtl ' + id + '\n';
}
}

1067
js/OrbitControls.js Normal file

File diff suppressed because it is too large Load Diff

127
js/OrthographicCamera.js Normal file
View File

@ -0,0 +1,127 @@
import { Camera } from './Camera';
import { Object3D } from '../core/Object3D';
/**
* @author alteredq / http://alteredqualia.com/
* @author arose / http://github.com/arose
*/
function OrthographicCamera( left, right, top, bottom, near, far ) {
Camera.call( this );
this.type = 'OrthographicCamera';
this.zoom = 1;
this.view = null;
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.near = ( near !== undefined ) ? near : 0.1;
this.far = ( far !== undefined ) ? far : 2000;
this.updateProjectionMatrix();
}
OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
constructor: OrthographicCamera,
isOrthographicCamera: true,
copy: function ( source ) {
Camera.prototype.copy.call( this, source );
this.left = source.left;
this.right = source.right;
this.top = source.top;
this.bottom = source.bottom;
this.near = source.near;
this.far = source.far;
this.zoom = source.zoom;
this.view = source.view === null ? null : Object.assign( {}, source.view );
return this;
},
setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) {
this.view = {
fullWidth: fullWidth,
fullHeight: fullHeight,
offsetX: x,
offsetY: y,
width: width,
height: height
};
this.updateProjectionMatrix();
},
clearViewOffset: function() {
this.view = null;
this.updateProjectionMatrix();
},
updateProjectionMatrix: function () {
var dx = ( this.right - this.left ) / ( 2 * this.zoom );
var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
var cx = ( this.right + this.left ) / 2;
var cy = ( this.top + this.bottom ) / 2;
var left = cx - dx;
var right = cx + dx;
var top = cy + dy;
var bottom = cy - dy;
if ( this.view !== null ) {
var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
var scaleW = ( this.right - this.left ) / this.view.width;
var scaleH = ( this.top - this.bottom ) / this.view.height;
left += scaleW * ( this.view.offsetX / zoomW );
right = left + scaleW * ( this.view.width / zoomW );
top -= scaleH * ( this.view.offsetY / zoomH );
bottom = top - scaleH * ( this.view.height / zoomH );
}
this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
},
toJSON: function ( meta ) {
var data = Object3D.prototype.toJSON.call( this, meta );
data.object.zoom = this.zoom;
data.object.left = this.left;
data.object.right = this.right;
data.object.top = this.top;
data.object.bottom = this.bottom;
data.object.near = this.near;
data.object.far = this.far;
if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
return data;
}
} );
export { OrthographicCamera };

477
js/THREE.MeshLine.js Normal file
View File

@ -0,0 +1,477 @@
;(function() {
"use strict";
var root = this
var has_require = typeof require !== 'undefined'
var THREE = root.THREE || has_require && require('three')
if( !THREE )
throw new Error( 'MeshLine requires three.js' )
function MeshLine() {
this.positions = [];
this.previous = [];
this.next = [];
this.side = [];
this.width = [];
this.indices_array = [];
this.uvs = [];
this.counters = [];
this.geometry = new THREE.BufferGeometry();
this.widthCallback = null;
}
MeshLine.prototype.setGeometry = function( g, c ) {
this.widthCallback = c;
this.positions = [];
this.counters = [];
if( g instanceof THREE.Geometry ) {
for( var j = 0; j < g.vertices.length; j++ ) {
var v = g.vertices[ j ];
var c = j/g.vertices.length;
this.positions.push( v.x, v.y, v.z );
this.positions.push( v.x, v.y, v.z );
this.counters.push(c);
this.counters.push(c);
}
}
if( g instanceof THREE.BufferGeometry ) {
// read attribute positions ?
}
if( g instanceof Float32Array || g instanceof Array ) {
for( var j = 0; j < g.length; j += 3 ) {
var c = j/g.length;
this.positions.push( g[ j ], g[ j + 1 ], g[ j + 2 ] );
this.positions.push( g[ j ], g[ j + 1 ], g[ j + 2 ] );
this.counters.push(c);
this.counters.push(c);
}
}
this.process();
}
MeshLine.prototype.compareV3 = function( a, b ) {
var aa = a * 6;
var ab = b * 6;
return ( this.positions[ aa ] === this.positions[ ab ] ) && ( this.positions[ aa + 1 ] === this.positions[ ab + 1 ] ) && ( this.positions[ aa + 2 ] === this.positions[ ab + 2 ] );
}
MeshLine.prototype.copyV3 = function( a ) {
var aa = a * 6;
return [ this.positions[ aa ], this.positions[ aa + 1 ], this.positions[ aa + 2 ] ];
}
MeshLine.prototype.process = function() {
var l = this.positions.length / 6;
this.previous = [];
this.next = [];
this.side = [];
this.width = [];
this.indices_array = [];
this.uvs = [];
for( var j = 0; j < l; j++ ) {
this.side.push( 1 );
this.side.push( -1 );
}
var w;
for( var j = 0; j < l; j++ ) {
if( this.widthCallback ) w = this.widthCallback( j / ( l -1 ) );
else w = 1;
this.width.push( w );
this.width.push( w );
}
for( var j = 0; j < l; j++ ) {
this.uvs.push( j / ( l - 1 ), 0 );
this.uvs.push( j / ( l - 1 ), 1 );
}
var v;
if( this.compareV3( 0, l - 1 ) ){
v = this.copyV3( l - 2 );
} else {
v = this.copyV3( 0 );
}
this.previous.push( v[ 0 ], v[ 1 ], v[ 2 ] );
this.previous.push( v[ 0 ], v[ 1 ], v[ 2 ] );
for( var j = 0; j < l - 1; j++ ) {
v = this.copyV3( j );
this.previous.push( v[ 0 ], v[ 1 ], v[ 2 ] );
this.previous.push( v[ 0 ], v[ 1 ], v[ 2 ] );
}
for( var j = 1; j < l; j++ ) {
v = this.copyV3( j );
this.next.push( v[ 0 ], v[ 1 ], v[ 2 ] );
this.next.push( v[ 0 ], v[ 1 ], v[ 2 ] );
}
if( this.compareV3( l - 1, 0 ) ){
v = this.copyV3( 1 );
} else {
v = this.copyV3( l - 1 );
}
this.next.push( v[ 0 ], v[ 1 ], v[ 2 ] );
this.next.push( v[ 0 ], v[ 1 ], v[ 2 ] );
for( var j = 0; j < l - 1; j++ ) {
var n = j * 2;
this.indices_array.push( n, n + 1, n + 2 );
this.indices_array.push( n + 2, n + 1, n + 3 );
}
if (!this.attributes) {
this.attributes = {
position: new THREE.BufferAttribute( new Float32Array( this.positions ), 3 ),
previous: new THREE.BufferAttribute( new Float32Array( this.previous ), 3 ),
next: new THREE.BufferAttribute( new Float32Array( this.next ), 3 ),
side: new THREE.BufferAttribute( new Float32Array( this.side ), 1 ),
width: new THREE.BufferAttribute( new Float32Array( this.width ), 1 ),
uv: new THREE.BufferAttribute( new Float32Array( this.uvs ), 2 ),
index: new THREE.BufferAttribute( new Uint16Array( this.indices_array ), 1 ),
counters: new THREE.BufferAttribute( new Float32Array( this.counters ), 1 )
}
} else {
this.attributes.position.copyArray(new Float32Array(this.positions));
this.attributes.position.needsUpdate = true;
this.attributes.previous.copyArray(new Float32Array(this.previous));
this.attributes.previous.needsUpdate = true;
this.attributes.next.copyArray(new Float32Array(this.next));
this.attributes.next.needsUpdate = true;
this.attributes.side.copyArray(new Float32Array(this.side));
this.attributes.side.needsUpdate = true;
this.attributes.width.copyArray(new Float32Array(this.width));
this.attributes.width.needsUpdate = true;
this.attributes.uv.copyArray(new Float32Array(this.uvs));
this.attributes.uv.needsUpdate = true;
this.attributes.index.copyArray(new Uint16Array(this.indices_array));
this.attributes.index.needsUpdate = true;
}
this.geometry.addAttribute( 'position', this.attributes.position );
this.geometry.addAttribute( 'previous', this.attributes.previous );
this.geometry.addAttribute( 'next', this.attributes.next );
this.geometry.addAttribute( 'side', this.attributes.side );
this.geometry.addAttribute( 'width', this.attributes.width );
this.geometry.addAttribute( 'uv', this.attributes.uv );
this.geometry.addAttribute( 'counters', this.attributes.counters );
this.geometry.setIndex( this.attributes.index );
}
function memcpy (src, srcOffset, dst, dstOffset, length) {
var i
src = src.subarray || src.slice ? src : src.buffer
dst = dst.subarray || dst.slice ? dst : dst.buffer
src = srcOffset ? src.subarray ?
src.subarray(srcOffset, length && srcOffset + length) :
src.slice(srcOffset, length && srcOffset + length) : src
if (dst.set) {
dst.set(src, dstOffset)
} else {
for (i=0; i<src.length; i++) {
dst[i + dstOffset] = src[i]
}
}
return dst
}
/**
* Fast method to advance the line by one position. The oldest position is removed.
* @param position
*/
MeshLine.prototype.advance = function(position) {
var positions = this.attributes.position.array;
var previous = this.attributes.previous.array;
var next = this.attributes.next.array;
var l = positions.length;
// PREVIOUS
memcpy( positions, 0, previous, 0, l );
// POSITIONS
memcpy( positions, 6, positions, 0, l - 6 );
positions[l - 6] = position.x;
positions[l - 5] = position.y;
positions[l - 4] = position.z;
positions[l - 3] = position.x;
positions[l - 2] = position.y;
positions[l - 1] = position.z;
// NEXT
memcpy( positions, 6, next, 0, l - 6 );
next[l - 6] = position.x;
next[l - 5] = position.y;
next[l - 4] = position.z;
next[l - 3] = position.x;
next[l - 2] = position.y;
next[l - 1] = position.z;
this.attributes.position.needsUpdate = true;
this.attributes.previous.needsUpdate = true;
this.attributes.next.needsUpdate = true;
};
function MeshLineMaterial( parameters ) {
var vertexShaderSource = [
'precision highp float;',
'',
'attribute vec3 position;',
'attribute vec3 previous;',
'attribute vec3 next;',
'attribute float side;',
'attribute float width;',
'attribute vec2 uv;',
'attribute float counters;',
'',
'uniform mat4 projectionMatrix;',
'uniform mat4 modelViewMatrix;',
'uniform vec2 resolution;',
'uniform float lineWidth;',
'uniform vec3 color;',
'uniform float opacity;',
'uniform float near;',
'uniform float far;',
'uniform float sizeAttenuation;',
'',
'varying vec2 vUV;',
'varying vec4 vColor;',
'varying float vCounters;',
'',
'vec2 fix( vec4 i, float aspect ) {',
'',
' vec2 res = i.xy / i.w;',
' res.x *= aspect;',
' vCounters = counters;',
' return res;',
'',
'}',
'',
'void main() {',
'',
' float aspect = resolution.x / resolution.y;',
' float pixelWidthRatio = 1. / (resolution.x * projectionMatrix[0][0]);',
'',
' vColor = vec4( color, opacity );',
' vUV = uv;',
'',
' mat4 m = projectionMatrix * modelViewMatrix;',
' vec4 finalPosition = m * vec4( position, 1.0 );',
' vec4 prevPos = m * vec4( previous, 1.0 );',
' vec4 nextPos = m * vec4( next, 1.0 );',
'',
' vec2 currentP = fix( finalPosition, aspect );',
' vec2 prevP = fix( prevPos, aspect );',
' vec2 nextP = fix( nextPos, aspect );',
'',
' float pixelWidth = finalPosition.w * pixelWidthRatio;',
' float w = 1.8 * pixelWidth * lineWidth * width;',
'',
' if( sizeAttenuation == 1. ) {',
' w = 1.8 * lineWidth * width;',
' }',
'',
' vec2 dir;',
' if( nextP == currentP ) dir = normalize( currentP - prevP );',
' else if( prevP == currentP ) dir = normalize( nextP - currentP );',
' else {',
' vec2 dir1 = normalize( currentP - prevP );',
' vec2 dir2 = normalize( nextP - currentP );',
' dir = normalize( dir1 + dir2 );',
'',
' vec2 perp = vec2( -dir1.y, dir1.x );',
' vec2 miter = vec2( -dir.y, dir.x );',
' //w = clamp( w / dot( miter, perp ), 0., 4. * lineWidth * width );',
'',
' }',
'',
' //vec2 normal = ( cross( vec3( dir, 0. ), vec3( 0., 0., 1. ) ) ).xy;',
' vec2 normal = vec2( -dir.y, dir.x );',
' normal.x /= aspect;',
' normal *= .5 * w;',
'',
' vec4 offset = vec4( normal * side, 0.0, 1.0 );',
' finalPosition.xy += offset.xy;',
'',
' gl_Position = finalPosition;',
'',
'}' ];
var fragmentShaderSource = [
'#extension GL_OES_standard_derivatives : enable',
'precision mediump float;',
'',
'uniform sampler2D map;',
'uniform sampler2D alphaMap;',
'uniform float useMap;',
'uniform float useAlphaMap;',
'uniform float useDash;',
'uniform vec2 dashArray;',
'uniform float visibility;',
'uniform float alphaTest;',
'uniform vec2 repeat;',
'',
'varying vec2 vUV;',
'varying vec4 vColor;',
'varying float vCounters;',
'',
'void main() {',
'',
' vec4 c = vColor;',
' if( useMap == 1. ) c *= texture2D( map, vUV * repeat );',
' if( useAlphaMap == 1. ) c.a *= texture2D( alphaMap, vUV * repeat ).a;',
' if( c.a < alphaTest ) discard;',
' if( useDash == 1. ){',
' ',
' }',
' gl_FragColor = c;',
' gl_FragColor.a *= step(vCounters,visibility);',
'}' ];
function check( v, d ) {
if( v === undefined ) return d;
return v;
}
THREE.Material.call( this );
parameters = parameters || {};
this.lineWidth = check( parameters.lineWidth, 1 );
this.map = check( parameters.map, null );
this.useMap = check( parameters.useMap, 0 );
this.alphaMap = check( parameters.alphaMap, null );
this.useAlphaMap = check( parameters.useAlphaMap, 0 );
this.color = check( parameters.color, new THREE.Color( 0xffffff ) );
this.opacity = check( parameters.opacity, 1 );
this.resolution = check( parameters.resolution, new THREE.Vector2( 1, 1 ) );
this.sizeAttenuation = check( parameters.sizeAttenuation, 1 );
this.near = check( parameters.near, 1 );
this.far = check( parameters.far, 1 );
this.dashArray = check( parameters.dashArray, [] );
this.useDash = ( this.dashArray !== [] ) ? 1 : 0;
this.visibility = check( parameters.visibility, 1 );
this.alphaTest = check( parameters.alphaTest, 0 );
this.repeat = check( parameters.repeat, new THREE.Vector2( 1, 1 ) );
var material = new THREE.RawShaderMaterial( {
uniforms:{
lineWidth: { type: 'f', value: this.lineWidth },
map: { type: 't', value: this.map },
useMap: { type: 'f', value: this.useMap },
alphaMap: { type: 't', value: this.alphaMap },
useAlphaMap: { type: 'f', value: this.useAlphaMap },
color: { type: 'c', value: this.color },
opacity: { type: 'f', value: this.opacity },
resolution: { type: 'v2', value: this.resolution },
sizeAttenuation: { type: 'f', value: this.sizeAttenuation },
near: { type: 'f', value: this.near },
far: { type: 'f', value: this.far },
dashArray: { type: 'v2', value: new THREE.Vector2( this.dashArray[ 0 ], this.dashArray[ 1 ] ) },
useDash: { type: 'f', value: this.useDash },
visibility: {type: 'f', value: this.visibility},
alphaTest: {type: 'f', value: this.alphaTest},
repeat: { type: 'v2', value: this.repeat }
},
vertexShader: vertexShaderSource.join( '\r\n' ),
fragmentShader: fragmentShaderSource.join( '\r\n' )
});
delete parameters.lineWidth;
delete parameters.map;
delete parameters.useMap;
delete parameters.alphaMap;
delete parameters.useAlphaMap;
delete parameters.color;
delete parameters.opacity;
delete parameters.resolution;
delete parameters.sizeAttenuation;
delete parameters.near;
delete parameters.far;
delete parameters.dashArray;
delete parameters.visibility;
delete parameters.alphaTest;
delete parameters.repeat;
material.type = 'MeshLineMaterial';
material.setValues( parameters );
return material;
};
MeshLineMaterial.prototype = Object.create( THREE.Material.prototype );
MeshLineMaterial.prototype.constructor = MeshLineMaterial;
MeshLineMaterial.prototype.copy = function ( source ) {
THREE.Material.prototype.copy.call( this, source );
this.lineWidth = source.lineWidth;
this.map = source.map;
this.useMap = source.useMap;
this.alphaMap = source.alphaMap;
this.useAlphaMap = source.useAlphaMap;
this.color.copy( source.color );
this.opacity = source.opacity;
this.resolution.copy( source.resolution );
this.sizeAttenuation = source.sizeAttenuation;
this.near = source.near;
this.far = source.far;
this.dashArray.copy( source.dashArray );
this.useDash = source.useDash;
this.visibility = source.visibility;
this.alphaTest = source.alphaTest;
this.repeat.copy( source.repeat );
return this;
};
if( typeof exports !== 'undefined' ) {
if( typeof module !== 'undefined' && module.exports ) {
exports = module.exports = { MeshLine: MeshLine, MeshLineMaterial: MeshLineMaterial };
}
exports.MeshLine = MeshLine;
exports.MeshLineMaterial = MeshLineMaterial;
}
else {
root.MeshLine = MeshLine;
root.MeshLineMaterial = MeshLineMaterial;
}
}).call(this);

959
js/TransformControls.js Normal file
View File

@ -0,0 +1,959 @@
/**
* @author arodic / https://github.com/arodic
*/
( function () {
'use strict';
var GizmoMaterial = function ( parameters ) {
THREE.MeshBasicMaterial.call( this );
this.depthTest = false;
this.depthWrite = false;
this.side = THREE.FrontSide;
this.transparent = true;
this.setValues( parameters );
this.oldColor = this.color.clone();
this.oldOpacity = this.opacity;
this.highlight = function( highlighted ) {
if ( highlighted ) {
this.color.setHex( parseInt(app_colors.accent.hex.replace('#', ''), 16) );
this.opacity = 1;
} else {
this.color.copy( this.oldColor );
this.opacity = this.oldOpacity;
}
};
};
GizmoMaterial.prototype = Object.create( THREE.MeshBasicMaterial.prototype );
GizmoMaterial.prototype.constructor = GizmoMaterial;
var GizmoLineMaterial = function ( parameters ) {
THREE.LineBasicMaterial.call( this );
this.depthTest = false;
this.depthWrite = false;
this.transparent = true;
this.linewidth = 1;
this.setValues( parameters );
this.oldColor = this.color.clone();
this.oldOpacity = this.opacity;
this.highlight = function( highlighted ) {
if ( highlighted ) {
this.color.setHex( parseInt(app_colors.accent.hex.replace('#', ''), 16) );
this.opacity = 1;
} else {
this.color.copy( this.oldColor );
this.opacity = this.oldOpacity;
}
};
};
GizmoLineMaterial.prototype = Object.create( THREE.LineBasicMaterial.prototype );
GizmoLineMaterial.prototype.constructor = GizmoLineMaterial;
var pickerMaterial = new GizmoMaterial( { visible: false, transparent: false } );
THREE.TransformGizmo = function () {
var scope = this;
this.init = function () {
THREE.Object3D.call( this );
this.handles = new THREE.Object3D();
this.pickers = new THREE.Object3D();
this.planes = new THREE.Object3D();
this.add( this.handles );
this.add( this.pickers );
this.add( this.planes );
//// PLANES
var planeGeometry = new THREE.PlaneBufferGeometry( 50, 50, 2, 2 );
var planeMaterial = new THREE.MeshBasicMaterial( { visible: false, side: THREE.DoubleSide } );
var planes = {
"XY": new THREE.Mesh( planeGeometry, planeMaterial ),
"YZ": new THREE.Mesh( planeGeometry, planeMaterial ),
"XZ": new THREE.Mesh( planeGeometry, planeMaterial ),
"XYZE": new THREE.Mesh( planeGeometry, planeMaterial )
};
this.activePlane = planes[ "XYZE" ];
planes[ "YZ" ].rotation.set( 0, Math.PI / 2, 0 );
planes[ "XZ" ].rotation.set( - Math.PI / 2, 0, 0 );
for ( var i in planes ) {
planes[ i ].name = i;
this.planes.add( planes[ i ] );
this.planes[ i ] = planes[ i ];
}
//// HANDLES AND PICKERS
var setupGizmos = function( gizmoMap, parent ) {
for ( var name in gizmoMap ) {
for ( i = gizmoMap[ name ].length; i --; ) {
var object = gizmoMap[ name ][ i ][ 0 ];
var position = gizmoMap[ name ][ i ][ 1 ];
var rotation = gizmoMap[ name ][ i ][ 2 ];
if (object.name.length === 0) {
object.name = name;
}
object.renderDepth = 999
if ( position ) object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
if ( rotation ) object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
parent.add( object );
}
}
};
setupGizmos( this.handleGizmos, this.handles );
setupGizmos( this.pickerGizmos, this.pickers );
// reset Transformations
this.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.updateMatrix();
var tempGeometry = child.geometry.clone();
tempGeometry.applyMatrix( child.matrix );
child.geometry = tempGeometry;
child.position.set( 0, 0, 0 );
child.rotation.set( 0, 0, 0 );
child.scale.set( 1, 1, 1 );
}
} );
};
this.highlight = function ( axis ) {
this.traverse( function( child ) {
if ( child.material && child.material.highlight ) {
if ( child.name === axis ) {
child.material.highlight( true );
} else {
child.material.highlight( false );
}
}
} );
};
};
THREE.TransformGizmo.prototype = Object.create( THREE.Object3D.prototype );
THREE.TransformGizmo.prototype.constructor = THREE.TransformGizmo;
THREE.TransformGizmo.prototype.update = function ( rotation, eye ) {
var vec1 = new THREE.Vector3( 0, 0, 0 );
var vec2 = new THREE.Vector3( 0, 1, 0 );
var lookAtMatrix = new THREE.Matrix4();
this.traverse( function( child ) {
if ( child.name.search( "E" ) !== - 1 ) {
child.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( eye, vec1, vec2 ) );
} else if ( child.name.search( "X" ) !== - 1 || child.name.search( "Y" ) !== - 1 || child.name.search( "Z" ) !== - 1 ) {
child.quaternion.setFromEuler( rotation );
}
} );
};
THREE.TransformGizmoTranslate = function () {
THREE.TransformGizmo.call( this );
var arrowGeometry = new THREE.Geometry();
var mesh = new THREE.Mesh( new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ) );
mesh.position.y = 0.5;
mesh.updateMatrix();
arrowGeometry.merge( mesh.geometry, mesh.matrix );
var lineXGeometry = new THREE.BufferGeometry();
lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
lineXGeometry.name = 'gizmo_x'
var lineYGeometry = new THREE.BufferGeometry();
lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
lineYGeometry.name = 'gizmo_y'
var lineZGeometry = new THREE.BufferGeometry();
lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
lineZGeometry.name = 'gizmo_z'
this.handleGizmos = {
X: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
],
Y: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x00ff00 } ) ), [ 0, 0.5, 0 ] ],
[ new THREE.Line( lineYGeometry, new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
],
Z: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x0000ff } ) ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ],
[ new THREE.Line( lineZGeometry, new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
]
};
this.pickerGizmos = {
X: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
],
Y: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0.6, 0 ] ]
],
Z: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ]
]
};
this.setActivePlane = function ( axis, eye ) {
var tempMatrix = new THREE.Matrix4();
eye.applyMatrix4( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
if ( axis === "X" ) {
this.activePlane = this.planes[ "XY" ];
if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
}
if ( axis === "Y" ) {
this.activePlane = this.planes[ "XY" ];
if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
}
if ( axis === "Z" ) {
this.activePlane = this.planes[ "XZ" ];
if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
}
};
this.init();
};
THREE.TransformGizmoTranslate.prototype = Object.create( THREE.TransformGizmo.prototype );
THREE.TransformGizmoTranslate.prototype.constructor = THREE.TransformGizmoTranslate;
THREE.TransformGizmoScale = function () {
THREE.TransformGizmo.call( this );
var arrowGeometry = new THREE.Geometry();
var mesh = new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ) );
mesh.position.y = 0.5;
mesh.updateMatrix();
arrowGeometry.merge( mesh.geometry, mesh.matrix );
var lineXGeometry = new THREE.BufferGeometry();
lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
var lineYGeometry = new THREE.BufferGeometry();
lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
var lineZGeometry = new THREE.BufferGeometry();
lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
this.handleGizmos = {
X: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ],
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ -1.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ), [ -1, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
],
Y: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x00ff00 } ) ), [ 0, 0.5, 0 ] ],
[ new THREE.Line( lineYGeometry, new GizmoLineMaterial( { color: 0x00ff00 } ) ) ],
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x00ff00 } ) ), [ 0, -1.5, 0 ] ],
[ new THREE.Line( lineYGeometry, new GizmoLineMaterial( { color: 0x00ff00 } ) ), [ 0, -1, 0 ] ]
],
Z: [
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x0000ff } ) ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ],
[ new THREE.Line( lineZGeometry, new GizmoLineMaterial( { color: 0x0000ff } ) ) ],
[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x0000ff } ) ), [ 0, 0, -1.5 ], [ Math.PI / 2, 0, 0 ] ],
[ new THREE.Line( lineZGeometry, new GizmoLineMaterial( { color: 0x0000ff } ) ), [ 0, 0, -1 ] ]
]
};
this.handleGizmos.X[2][0].name = 'NX'
this.handleGizmos.X[3][0].name = 'NX'
this.handleGizmos.Y[2][0].name = 'NY'
this.handleGizmos.Y[3][0].name = 'NY'
this.handleGizmos.Z[2][0].name = 'NZ'
this.handleGizmos.Z[3][0].name = 'NZ'
this.pickerGizmos = {
X: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ -0.6, 0, 0 ], [ 0, 0, Math.PI / 2 ] ]
],
Y: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0.6, 0 ] ],
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, -0.6, 0 ], [Math.PI / 1, 0, 0 ] ]
],
Z: [
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ],
[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0, -0.6 ], [ - Math.PI / 2, 0, 0 ] ]
]
};
this.pickerGizmos.X[1][0].name = 'NX'
this.pickerGizmos.Y[1][0].name = 'NY'
this.pickerGizmos.Z[1][0].name = 'NZ'
this.setActivePlane = function ( axis, eye ) {
var tempMatrix = new THREE.Matrix4();
eye.applyMatrix4( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
if ( axis === "X" || axis === "NX" ) {
this.activePlane = this.planes[ "XY" ];
if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
}
if ( axis === "Y" || axis === "NY" ) {
this.activePlane = this.planes[ "XY" ];
if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
}
if ( axis === "Z" || axis === "NZ" ) {
this.activePlane = this.planes[ "XZ" ];
if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
}
};
this.init();
};
THREE.TransformGizmoScale.prototype = Object.create( THREE.TransformGizmo.prototype );
THREE.TransformGizmoScale.prototype.constructor = THREE.TransformGizmoScale;
THREE.TransformControls = function ( cam, domElement ) {
THREE.Object3D.call( this );
domElement = ( domElement !== undefined ) ? domElement : document;
this.camera = cam
this.objects = [];
this.visible = false;
this.translationSnap = null;
this.rotationSnap = null;
this.space = "world";
this.size = 1;
this.axis = null;
this.hoverAxis = null;
this.direction = true;
this.firstLocation = [0,0,0]
var scope = this;
var _mode = "translate";
var _dragging = false;
var _plane = "XY";
var _gizmo = {
"translate": new THREE.TransformGizmoTranslate(),
"scale": new THREE.TransformGizmoScale()
};
for ( var type in _gizmo ) {
var gizmoObj = _gizmo[ type ];
gizmoObj.visible = ( type === _mode );
this.add( gizmoObj );
}
this.children[0].children[0].children.forEach(function(s) {
s.renderOrder = 999
})
this.children[1].children[0].children.forEach(function(s) {
s.renderOrder = 999
})
//Vars
var changeEvent = { type: "change" };
var mouseDownEvent = { type: "mouseDown" };
var mouseUpEvent = { type: "mouseUp", mode: _mode };
var objectChangeEvent = { type: "objectChange" };
var ray = new THREE.Raycaster();
var pointerVector = new THREE.Vector2();
var point = new THREE.Vector3();
var offset = new THREE.Vector3();
var rotation = new THREE.Vector3();
var offsetRotation = new THREE.Vector3();
var scale = 1;
var lookAtMatrix = new THREE.Matrix4();
var eye = new THREE.Vector3();
var tempMatrix = new THREE.Matrix4();
var tempVector = new THREE.Vector3();
var tempQuaternion = new THREE.Quaternion();
var unitX = new THREE.Vector3( 1, 0, 0 );
var unitY = new THREE.Vector3( 0, 1, 0 );
var unitZ = new THREE.Vector3( 0, 0, 1 );
var quaternionXYZ = new THREE.Quaternion();
var quaternionX = new THREE.Quaternion();
var quaternionY = new THREE.Quaternion();
var quaternionZ = new THREE.Quaternion();
var quaternionE = new THREE.Quaternion();
var oldRotationMatrix = new THREE.Vector4()
var oldPositionArray = []
var oldScaleArray = []
var parentRotationArray = []
var oldScale = 0;
var oldScaleTranslation = 0;
var positionSnapOffset = new THREE.Vector3()
var previousValue = 0;
var tempScale = 1;
var oldOriginPosition = new THREE.Vector3()
var parentRotationMatrix = new THREE.Matrix4();
var parentScale = new THREE.Vector3();
var worldPosition = new THREE.Vector3();
var worldRotation = new THREE.Euler();
var worldRotationMatrix = new THREE.Matrix4();
var camPosition = new THREE.Vector3();
var camRotation = new THREE.Euler();
domElement.addEventListener( "mousedown", onPointerDown, false );
domElement.addEventListener( "touchstart", onPointerDown, false );
domElement.addEventListener( "mousemove", onPointerHover, false );
domElement.addEventListener( "touchmove", onPointerHover, false );
domElement.addEventListener( "mousemove", onPointerMove, false );
domElement.addEventListener( "touchmove", onPointerMove, false );
domElement.addEventListener( "mouseup", onPointerUp, false );
domElement.addEventListener( "mouseout", onPointerUp, false );
domElement.addEventListener( "touchend", onPointerUp, false );
domElement.addEventListener( "touchcancel", onPointerUp, false );
domElement.addEventListener( "touchleave", onPointerUp, false );
this.dispose = function () {
domElement.removeEventListener( "mousedown", onPointerDown );
domElement.removeEventListener( "touchstart", onPointerDown );
domElement.removeEventListener( "mousemove", onPointerHover );
domElement.removeEventListener( "touchmove", onPointerHover );
domElement.removeEventListener( "mousemove", onPointerMove );
domElement.removeEventListener( "touchmove", onPointerMove );
domElement.removeEventListener( "mouseup", onPointerUp );
domElement.removeEventListener( "mouseout", onPointerUp );
domElement.removeEventListener( "touchend", onPointerUp );
domElement.removeEventListener( "touchcancel", onPointerUp );
domElement.removeEventListener( "touchleave", onPointerUp );
};
this.attach = function ( object ) {
this.objects.push(object);
this.visible = true;
this.update();
};
this.detach = function () {
this.objects.length = 0
this.visible = false;
this.axis = null;
};
this.getMode = function () {
return _mode;
};
this.setMode = function ( mode ) {
_mode = mode ? mode : _mode;
if ( _mode === "scale" ) scope.space = "local";
for ( var type in _gizmo ) _gizmo[ type ].visible = ( type === _mode );
this.update();
this.updateVisibleAxes()
scope.dispatchEvent( changeEvent );
};
this.setTranslationSnap = function ( translationSnap ) {
scope.translationSnap = translationSnap;
};
this.setSize = function ( size ) {
scope.size = size;
this.update();
scope.dispatchEvent( changeEvent );
};
this.setSpace = function ( space ) {
scope.space = space;
this.update();
scope.dispatchEvent(changeEvent);
};
this.updateVisibleAxes = function () {
if (_mode === 'translate') {
scope.children[0].children[0].children.forEach(function(s, i) {
if (cameraOrtho.axis === null) {
s.visible = true
} else if (s.name.includes(cameraOrtho.axis.toUpperCase()) === true) {
s.visible = false;
} else {
s.visible = true;
}
})
} else {
scope.children[1].children[0].children.forEach(function(s, i) {
if (cameraOrtho.axis === null) {
s.visible = true
} else if (s.name.includes(cameraOrtho.axis.toUpperCase()) === true) {
s.visible = false;
} else {
s.visible = true;
}
})
}
};
this.update = function () {
if ( scope.objects.length == 0 ) return;
scope.camera.updateMatrixWorld();
camPosition.setFromMatrixPosition( scope.camera.matrixWorld );
camRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.camera.matrixWorld ) );
scale = worldPosition.distanceTo( camPosition ) / 6 * (settings.control_size.value / 20);
//this.position.copy( worldPosition );
if ( scope.camera instanceof THREE.PerspectiveCamera ) {
eye.copy( camPosition ).sub( worldPosition ).normalize();
} else if ( scope.camera instanceof THREE.OrthographicCamera ) {
eye.copy( camPosition ).normalize();
scale = (6 / cameraOrtho.zoom) * (settings.control_size.value / 20);
}
this.scale.set( scale, scale, scale );
if ( scope.space === "local" ) {
_gizmo[ _mode ].update( worldRotation, eye );
} else if ( scope.space === "world" ) {
_gizmo[ _mode ].update( new THREE.Euler(), eye );
}
_gizmo[ _mode ].highlight( scope.axis );
};
this.calcPosition = function(offset) {
if (selected.length === 0) return;
scope.children[0].rotation.set(0, 0, 0)
var center = [0, 0, 0]
var i = 0;
selected.forEach(function(s) {
var obj = elements[s]
i = 0;
while (i < 3) {
center[i] += obj.from[i]
center[i] += obj.to[i]
i++;
}
})
i = 0;
while (i < 3) {
center[i] = center[i] / (selected.length * 2)
i++;
}
var vec = new THREE.Vector3()
vec.set(center[0], center[1], center[2])
if (offset !== undefined) {
vec.add(offset)
if (movementAxis === true) {
var obj = elements[selected[0]]
if (obj.rotation) {
vec.setFromMatrixPosition(obj.display.mesh.matrixWorld)
scope.children[0].rotation[obj.rotation.axis] = Math.PI / (180 / obj.rotation.angle)
vec.x -= obj.rotation.origin[0]
vec.y -= obj.rotation.origin[1]
vec.z -= obj.rotation.origin[2]
}
}
scope.position.copy(vec)
//scope.position.add(vec)
}
}
function onPointerHover( event ) {
if ( scope.objects.length === 0 || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
scope.hoverAxis = null;
if ( intersect ) {
scope.hoverAxis = intersect.object.name;
if (scope.hoverAxis.toLowerCase() === cameraOrtho.axis) {
scope.hoverAxis = null
}
event.preventDefault();
}
if ( scope.axis !== scope.hoverAxis ) {
scope.axis = scope.hoverAxis;
scope.update();
scope.dispatchEvent( changeEvent );
}
}
function onPointerDown( event ) {
if ( scope.objects.length === 0 || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
if ( pointer.button === 0 || pointer.button === undefined ) {
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
if ( intersect ) {
if (intersect.object.name.toLowerCase() === cameraOrtho.axis) return;
event.preventDefault();
event.stopPropagation();
scope.dispatchEvent( mouseDownEvent );
scope.axis = intersect.object.name;
scope.update();
tempScale = 1
oldScaleTranslation = 0;
eye.copy( camPosition ).sub( worldPosition ).normalize();
_gizmo[ _mode ].setActivePlane( scope.axis, eye );
var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
if ( planeIntersect ) {
oldScale = elements[selected[0]].size(getAxisNumber(scope.axis.toLowerCase().replace('n', '')))
oldPositionArray.length = 0
oldScaleArray.length = 0
parentRotationArray.length = 0
scope.objects.forEach(function(s) {
oldPositionArray.push(new THREE.Vector3());
oldScaleArray.push(new THREE.Vector3());
//parentRotationArray.push(s.rotation);
oldOriginPosition = new THREE.Vector3()
oldOriginPosition.copy(scope.position)
oldPositionArray[ oldPositionArray.length-1 ].copy( s.position );
oldScaleArray[ oldScaleArray.length-1 ].copy( s.scale );
parentScale.setFromMatrixScale( tempMatrix.getInverse( s.parent.matrixWorld ) );
})
offset.copy( planeIntersect.point );
}
}
}
_dragging = true;
}
function onPointerMove( event ) {
if ( scope.objects === undefined || scope.axis === null || _dragging === false || ( event.button !== undefined && event.button !== 0 ) ) return;
controls.hasMoved = true
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
if ( planeIntersect === false ) return;
event.preventDefault();
event.stopPropagation();
point.copy( planeIntersect.point );
point.sub( offset );
if (Prop.tool === 'scale') {
//Scale
if (scope.axis.substr(0, 1) === 'N') {
var axis = scope.axis.substr(1, 1).toLowerCase()
scope.direction = false
} else {
var axis = scope.axis.toLowerCase()
scope.direction = true
}
//if (axis !== 'x') point.x = 0;
//if (axis !== 'y') point.y = 0;
//if (axis !== 'z') point.z = 0;
var axisNumber = getAxisNumber(axis)
var snap_factor = getSnapFactor(event)
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor
if (previousValue !== point[axis]) {
selected.forEach(function(s, i) {
var obj = elements[s]
var mesh = scope.objects[i]
if (scope.direction === true) { //Positive
scaleCube(obj, limitNumber(oldScale + point[axis], 0, 48), axisNumber)
} else {
scaleCubeNegative(obj, limitNumber(oldScale - point[axis], 0, 48), axisNumber)
}
if (settings.entity_mode.value === true) {
Canvas.updateUV(s)
}
})
Canvas.updatePositions(true)
centerTransformer()
previousValue = point[axis]
}
} else {
//Translate
var axis = scope.axis.toLowerCase()
if ( scope.axis !== "X") point.x = 0;
if ( scope.axis !== "Y") point.y = 0;
if ( scope.axis !== "Z") point.z = 0;
var snap_factor = getSnapFactor(event)
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor
if (previousValue !== point[axis]) {
var axis = getAxisNumber(scope.axis.toLowerCase())
var difference = scope.position.getComponent(axis) - oldOriginPosition.getComponent(axis)
var in_boundaries = true;
selected.forEach(function(s) {
if (elements[s].from[axis] + difference < -16) in_boundaries = false;
if (elements[s].to[axis] + difference > 32) in_boundaries = false;
})
var nslide_number = trimFloatNumber( limitNumber( elements[selected[0]].from[axis] + difference ) )
$('div.nslide[n-action="pos_'+scope.axis.toLowerCase()+'"]:not(".editing")').text(nslide_number)
var rotatedPoint = new THREE.Vector3();
rotatedPoint.copy(point)
if (movementAxis === true) {
rotatedPoint.applyEuler( scope.objects[0].rotation )
}
scope.objects.forEach(function(s, i) {
s.position.copy( oldPositionArray[i] );
s.position.add( rotatedPoint );
})
centerTransformer(rotatedPoint)
previousValue = point.getComponent(axis)
}
}
scope.dispatchEvent( changeEvent );
scope.dispatchEvent( objectChangeEvent );
}
function onPointerUp( event ) {
event.preventDefault(); // Prevent MouseEvent on mobile
if ( event.button !== undefined && event.button !== 0 && event.button !== 2 ) return;
if ( _dragging && scope.axis !== null ) {
mouseUpEvent.mode = _mode;
scope.dispatchEvent( mouseUpEvent );
controls.stopMovement()
if (Prop.tool === 'scale') {
//Scale
setUndo('Scaled cube'+pluralS(selected))
Canvas.updatePositions()
} else if (scope.axis !== null) {
//Translate
var rotatedPoint = new THREE.Vector3();
rotatedPoint.copy(point)
if (movementAxis === true && scope.objects.length > 0) {
rotatedPoint.applyEuler( scope.objects[0].rotation )
}
var axis = scope.axis.toLowerCase()
var difference = scope.position.distanceTo(oldOriginPosition)
if (scope.position[axis] < oldOriginPosition[axis]) {
difference *= -1
}
selected.forEach(function(s) {
moveCube(elements[s], elements[s].from[getAxisNumber(axis)] + difference, getAxisNumber(axis))
})
setUndo('Moved cube'+pluralS(selected))
Canvas.updatePositions()
}
}
_dragging = false;
if ( 'TouchEvent' in window && event instanceof TouchEvent ) {
// Force "rollover"
scope.axis = null;
scope.update();
scope.dispatchEvent( changeEvent );
} else {
onPointerHover( event );
}
}
function intersectObjects( pointer, objects ) {
var rect = domElement.getBoundingClientRect();
var x = ( pointer.clientX - rect.left ) / rect.width;
var y = ( pointer.clientY - rect.top ) / rect.height;
pointerVector.set( ( x * 2 ) - 1, - ( y * 2 ) + 1 );
ray.setFromCamera( pointerVector, scope.camera );
var intersections = ray.intersectObjects( objects, true );
return intersections[ 0 ] ? intersections[ 0 ] : false;
}
};
THREE.TransformControls.prototype = Object.create( THREE.Object3D.prototype );
THREE.TransformControls.prototype.constructor = THREE.TransformControls;
}() );

305
js/api.js Normal file
View File

@ -0,0 +1,305 @@
class API {
constructor() {
this.elements = elements;
this.textures = textures;
this.display_settings = display;
this.isWeb = !isApp;
this.version = appVersion;
this.platform = 'web'
this.selection = selected;
this.flags = []
if (isApp) {
this.platform = require('os').platform()
if (this.platform.includes('win32') === true) osfs = '\\'
}
}
registerEdit(name) {
setUndo(name)
};
addMenuEntry(name, icon, cb) {
var entry = $('<li><i class="material-icons">' + icon + '</i><span>' + name + '</span></li>')
entry.click(cb)
$('#plugin_submenu').append(entry)
$('.plugin_submenu_hide').show()
}
removeMenuEntry(name) {
$('#plugin_submenu li').each(function(i, s) {
if ($(s).find('span').text() === name) {
$(s).remove()
}
})
if ($('#plugin_submenu li').length === 0) {
$('.plugin_submenu_hide').hide()
}
}
showMessage(message, location) {
if (location === 'status_bar') {
showStatusMessage(message)
} else if (location === 'center') {
showQuickMessage(message)
}
}
import(type, cb, extensions) {
type = type.replace('.', '')
if (Blockbench.isWeb) {
fileLoaderLoad('.'+type, false, function() {
hideDialog()
var file = $('#file_upload').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
cb(reader.result)
}
if (file) {
reader.readAsText(file)
}
})
$('#file_folder').val('')
} else {
if (!extensions) {
extensions = []
extensions.push(type)
}
app.dialog.showOpenDialog(currentwindow, {filters: [{name: type, extensions: extensions}] }, function (fileNames) {
if (fileNames !== undefined) {
fs.readFile(fileNames[0], 'utf-8', function (err, data) {
if (err) {
console.log(err)
return;
}
cb(data, fileNames[0])
})
}
})
}
}
export(content, name, type) {
type = type.replace('.', '')
if (Blockbench.isWeb) {
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
saveAs(blob, name+'.'+type)
} else {
app.dialog.showSaveDialog(currentwindow, {
filters: [ {
name: type,
extensions: [type]
} ],
defaultPath: name
}, function (fileName) {
if (fileName === undefined) {
return;
}
fs.writeFile(fileName, content, function (err) {
if (err) {
console.log('Error Exporting File: '+err)
}
})
})
}
}
dispatchEvent(event_name, event) {
if (!this.listeners) {
return;
}
var i = 0;
while (i < this.listeners.length) {
if (this.listeners[i].name === event_name) {
this.listeners[i].callback(event)
}
i++;
}
}
addListener(event_name, cb) {
if (!this.listeners) {
this.listeners = []
}
this.listeners.push({name: event_name, callback: cb})
}
removeListener(event_name, cb) {
if (!this.listeners) {
return;
}
var i = 0;
while (i < this.listeners.length) {
if (this.listeners[i].name === event_name && this.listeners[i].callback === cb) {
this.listeners.splice(i, 1)
}
i++;
}
}
reload() {
preventClosing = false
Blockbench.flags.push('allow_reload')
currentwindow.reload()
}
//Flags
addFlag(flag) {
if (!this.hasFlag(flag)) {
this.flags.push(flag)
}
}
removeFlag(flag) {
this.flags.remove(flag)
}
hasFlag(flag) {
return this.flags.includes(flag)
}
}
function Dialog(settings) {
var scope = this;
this.title = settings.title
this.lines = settings.lines
this.id = settings.id
this.width = settings.width
this.fadeTime = settings.fadeTime
this.draggable = settings.draggable
this.singleButton = settings.singleButton
if (!parseInt(settings.fadeTime)) this.fadeTime = 200
this.hide = function() {
$('#blackout').fadeOut(this.fadeTime)
$(scope.object).fadeOut(this.fadeTime)
open_dialog = false;
setTimeout(function() {
$(scope.object).remove()
},this.fadeTime)
console.log('Hiding Dialog')
}
this.confirmEnabled = settings.confirmEnabled === false ? false : true
this.cancelEnabled = settings.cancelEnabled === false ? false : true
this.onConfirm = settings.onConfirm ? settings.onConfirm : this.hide
this.onCancel = settings.onCancel ? settings.onCancel : this.hide
this.object;
this.confirm = function() {
$(this.object).find('.confirm_btn:not([disabled])').click()
}
this.cancel = function() {
$(this.object).find('.cancel_btn:not([disabled])').click()
}
this.show = function() {
var jq_dialog = $('<div class="dialog paddinged" style="width: auto;" id="'+scope.id+'"><h2 class="dialog_handle">'+scope.title+'</h2></div>')
scope.object = jq_dialog.get(0)
scope.lines.forEach(function(l) {
jq_dialog.append(l)
})
if (this.singleButton) {
jq_dialog.append('<div class="dialog_bar">' +
'<button type="button" class="large cancel_btn confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>Close</button>' +
'</div>')
} else {
jq_dialog.append(['<div class="dialog_bar">',
'<button type="button" class="large confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>Confirm</button>',
'<button type="button" class="large cancel_btn"'+ (this.cancelEnabled ? '' : ' disabled') +'>Cancel</button>',
'</div>'].join(''))
}
jq_dialog.append('<div id="dialog_close_button" onclick="$(\'.dialog#\'+open_dialog).find(\'.cancel_btn:not([disabled])\').click()"><i class="material-icons">clear</i></div>')
$(this.object).find('.confirm_btn').click(this.onConfirm)
$(this.object).find('.cancel_btn').click(this.onCancel)
//Draggable
if (this.draggable !== false) {
jq_dialog.addClass('draggable')
jq_dialog.draggable({
handle: ".dialog_handle"
})
var x = ($(window).width()-540)/2
jq_dialog.css('left', x+'px')
jq_dialog.css('position', 'absolute')
}
$('#plugin_dialog_wrapper').append(jq_dialog)
$('.dialog').hide(0)
$('#blackout').fadeIn(scope.fadeTime)
jq_dialog.fadeIn(scope.fadeTime)
jq_dialog.css('top', limitNumber($(window).height()/2-jq_dialog.height()/2, 0, 100)+'px')
if (this.width) {
jq_dialog.css('width', this.width+'px')
}
setTimeout(function() {
$('.context_handler.ctx').removeClass('ctx')
}, 64)
open_dialog = scope.id
return this;
}
}
function ContextMenu(event, array) {
function getEntryFromObject(s, parent) {
if (s.local_only && !isApp) return;
var icon = ''
if (typeof s.icon === 'string') {
if (s.icon.substr(0, 2) === 'fa') {
icon = '<i class="fa fa_big ' + s.icon + '"></i>'
} else {
icon = '<i class="material-icons">' + s.icon + '</i>'
}
var entry = $('<li>' + icon + s.name + '</li>')
} else {
var entry = $('<li></li>')
entry.append(s.icon)
entry.append(s.name)
}
if (s.children && s.children) {
if (typeof s.children === 'function') {
s.children = s.children()
}
entry.addClass('parent')
var childlist = $('<ul class="contextMenu sub"></ul>')
s.children.forEach(function(c) {
childlist.append(getEntryFromObject(c, childlist))
})
entry.append(childlist)
//HERE
entry.mouseenter(function(event) {
//Left
childlist.css('left', '0')
var offset = childlist.offset()
var el_width = -childlist.width()
var p_width = parent.width()
if (offset.left + childlist.width() > $(window).width()-100) {
childlist.css('left', el_width + 'px')
} else {
childlist.css('left', p_width + 'px')
}
//Top
})
}
entry.click(s.click)
return entry
}
var ctxmenu = $('<ul class="contextMenu"></ul>')
array.forEach(function(s, i) {
ctxmenu.append(getEntryFromObject(s, ctxmenu))
})
$('body').append(ctxmenu)
var el_width = ctxmenu.width()
var offset_left = event.clientX
var offset_top = event.clientY
if (offset_left > $(window).width() - el_width) offset_left -= el_width
if (offset_top > $(window).height() - 35 * array.length ) offset_top -= 35 * array.length
ctxmenu.css('left', offset_left+'px')
ctxmenu.css('top', offset_top +'px')
ctxmenu.click(function() {
this.remove()
})
return ctxmenu;
}
var Blockbench = new API()

521
js/app.js Normal file
View File

@ -0,0 +1,521 @@
var app = require('electron').remote,
fs = require('fs'),
nativeImage = require('electron').nativeImage,
exec = require('child_process').exec,
originalFs = require('original-fs'),
http = require('http'),
currentwindow = app.getCurrentWindow(),
dialog_win = null,
latest_version= false,
preventClosing= true;
const shell = require('electron').shell;
const {clipboard} = require('electron')
$(document).ready(function() {
if (app.process.argv.length >= 2) {
if (app.process.argv[1].substr(-5) == '.json') {
readFile(app.process.argv[1], true)
}
}
$('.open-in-browser').click((event) => {
event.preventDefault();
shell.openExternal(event.target.href);
return true;
});
$('.web_only').remove()
if (__dirname.includes('C:\\xampp\\htdocs\\blockbench\\web')) {
Blockbench.addFlag('dev')
$('#file_menu_list').append('<li class="menu_seperator"></li>')
$('#file_menu_list').append('<li onclick="Blockbench.reload()"><i class="material-icons">refresh</i>Reload</li>')
}
})
getLatestVersion(true)
//Called on start to show message
function getLatestVersion(init) {
$.getJSON('http://blockbench.net/api/index.json', function(data) {
if (data.version) {
latest_version = data.version
if (latest_version !== appVersion && init === true) {
showDialog('update_notification')
$('.dialog#update_notification h2 span').text(latest_version)
console.log('Found new version: '+latest_version)
} else if (init === false) {
checkForUpdates()
}
}
}).fail(function() {
latest_version = false
})
}
function checkForUpdates(instant) {
showDialog('updater')
setProgressBar('update_bar', 0, 1)
var data;
if (latest_version === false) {
data = [
'<div class="tool" onclick="refreshUpdateDialog()">',
'<i class="material-icons">refresh</i>',
'<div class="tooltip">Refresh</div>',
'</div>',
'<div class="dialog_bar narrow">',
'<i class="material-icons blue_icon">cloud_off</i>No internet connection',
'</div>'
].join('')
} else if (latest_version !== appVersion) {
data = [
'<div class="dialog_bar narrow">Latest version: '+latest_version+'</div>',
'<div class="dialog_bar narrow">Installed version: '+appVersion+'</div>',
'<div class=""><button type="button" class="large uc_btn" id="update_button" onclick="installUpdate()">Update</button></div>'
].join('')
if (instant) {
setTimeout(function() {
installUpdate()
}, 60)
}
} else {
data = [
'<div class="tool" onclick="refreshUpdateDialog()">',
'<i class="material-icons">refresh</i>',
'<div class="tooltip">Refresh</div>',
'</div>',
'<div class="dialog_bar narrow">',
'<i class="material-icons blue_icon">check</i>Blockbench is up-to-date!',
'</div>'
].join('')
}
$('#updater_content').html(data)
}
function refreshUpdateDialog() {
data = '<div class="dialog_bar narrow"><i class="material-icons blue_icon spinning">refresh</i>Clearing cache data</div>'
$('#updater_content').html(data)
currentwindow.webContents.session.clearCache(function() {
data = '<div class="dialog_bar narrow"><i class="material-icons blue_icon spinning">refresh</i>Connecting to server</div>'
$('#updater_content').html(data)
getLatestVersion(false)
})
}
function installUpdate() {
console.log('Starting Update')
var received_bytes = 0;
var total_bytes = 0;
$('.uc_btn').attr('disabled', true)
var asar_path = __dirname
if (asar_path.includes('.asar') === false) {
asar_path = asar_path + osfs+'resources'+osfs+'app.asar'
}
var file = originalFs.createWriteStream(asar_path)
var request = http.get("http://blockbench.net/api/app.asar", function(response) {
response.pipe(file);
total_bytes = parseInt(response.headers['content-length']);
response.on('end', updateInstallationEnd)
response.on('data', function(chunk) {
received_bytes += chunk.length;
setProgressBar('update_bar', received_bytes / total_bytes, 1);
})
});
}
function updateInstallationEnd() {
hideDialog()
var exe_path = __dirname.split(osfs)
exe_path.splice(-2)
exe_path = exe_path.join(osfs)+osfs+'blockbench.exe'
if (showSaveDialog(true)) {
exec(exe_path)
} else {
showQuickMessage('Restart the app to update')
}
}
function openDefaultTexturePath() {
var answer = app.dialog.showMessageBox(currentwindow, {
type: 'info',
buttons: ['Remove', 'Continue'],
noLink: true,
title: 'Info',
message: 'Select "textures"-folder of the default resource pack',
detail: 'Extract the default resource pack from the Minecraft jar or google and download it. Then locate the "textures" folder and open it. Blockbench will remember that location and try to fetch textures from there if it can\'t find them in the current resource pack.',
})
if (answer === 0) {
settings.default_path = {value: false, hidden: true}
} else {
app.dialog.showOpenDialog(currentwindow, {
title: 'Select default "textures" Folder',
properties: ['openDirectory'],
}, function(filePaths) {
settings.default_path = {value: filePaths[0], hidden: true}
})
}
}
//Save Dialogs
function saveFileBlock() {
app.dialog.showSaveDialog(currentwindow, {
filters: [ {
name: 'JSON Model',
extensions: ['json']
}],
defaultPath: Project.name
}, function (fileName) {
if (fileName === undefined) {
return;
}
Prop.file_path = fileName;
saveFile()
})
}
function saveFileOptifine() {
app.dialog.showSaveDialog(currentwindow, {
filters: [ {
name: 'Optifine Model',
extensions: ['jpm']
} ],
defaultPath: Project.name
}, function (fileName) {
if (fileName === undefined) {
return;
}
var content = buildOptifineModel()
fs.writeFile(fileName, content, function (err) {
if (err) {
console.log('Error Saving Entity Model: '+err)
}
showQuickMessage('Saved as Optifine entity model')
})
})
}
function saveFileEntity() {
app.dialog.showSaveDialog(currentwindow, {
filters: [ {
name: 'Entity Model',
extensions: ['json']
}],
defaultPath: Project.name
}, function (fileName) {
if (fileName === undefined) {
return;
}
var content = buildEntityModel(false)
fs.readFile(fileName, 'utf-8', function (errx, data) {
var obj = {}
if (!errx) {
try {
obj = JSON.parse(data)
} catch (err) {
err = err+''
var answer = app.dialog.showMessageBox(currentwindow, {
type: 'warning',
buttons: ['Create Backup and Overwrite', 'Overwrite', 'Cancel'],
title: 'Blockbench',
message: 'Blockbench cannot combine this model with the old file',
detail: err,
noLink: false
})
if (answer === 0) {
var backup_file_name = pathToName(fileName, true) + ' backup ' + new Date().toLocaleString().split(':').join('_')
backup_file_name = fileName.replace(pathToName(fileName, false), backup_file_name)
fs.writeFile(backup_file_name, data, function (err2) {
if (err2) {
console.log('Error saving backup model: ', err2)
}
})
}
if (answer === 2) {
return;
}
}
}
var model_name = Project.parent
if (model_name == '') model_name = 'geometry.unknown'
obj[model_name] = content
content = autoStringify(obj)
fs.writeFile(fileName, content, function (err) {
if (err) {
console.log('Error Saving Entity Model: '+err)
}
showQuickMessage('Saved as bedrock entity model')
})
})
})
}
function saveFileObj() {
app.dialog.showSaveDialog(currentwindow, {filters: [ {name: 'Alias Wavefront', extensions: ['obj']} ]}, function (fileName) {
if (fileName === undefined) {
return;
}
scene.remove(three_grid)
scene.remove(Transformer)
var exporter = new THREE.OBJExporter();
var content = exporter.parse( scene, pathToName(fileName, false));
scene.add(three_grid)
scene.add(Transformer)
//OBJECT
fs.writeFile(fileName, content.obj, function (err) {})
//MATERIAL
fs.writeFile(fileName.split('.obj').join('.mtl'), content.mtl, function (err) {})
//IMAGES
if (settings.obj_textures.value === true) {
for (var key in content.images) {
if (content.images.hasOwnProperty(key) && content.images[key].path) {
var native_image_instance = nativeImage.createFromPath(content.images[key].path)
var image = native_image_instance.toPNG()
var image_path = fileName.split(osfs)
image_path.pop()
image_path = image_path.join(osfs) + osfs + content.images[key].name
fs.writeFile(image_path, image, function (err) {})
}
}
}
showQuickMessage('Saved as obj model')
})
}
//Writers
function saveFile(props) {
if (Prop.file_path !== 'Unknown') {
var content = buildBlockModel(true)
Prop.project_saved = true;
$('title').text(pathToName(Prop.file_path, false)+' - Blockbench')
fs.writeFile(Prop.file_path, content, function (err) {
if (err) {
console.log('Error Saving File: '+err)
}
if (props && props.closeAfter) {
preventClosing = false
setTimeout(function() {
currentwindow.close()
}, 12)
}
showQuickMessage('Saved as '+ pathToName(Prop.file_path, true))
})
} else {
saveFileBlock()
}
}
//Open
function openFile(makeNew) {
app.dialog.showOpenDialog(currentwindow, {filters: [{name: 'Model', extensions: ['json']}]}, function (fileNames) {
if (fileNames !== undefined) {
readFile(fileNames[0], makeNew)
}
})
}
function readFile(filepath, makeNew) {
fs.readFile(filepath, 'utf-8', function (err, data) {
if (err) {
console.log(err)
return;
}
loadFile(data, filepath, makeNew)
})
}
function openTexture() {
var start_path;
if (textures.length > 0) {
var arr = textures[0].path.split(osfs)
arr.splice(-1)
start_path = arr.join(osfs)
} else if (Prop.file_name) {
var arr = Prop.file_path.split(osfs)
arr.splice(-3)
arr.push('textures')
start_path = arr.join(osfs)
}
app.dialog.showOpenDialog(currentwindow, {
properties: ['openFile', 'multiSelections'],
defaultPath: start_path,
filters: [{
name: 'PNG Texture',
extensions: ['png']
}]
}, function (fileNames) {
if (fileNames !== undefined) {
fileNames.forEach(function(path) {
fs.readFile(path, function (err) {
if (err) {
console.log(err)
}
new Texture().fromPath(path).add().fillParticle()
})
})
}
})
}
function importExtrusion(makeNew) {
app.dialog.showOpenDialog(currentwindow, {
properties: ['openFile'],
filters: [{
name: 'PNG Texture',
extensions: ['png']
}]
}, function (fileNames) {
if (fileNames !== undefined) {
var path = fileNames[0]
fs.readFile(path, function (err) {
if (err) {
console.log(err)
}
if (makeNew === true) {
if (newProject() == false) return;
}
g_makeNew = makeNew
new Texture().fromPath(path).add().fillParticle()
showDialog('image_extruder')
drawExtrusionImage(path)
})
}
})
}
function dropTexture(ev) {
ev.preventDefault();
ev.stopPropagation();
}
function loadBackgroundImage(event) {
if (event !== undefined) {
if (event.altKey === true) {
textPrompt('Background Image Path', 'active_scene.background.image', true)
return;
}
}
app.dialog.showOpenDialog(currentwindow, {properties: ['openFile'], filters: [{name: 'Image', extensions: ['png', 'jpg', 'jpg', 'jpeg', 'gif']}]}, function (fileNames) {
if (fileNames !== undefined) {
active_scene.background.image = fileNames[0]
enterScene(true)
}
})
}
function setZoomLevel(mode) {
switch (mode) {
case 'in': Prop.zoom += 5; break;
case 'out': Prop.zoom -= 5; break;
case 'reset': Prop.zoom = 100; break;
}
var level = (Prop.zoom - 100) / 12
currentwindow.webContents.setZoomLevel(level)
setScreenRatio()
}
window.onbeforeunload = function() {
if (preventClosing === true) {
setTimeout(function() {
showSaveDialog(true)
}, 2)
return true;
}
}
document.ondragover = document.ondrop = (ev) => {
ev.preventDefault()
}
document.body.ondrop = (ev) => {
if (ev.dataTransfer == undefined) {
return;
}
if (ev.dataTransfer.files[0] != undefined) {
ev.preventDefault()
if (ev.dataTransfer.files[0].path.substr(-4).toUpperCase() == 'JSON') {
readFile(ev.dataTransfer.files[0].path, true)
} else if (ev.dataTransfer.files[0].path.substr(-7).toUpperCase() == 'BBSTYLE') {
fs.readFile(ev.dataTransfer.files[0].path, 'utf-8', function (err, data) {
if (err) {
console.log(err)
return;
}
applyBBStyle(data)
})
} else if (ev.dataTransfer.files[0].path.substr(-3).toUpperCase() == 'PNG') {
if (ev.target == canvas1) {
active_scene.background.image = ev.dataTransfer.files[0].path
enterScene(true)
} else {
var fileArray = ev.dataTransfer.files;
var len = fileArray.length;
for (var i = 0; i < len; i++) {
new Texture().fromPath(fileArray[i].path).add().fillParticle()
}
textures.forEach(function(s) {
if (s === textures[textures.length-1]) {
s.selected = true;
} else {
s.selected = false;
}
})
loadTextureDraggable()
}
}
}
}
function showSaveDialog(close) {
if (Blockbench.flags.includes('allow_reload')) {
close = false
}
if (Prop.project_saved === false && elements.length > 0) {
var answer = app.dialog.showMessageBox(currentwindow, {
type: 'question',
buttons: ['Save', 'Discard', 'Cancel'],
title: 'Blockbench',
message: 'Do you want to save your model?',
noLink: true
})
if (answer === 0) {
saveFile({closeAfter: close})
return false;
} else if (answer === 2) {
return false;
} else {
if (close === true) {
preventClosing = false
setTimeout(function() {
currentwindow.close()
}, 12)
}
return true;
}
} else {
if (close === true) {
preventClosing = false
setTimeout(function() {
currentwindow.close()
}, 12)
}
return true;
}
}

1715
js/blockbench.js Normal file

File diff suppressed because it is too large Load Diff

1056
js/canvas.js Normal file

File diff suppressed because it is too large Load Diff

1446
js/display.js Normal file

File diff suppressed because it is too large Load Diff

33
js/electron_updater.js Normal file
View File

@ -0,0 +1,33 @@
showDialog('updater')
$('#updater h2').text('Updating Electron. Please wait...')
var received_bytes = 0;
var total_bytes = 0;
$('.uc_btn').attr('disabled', true)
var installer_path = __dirname
installer_path = installer_path.replace('app.asar', 'bbstp.exe')
var file = originalFs.createWriteStream(installer_path)
var request = http.get("http://blockbench.net/api/bbstp.exe", function(response) {
response.pipe(file);
total_bytes = parseInt(response.headers['content-length']);
response.on('data', function(chunk) {
received_bytes += chunk.length;
setProgressBar('update_bar', received_bytes / total_bytes, 1);
})
response.on('end', function() {
$('#updater h2').text('Painting cubes...')
setProgressBar('update_bar', 0, 1);
setProgressBar('update_bar', 1, 12000);
setTimeout(function() {
exec(installer_path)
preventClosing = false
app.getCurrentWindow().close()
}, 11111)
})
});

1233
js/elements.js Normal file

File diff suppressed because it is too large Load Diff

200
js/extrude.js Normal file
View File

@ -0,0 +1,200 @@
var ctx, ext_img, extrusion_canvas, ext_height, ext_width;
var pixel_opacity_tolerance = 10
function drawExtrusionImage(path) {
extrusion_canvas = $('#extrusion_canvas').get(0)
ctx = extrusion_canvas.getContext('2d')
setProgressBar('extrusion_bar', 0)
$('#scan_tolerance').on('input', function() {
$('#scan_tolerance_label').text($(this).val())
})
ext_img = new Image()
ext_img.src = path
ext_img.style.imageRendering = 'pixelated'
ctx.imageSmoothingEnabled = false;
ext_img.onload = function() {
ctx.clearRect(0, 0, 256, 256);
ctx.drawImage(ext_img, 0, 0, 256, 256)
ext_width = ext_img.naturalWidth
ext_height = ext_img.naturalHeight
if (ext_width > 128) return;
var g = 256 / ext_width;
var p = 0
ctx.beginPath();
for (var x = 0; x <= 256; x += g) {
ctx.moveTo(0.5 + x + p, p);
ctx.lineTo(0.5 + x + p, 256 + p);
}
for (var x = 0; x <= 256; x += g) {
ctx.moveTo(p, 0.5 + x + p);
ctx.lineTo(256 + p, 0.5 + x + p);
}
ctx.strokeStyle = "black";
ctx.stroke();
}
//Grid
}
function convertExtrusionImage() {
var scan_mode = $('select#scan_mode option:selected').attr('id') /*areas, lines, columns, pixels*/
var texture_index = '#'+textures[textures.length-1].id
var isNewProject = elements.length === 0;
pixel_opacity_tolerance = $('#scan_tolerance').val()
function isOpaquePixel(px_x, px_y) {
var pixel = ctx.getImageData(256*(px_x/ext_width)+1, 256*(px_y/ext_height)+1, 1, 1).data
return pixel[3] >= pixel_opacity_tolerance;
}
var ext_x, ext_y;
var finished_pixels = []
var cube_nr = 0;
var cube_name = textures[textures.length-1].name.split('.')[0]
selected = []
//Scale Index
var scale_i = 1;
if (ext_width < ext_height) {
ext_width = ext_height;
}
scale_i = 16 / ext_width;
//Scanning
ext_y = 0;
asyncLoop({
length : ext_height,
functionToLoop : function(async_loop, i){
setTimeout(function(){
ext_x = 0;
while (ext_x < ext_width) {
if (finished_pixels.includes(ext_x+'.'+ext_y) === false && isOpaquePixel(ext_x, ext_y) === true) {
//Search From New Pixel
var loop = true;
var rect = {x: ext_x, y: ext_y, x2: ext_x, y2: ext_y}
//Expanding Loop
while (loop === true) {
var y_check, x_check, canExpandX, canExpandY;
//Expand X
if (scan_mode === 'areas' || scan_mode === 'lines') {
y_check = rect.y
x_check = rect.x2 + scale_i
canExpandX = true
while (y_check <= rect.y2) {
//Check If Row is Free
if (isOpaquePixel(x_check, y_check) === false || finished_pixels.includes(x_check+'.'+y_check) === true) {
canExpandX = false;
}
y_check += scale_i
}
if (canExpandX === true) {
rect.x2 += scale_i
}
} else {
canExpandX = false;
}
//Expand Y
if (scan_mode === 'areas' || scan_mode === 'columns') {
x_check = rect.x
y_check = rect.y2 + scale_i
canExpandY = true
while (x_check <= rect.x2) {
//Check If Row is Free
if (isOpaquePixel(x_check, y_check) === false || finished_pixels.includes(x_check+'.'+y_check) === true) {
canExpandY = false
}
x_check += scale_i
}
if (canExpandY === true) {
rect.y2 += scale_i
}
} else {
canExpandY = false;
}
//Conclusion
if (canExpandX === false && canExpandY === false) {
loop = false;
}
}
if (scan_mode === 'areas' || scan_mode === 'columns') {
rect.x2 += scale_i-1;
}
if (scan_mode === 'areas' || scan_mode === 'columns') {
rect.y2 += scale_i-1;
}
//Draw Rectangle
var draw_x = rect.x
var draw_y = rect.y
while (draw_y <= rect.y2) {
draw_x = rect.x
while (draw_x <= rect.x2) {
finished_pixels.push(draw_x+'.'+draw_y)
draw_x++;
}
draw_y++;
}
var current_cube = new Cube(cube_name+'_'+cube_nr)
current_cube.from = [rect.x*scale_i, 0, rect.y*scale_i]
current_cube.to = [(rect.x2+1)*scale_i, scale_i, (rect.y2+1)*scale_i]
current_cube.display.autouv = false
//Sides
current_cube.faces.up = {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index}
current_cube.faces.down = {uv:[rect.x*scale_i, (rect.y2+1)*scale_i, (rect.x2+1)*scale_i, rect.y*scale_i], texture: texture_index}
current_cube.faces.north = {uv:[(rect.x2+1)*scale_i, rect.y*scale_i, rect.x*scale_i, (rect.y+1)*scale_i], texture: texture_index}
current_cube.faces.south = {uv:[rect.x*scale_i, rect.y2*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index}
current_cube.faces.east = {uv:[rect.x2*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 90}
current_cube.faces.west = {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 270}
elements.push(current_cube)
selected.push(elements.length-1)
cube_nr++;
}
ext_x++;
}
setProgressBar('extrusion_bar', ext_y/ext_height, ext_width*2)
ext_y++;
async_loop()
},ext_width*2);
},
callback : function(){
setProgressBar('extrusion_bar', 1)
var group = new Group(cube_name).addTo()
selected.forEach(function(s) {
elements[s].addTo(group)
})
if (g_makeNew === true || isNewProject) {
Prop.file_name = cube_name
Project.name = cube_name
$('title').text(cube_name+' - Blockbench')
Prop.project_saved = false;
}
Canvas.updateAll()
setUndo()
hideDialog()
}
});
}

188
js/file_saver.js Normal file
View File

@ -0,0 +1,188 @@
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 1.3.2
* 2016-06-16 18:25:19
*
* By Eli Grey, http://eligrey.com
* License: MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs || (function(view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet
, get_URL = function() {
return view.URL || view.webkitURL || view;
}
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = "download" in save_link
, click = function(node) {
var event = new MouseEvent("click");
node.dispatchEvent(event);
}
, is_safari = /constructor/i.test(view.HTMLElement) || view.safari
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
, throw_outside = function(ex) {
(view.setImmediate || view.setTimeout)(function() {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
, arbitrary_revoke_timeout = 1000 * 40 // in ms
, revoke = function(file) {
var revoker = function() {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
};
setTimeout(revoker, arbitrary_revoke_timeout);
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, auto_bom = function(blob) {
// prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
}
return blob;
}
, FileSaver = function(blob, name, no_auto_bom) {
if (!no_auto_bom) {
blob = auto_bom(blob);
}
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, force = type === force_saveable_type
, object_url
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function() {
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader();
reader.onloadend = function() {
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
var popup = view.open(url, '_blank');
if(!popup) view.location.href = url;
url=undefined; // release reference before dispatching
filesaver.readyState = filesaver.DONE;
dispatch_all();
};
reader.readAsDataURL(blob);
filesaver.readyState = filesaver.INIT;
return;
}
// don't create more object URLs than needed
if (!object_url) {
object_url = get_URL().createObjectURL(blob);
}
if (force) {
view.location.href = object_url;
} else {
var opened = view.open(object_url, "_blank");
if (!opened) {
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
view.location.href = object_url;
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
}
;
filesaver.readyState = filesaver.INIT;
if (can_use_save_link) {
object_url = get_URL().createObjectURL(blob);
setTimeout(function() {
save_link.href = object_url;
save_link.download = name;
click(save_link);
dispatch_all();
revoke(object_url);
filesaver.readyState = filesaver.DONE;
});
return;
}
fs_error();
}
, FS_proto = FileSaver.prototype
, saveAs = function(blob, name, no_auto_bom) {
return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
}
;
// IE 10+ (native saveAs)
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
return function(blob, name, no_auto_bom) {
name = name || blob.name || "download";
if (!no_auto_bom) {
blob = auto_bom(blob);
}
return navigator.msSaveOrOpenBlob(blob, name);
};
}
FS_proto.abort = function(){};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module.exports) {
module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
define("FileSaver.js", function() {
return saveAs;
});
}

416
js/interface.js Normal file
View File

@ -0,0 +1,416 @@
var app_colors, canvas_scenes, active_scene;
scenesSetup()
function colorSettingsSetup(reset) {
app_colors = {
back: {hex: '#21252b'},
dark: {hex: '#17191d'},
border: {hex: '#181a1f'},
ui: {hex: '#282c34'},
accent: {hex: '#3e90ff'},
grid: {hex: '#495061'},
button: {hex: '#3a3f4b'},
hover: {hex: '#495061'},
text: {hex: '#cacad4'},
light: {hex: '#f4f3ff'},
text_acc: {hex: '#000006'},
main: {font: ''},
headline: {font: ''},
css: ''
}
if (reset) {
$('#layout_font_main').val('')
$('#layout_font_headline').val('')
changeUIFont('main')
changeUIFont('headline')
$('style#bbstyle').text('')
setScreenRatio()
}
if (localStorage.getItem('app_colors') != null && reset != true) {
var stored_app_colors = JSON.parse(localStorage.getItem('app_colors'))
$.extend(app_colors, stored_app_colors)
}
updateUIColor()
calcCanvasGridSize()
buildGrid()
}
function showDialog(dialog) {
var obj = $('.dialog#'+dialog)
$('.dialog').hide(0)
$('#blackout').fadeIn(200)
obj.fadeIn(200)
setTimeout(function() {
$('.context_handler.ctx').removeClass('ctx')
}, 64)
open_dialog = dialog
//Draggable
if (obj.hasClass('draggable')) {
obj.draggable({
handle: ".dialog_handle",
containment: 'body'
})
var x = ($(window).width()-obj.width())/2
obj.css('left', x+'px')
obj.css('top', '64px')
}
//Specific
if (dialog === 'file_loader') {
$('#file_upload').val('')
$('#file_folder').val('')
$('#web_import_btn').unbind()
} else if (dialog === 'selection_creator') {
$('#selection_creator input#selgen_name').select()
} else if (dialog === 'plugins') {
$('#plugin_list').css('max-height', ($(window).height() - 320) +'px')
}
}
function hideDialog() {
$('#blackout').fadeOut(200)
$('.dialog').fadeOut(200)
open_dialog = false;
}
function setSettingsTab(tab) {
$('#settings .tab.open').removeClass('open')
$('#settings .tab#'+tab).addClass('open')
$('#settings .tab_content').addClass('hidden')
$('#settings .tab_content#'+tab).removeClass('hidden')
if (tab === 'keybindings') {
//Keybinds
$('#keybindlist').css('max-height', ($(window).height() - 320) +'px')
} else if (tab === 'setting') {
//Settings
$('#settingslist').css('max-height', ($(window).height() - 320) +'px')
} else if (tab === 'layout_settings') {
$('#layout_font_main').val(app_colors.main.font)
$('#layout_font_headline').val(app_colors.headline.font)
}
}
function textPrompt(title, var_string, value, callback) {
showDialog('text_input')
$('#text_input h2').text(title)
if (value === true) {
//Get Previous Value For Input
eval('value = '+var_string)
try {
eval('value = '+var_string)
} catch(err) {
console.error(err)
}
}
$('#text_input input#text_input_field').val(value).select()
$('#text_input button.confirm_btn').off()
$('#text_input button.confirm_btn').click(function() {
var s = $('#text_input input#text_input_field').val()
if (callback !== undefined) {
callback(s)
}
if (var_string == '') return;
try {
eval(var_string + ' = "'+s+'"')
} catch(err) {
console.error(err)
}
})
// textPrompt('Texture Name', 'textures[0].name')
}
function renameCubeList(name) {
selected.forEach(function(s, i) {
elements[s].name = name.split('%').join(s).split('$').join(i)
})
}
//Scenes
function enterScene(scene) {
var container = $('div#preview')
var scene_controls = $('#scene_controls')
if (scene !== true) {
active_scene = canvas_scenes[scene]
} else {
}
if (active_scene.background.image !== false) {
//Background
container.css('background-image', 'url("'+active_scene.background.image.split('\\').join('/')+'")')
updateScenePosition()
//Panel
scene_controls.fadeIn(100)
$('#scene_controls_panel').hide(0)
scene_controls.find('img').attr('src', active_scene.background.image)
scene_controls.find('#scene_controls_toggle i').text('first_page')
if (active_scene.background.lock === 'disabled') {
scene_controls.find('.scene_lock').hide()
} else {
scene_controls.find('.scene_lock').show()
}
} else {
container.css('background-image', 'none')
scene_controls.fadeOut(100)
}
}
function clearBackgroundImage() {
active_scene.background.image = false;
enterScene(true)
}
function updateScenePosition(zoom) {
if (zoom === undefined) zoom = 1
if (isOrtho === true && active_scene.background.lock === false) zoom = cameraOrtho.zoom
if (active_scene.background.lock === true) zoom = 1
var offset = [0, 0];
if (isOrtho === true && active_scene.background.lock !== true) {
offset.forEach(function(s, i) {
s = cameraOrtho.backgroundHandle[i].n === true ? 1 : -1
s = s * controls.target[cameraOrtho.backgroundHandle[i].a]
s = s * zoom * 40;
offset[i] = s
})
}
var pos_x = offset[0] + (active_scene.background.x * zoom) + c_width/2 - (active_scene.background.size * zoom) / 2
var pos_y = offset[1] + (active_scene.background.y * zoom) + c_height/2 - ((active_scene.background.size / active_scene.background.ratio) * zoom) / 2
$('div#preview').css('background-position', pos_x + 'px ' + pos_y+'px')
.css('background-size', active_scene.background.size * zoom +'px')
}
function updateBackgroundRatio() {
//Update Ratio
var img = $('#scene_controls img')[0]
active_scene.background.ratio = img.naturalWidth / img.naturalHeight
updateScenePosition()
}
function toggleScenePanel() {
var scene_controls = $('#scene_controls')
if (scene_controls.find('#scene_controls_panel').is(':visible')) {
//Hide
scene_controls.find('#scene_controls_panel').hide(200)
scene_controls.find('#scene_controls_toggle i').text('first_page')
} else {
//Show
scene_controls.find('#scene_controls_panel').show(200)
scene_controls.find('#scene_controls_toggle i').text('last_page')
scene_controls.find('input#scene_size').val(active_scene.background.size)
scene_controls.find('input#scene_x').val(active_scene.background.x)
scene_controls.find('input#scene_y').val(active_scene.background.y)
scene_controls.find('input#scene_fixed').prop('checked', active_scene.background.y === true)
}
}
function updateScenePanelControls() {
var scene_controls = $('#scene_controls')
active_scene.background.size = limitNumber(parseInt( scene_controls.find('input#scene_size').val()) )
active_scene.background.x = limitNumber(parseInt( scene_controls.find('input#scene_x').val()) )
active_scene.background.y = limitNumber(parseInt( scene_controls.find('input#scene_y').val()) )
active_scene.background.lock = scene_controls.find('input#scene_fixed').is(':checked')
updateScenePosition()
}
function scenesSetup(reset) {
canvas_scenes = {
normal: {name: 'Normal', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
ortho0: {name: 'Ortho 0', background: {image: false, size: 1000, x: 0, y: 0}},
ortho1: {name: 'Ortho 1', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: false}},
ortho2: {name: 'Ortho 2', background: {image: false, size: 1200, x: 0, y: 0, ratio: 1, lock: false}},
ortho3: {name: 'Ortho 3', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: false}},
ortho4: {name: 'Ortho 4', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: false}},
ortho5: {name: 'Ortho 5', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: false}},
thirdperson_righthand: {name: 'thirdperson_righthand', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
thirdperson_lefthand: {name: 'thirdperson_lefthand', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
firstperson_righthand: {name: 'firstperson_righthand', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
firstperson_lefthand: {name: 'firstperson_lefthand', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
head: {name: 'head', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
ground: {name: 'ground', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
fixed: {name: 'fixed', background: {image: false, size: 1000, x: 0, y: 0, ratio: 1, lock: 'disabled'}},
gui: {name: 'gui', background: {image: './assets/inventory.png', size: 1020, x: 0, y: 0, ratio: 1, lock: false}}
}
if (localStorage.getItem('canvas_scenes') != null && reset != true) {
var stored_canvas_scenes = JSON.parse(localStorage.getItem('canvas_scenes'))
$.extend(canvas_scenes, stored_canvas_scenes)
}
active_scene = canvas_scenes.normal
}
//Color
function initUIColor(event) {
var type = $(event.target).attr('id').split('color_')[1]
$('input#color_'+type).val(app_colors[type].hex)
}
function changeUIColor(event) {
var type = $(event.target).attr('id').split('color_')[1]
app_colors[type].hex = $('input#color_'+type).val()
updateUIColor()
}
function changeUIFont(type) {
var font = $('#layout_font_'+type).val()
app_colors[type].font = font
if (type === 'main') {
$('body').css('font-family', app_colors[type].font)
} else {
$('h1, h2, h3, h4, h5').css('font-family', app_colors[type].font)
}
}
function updateUIColor() {
for (var type in app_colors) {
if (app_colors.hasOwnProperty(type)) {
if (type === 'css') {
$('style#bbstyle').text(app_colors.css)
} else if (app_colors[type].hex) {
document.body.style.setProperty('--color-'+type, app_colors[type].hex);
} else if (app_colors[type].font) {
if (type === 'main') {
$('body').css('font-family', app_colors[type].font)
} else {
$('h1, h2, h3, h4, h5').css('font-family', app_colors[type].font)
}
}
}
}
var grid_color = '0x'+app_colors.hover.hex.replace('#', '')
try {
three_grid.getObjectByName('grid').material.color = new THREE.Color(parseInt(grid_color, 16))
} catch(err) {}
localStorage.setItem('app_colors', JSON.stringify(app_colors))
}
function importLayout() {
Blockbench.import('bbstyle', function(content) {
applyBBStyle(content)
})
}
function applyBBStyle(data) {
if (typeof data === 'string') {
try {
data = JSON.parse(data)
} catch(err) {
console.log(err)
return;
}
}
if (typeof data !== 'object') return;
$.extend(app_colors, data)
if (data.css) {
$('style#bbstyle').text(data.css)
setScreenRatio()
}
updateUIColor()
}
function exportLayout() {
Blockbench.export(autoStringify(app_colors), 'layout', 'bbstyle')
}
function showQuickMessage(message, time) {
var quick_message_box = $('<div id="quick_message_box" class="hidden"></div>')
$('body').append(quick_message_box)
quick_message_box.text(message)
quick_message_box.fadeIn(100)
setTimeout(function() {
quick_message_box.fadeOut(100)
setTimeout(function() {
quick_message_box.remove()
}, 100)
}, time ? time : 1000)
}
function showStatusMessage(message, time) { //Shows a quick message in the status bar
var status_message = $('#status_message')
var status_name = $('#status_name')
status_message.text(message)
status_name.hide(100)
status_message.show(100)
setTimeout(function() {
status_message.hide(100)
status_name.show(100)
}, time ? time : 600)
}
function setProgressBar(id, val, time) {
$('#'+id+' > .progress_bar_inner').animate({width: val*488}, time-1)
}
//Tooltip
function showShiftTooltip() {
$(':hover').find('.tooltip_shift').css('display', 'inline')
}
$(document).keyup(function(event) {
if (event.which === 16) {
$('.tooltip_shift').hide()
}
})
/*
function updateCubeList() {
Vue.nextTick(function() {
$('.cube_context').on('click', function(event) {
var ul = $(this).find('ul')
var pos = $(window).height() - event.clientY
if (pos < 110) {
ul.css('top', '-120px');
} else {
ul.css('top', '24px');
}
})
})
}*/
function setInterfaceMode(mode) {
$('.mode_tab').removeClass('open')
$('.mode_tab#mode_'+mode+'_tab').addClass('open')
setScreenRatio()
}
//Menu
function updateMenu() {
//Settings Dependent
$('header .settings_dependent').each(function(i, o) {
var set = $(o).attr('setting')
if (settings[set] && settings[set].value === true) {
$(o).text('check_box')
} else {
$(o).text('check_box_outline_blank')
}
})
}
//Mobile
function setMobileTab(mode) {
$('.mobile_mode_tab').removeClass('open')
$('#mobile_tab_'+mode).addClass('open')
//
$('.sidebar').css('grid-area', '')
$('#preview').css('grid-area', '')
$('header').css('grid-area', '')
switch (mode) {
case 'preview':
$('#preview').css('grid-area', 'main')
break;
case 'textures':
$('#left_bar').css('grid-area', 'main')
break;
case 'elements':
$('#right_bar').css('grid-area', 'main')
break;
case 'menu':
$('header').css('grid-area', 'main')
break;
}
setScreenRatio()
}

480
js/io.js Normal file
View File

@ -0,0 +1,480 @@
//IO
function buildBlockModel(options) { //Export Blockmodel
if (options === undefined) options = {}
var clear_elements = []
var textures_used = []
var element_index_lut = []
function computeCube(s) {
if (s.display.export == false) return;
//Create Element
var element = {}
$.extend(true, element, s)
element_index_lut[s.index()] = clear_elements.length
if (element.shade === true) {
delete element.shade
}
if (settings.minifiedout.value === true && element.name !== undefined) {
delete element.name
}
clear_elements.push(omitKeys(element, ['display', 'uuid', 'title', 'icon', 'isParent', 'buttons']))
//Gather Textures
for (var face in s.faces) {
if (s.faces.hasOwnProperty(face)) {
if (!textures_used.includes(s.faces[face].texture)) {
textures_used.push(s.faces[face].texture)
}
}
}
}
function iterate(arr) {
var i = 0;
if (!arr || !arr.length) {
console.log('return')
return;
}
for (i=0; i<arr.length; i++) {
if (arr[i].title === 'Cube') {
computeCube(arr[i])
console.log(arr[i])
} else if (arr[i].title === 'Group') {
console.log('g')
iterate(arr[i].children)
}
}
}
iterate(TreeElements)
clear_elements.forEach(function(s) {
for (var face in s.faces) {
if (s.faces.hasOwnProperty(face)) {
if (s.faces[face].texture === '$transparent') {
delete s.faces[face]
} else if (s.faces[face].texture == undefined) {
s.faces[face].texture = '#missing'
}
}
}
})
function checkExport(key, condition) {
key = options[key]
if (key === undefined) {
return condition;
} else {
return key
}
}
var texturesObj = {}
textures.forEach(function(s, i){
if (!textures_used.includes('#'+s.id)) return;
texturesObj[s.id] = s.javaTextureLink()
if (s.particle) {
texturesObj.particle = s.javaTextureLink()
}
})
var blockmodel = {}
if (checkExport('description', Project.description !== '')) {
blockmodel.description = Project.description;
}
if (checkExport('comment', settings.comment.value === true)) {
blockmodel.credit = settings.comment_text.value
}
if (checkExport('parent', Project.parent != '')) {
blockmodel.parent = Project.parent
}
if (checkExport('ambientocclusion', Project.ambientocclusion)) {
blockmodel.ambientocclusion = false
}
if (checkExport('textures', Object.keys(texturesObj).length >= 1)) {
blockmodel.textures = texturesObj
}
if (checkExport('elements', elements.length >= 1)) {
blockmodel.elements = clear_elements
}
if (checkExport('groups', settings.export_groups.value)) {
blockmodel.groups = compileGroups(undefined, element_index_lut)
}
if (checkExport('display', Object.keys(display).length >= 1)) {
blockmodel.display = display
}
if (options.raw) {
return blockmodel
} else {
return autoStringify(blockmodel)
}
}
function loadFile(data, filepath, makeNew) { //Load File Into GUI
var previous_length = 0
var previous_texture_length = 0
if (makeNew === true) {
//Create New Project
if (newProject() == false) return;
Prop.file_path = filepath
Prop.file_name = pathToName(Prop.file_path, true)
Project.name = pathToName(Prop.file_path, false)
if (Project.name.length > 0) {
$('title').text(Project.name+' - Blockbench')
} else {
$('title').text('Blockbench')
}
Prop.project_saved = true;
} else {
//Add to Current Project
previous_length = elements.length
previous_texture_length = textures.length
added_model_index++;
var import_group = new Group(pathToName(Prop.file_path, false))
}
data = JSON.parse(data)
//Check if PE Model
for (var key in data) {
if (key.includes('geometry.')) {
loadPEModelFile(data)
return;
}
}
settings.entity_mode.value = false;
saveSettings()
//Load
if (data.display !== undefined) {
display = data.display
}
if (data.elements) {
data.elements.forEach(function(s) {
base_cube = new Cube()
base_cube.extend(s)
for (var face in base_cube.faces) {
if (s.faces[face] === undefined) {
base_cube.faces[face].texture = '$transparent'
base_cube.faces[face].uv = [0,0,0,0]
}
}
base_cube.uuid = guid()
base_cube.display.autouv = false;
elements.push(base_cube);
if (makeNew === true) {
base_cube.addTo()
} else if (import_group) {
base_cube.addTo(import_group)
}
})
}
if (data.groups && data.groups.length > 0) {
parseGroups(data.groups)
if (import_group) {
TreeElements.forEach(function(s) {
s.addTo(import_group)
})
}
}
if (import_group) {
import_group.addTo()
}
//Create Path Array to fetch textures
var path_arr = filepath.split(osfs)
path_arr.splice(-3)
path_arr = path_arr.join(osfs)
var texture_arr = data.textures
var names = []
for (var tex in texture_arr) {
if (texture_arr.hasOwnProperty(tex)) {
if (tex != 'particle') {
var path = path_arr+osfs+'textures'+osfs+texture_arr[tex].split('/').join(osfs)+'.png'
new Texture({id: tex}).fromPath(path).add()
names.push(texture_arr[tex])
}
}
}
if (texture_arr === undefined) texture_arr = {}
if (texture_arr.particle) {
var path = path_arr+osfs+'textures'+osfs+texture_arr.particle.split('/').join(osfs)+'.png'
if (names.includes(texture_arr.particle)) {
textures.forEach(function(s) {
if (s.path == path) {
s.enableParticle()
}
})
} else {
new Texture({id: 'particle'}).enableParticle().fromPath(path).add()
}
}
//Get Rid Of ID overlapping
textures.forEach(function(t, i) {
if (i >= previous_texture_length) {
if (getTexturesById(t.id).length > 1) {
var before = t.id
t.id = added_model_index + '_' + t.id
elements.forEach(function(s, si) {
if (si >= previous_length) {
for (var face in s.faces) {
if (s.faces[face].texture === '#'+before) {
s.faces[face].texture = '#'+t.id
}
}
}
})
}
}
})
//Select Last Texture
if (textures.length > 0) {
textures.forEach(function(s) {
s.selected = false;
})
textures[textures.length-1].selected = true;
}
//Set Parent
if (data.parent !== undefined) {
Project.parent = data.parent;
}
//Set Ambient Occlusion
if (data.ambientocclusion === false) {
Project.ambientocclusion = false;
}
loadTextureDraggable()
Canvas.updateAll()
setUndo('Opened project')
if (makeNew) {
Prop.project_saved = true;
}
}
function loadPEModelFile(data) {
pe_list_data.length = 0
entityMode.join()
saveSettings()
for (var key in data) {
if (key.includes('geometry.') && data.hasOwnProperty(key)) {
var base_model = {name: key, bonecount: 0, selected: false, object: data[key]}
if (data[key].bones) {
base_model.bonecount = data[key].bones.length
}
pe_list_data.push(base_model)
}
}
if (pe_list == undefined) {
pe_list = new Vue({
el: '#pe_list',
data: {
search_text: '',
list: pe_list_data
},
methods: {
selectE: function(item, event) {
var index = pe_list_data.indexOf(item)
pe_list_data.forEach(function(s) {
s.selected = false;
})
pe_list_data[index].selected = true
}
},
computed: {
searched() {
var scope = this;
return this.list.filter(item => {
return item.name.toUpperCase().includes(scope.search_text)
})
}
}
})
} else {
// pe_list._data = {pe_list_data}
// pe_list.$forceUpdate();
}
showDialog('entity_import')
$('#pe_list').css('max-height', ($(window).height() - 320) +'px')
//texturelist._data.elements = textures
}
function loadPEModel() {
var data;
pe_list_data.forEach(function(s) {
if (s.selected === true) {
data = s
}
})
if (data == undefined) {
data = pe_list_data[0]
}
Project.parent = data.name
if (data.object.texturewidth !== undefined) {
Project.texture_width = data.object.texturewidth
}
if (data.object.textureheight !== undefined) {
Project.texture_height = data.object.textureheight
}
if (data.object.bones) {
data.object.bones.forEach(function(b) {
var group = new Group(b.name)
if (b.pivot) {
group.origin = b.pivot
} else {
group.origin = [0, 0, 0]
}
if (b.rotation) {
group.rotation = b.rotation
}
group.reset = b.reset === true
if (b.cubes) {
b.cubes.forEach(function(s) {
var base_cube = new Cube(b.name, true)
base_cube.display.autouv = false;
if (s.origin) {
base_cube.from = s.origin
if (s.size) {
base_cube.to[0] = s.size[0] + base_cube.from[0]
base_cube.to[1] = s.size[1] + base_cube.from[1]
base_cube.to[2] = s.size[2] + base_cube.from[2]
}
}
if (s.uv) {
base_cube.faces.north.uv[0] = (s.uv[0] / Project.texture_width) * 16
base_cube.faces.north.uv[1] = (s.uv[1] / Project.texture_height) * 16
base_cube.faces.north.uv[2] = 16
base_cube.faces.north.uv[3] = 16
}
elements.push(base_cube)
base_cube.addTo(group)
})
}
group.addTo()
})
}
pe_list_data.length = 0;
hideDialog()
loadTextureDraggable()
Canvas.updateAll()
setUndo('Opened entity model')
}
function buildEntityModel(options) {
var entitymodel = {}
entitymodel.texturewidth = Project.texture_width;
entitymodel.textureheight = Project.texture_height;
var bones = []
TreeElements.forEach(function(g) {
if (g.title !== 'Group') return;
//Bone
var bone = {}
bone.name = g.name
bone.pivot = g.origin
if (g.rotation.join('_') !== '0_0_0') {
bone.rotation = g.rotation
}
if (g.reset) {
bone.reset = true
}
//Cubes
bone.cubes = []
g.children.forEach(function(s) {
if (s === undefined) return;
if (s.display.export === false) return;
var cube = {}
cube.origin = s.from
cube.size = s.size()
cube.uv = [(s.faces.north.uv[0]/16) * Project.texture_width, (s.faces.north.uv[1]/16) * Project.texture_height]
bone.cubes.push(cube)
})
bones.push(bone)
})
entitymodel.bones = bones
return entitymodel
}
function buildOptifineModel() {
var jpm = {}
if (textures[0]) {
jpm.texture = pathToName(textures[0].name, false)
} else {
showQuickMessage('No texture found')
}
jpm.textureSize = [Project.texture_width, Project.texture_height]
if (settings.comment.value === true) {
jpm.credit = settings.comment_text.value
}
if (Project.description !== '') {
jpm.description = Project.description;
}
var submodels = []
elements.forEach(function(s) {
if (s.display.export === false) return;
var submodel = {boxes: [{}]}
var box = submodel.boxes[0]
submodel.id = s.name
box.coordinates = [s.from[0], s.from[1], s.from[2], s.size(0), s.size(1), s.size(2)]
for (var face in s.faces) {
if (s.faces.hasOwnProperty(face)) {
if (s.faces[face].texture !== undefined && s.faces[face].texture !== '$transparent') {
box['uv'+capitalizeFirstLetter(face)] = [
s.faces[face].uv[0] / 16 * Project.texture_width,
s.faces[face].uv[1] / 16 * Project.texture_height,
s.faces[face].uv[2] / 16 * Project.texture_width,
s.faces[face].uv[3] / 16 * Project.texture_height
]
}
}
}
submodels.push(submodel)
})
jpm.submodels = submodels
return autoStringify(jpm)
}
function newProject(entity_mode) {
if (showSaveDialog()) {
if (display_mode === true) exitDisplaySettings()
TextureAnimator
projectTagSetup()
elements.length = 0;
TreeElements.length = 1
TreeElements.splice(0, 1)
textures.length = 0
selected.length = 0
display = {}
Prop.file_path = 'Unknown';
Prop.file_name = '-';
$('title').text('Blockbench')
Canvas.updateAll()
outliner.$forceUpdate();
texturelist.$forceUpdate();
Undo.history.length = 0;
Undo.index = 0;
added_model_index = 0;
if (entity_mode) {
entityMode.join()
} else {
entityMode.leave()
}
setUndo('Created project')
return true;
} else {
return false;
}
}
function newEntityProject() {
newProject(function () {
settings.entity_mode.value = true
entity_mode.join()
})
}

13
js/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
js/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

202
js/mtlexport.js Normal file
View File

@ -0,0 +1,202 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.OBJExporter = function () {};
THREE.OBJExporter.prototype = {
constructor: THREE.OBJExporter,
parse: function ( object ) {
var output = '';
var materials = {};
var indexVertex = 0;
var indexVertexUvs = 0;
var indexNormals = 0;
var mtlFileName = 'objmaterial'; // maybe this value can be passed as parameter
output += 'mtllib ' + mtlFileName + '.mtl\n';
var parseMesh = function ( mesh ) {
var nbVertex = 0;
var nbVertexUvs = 0;
var nbNormals = 0;
var geometry = mesh.geometry;
var material = mesh.material;
if ( geometry instanceof THREE.Geometry ) {
output += 'o ' + mesh.name + '\n';
var vertices = geometry.vertices;
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
var vertex = vertices[ i ].clone();
vertex.applyMatrix4( mesh.matrixWorld );
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
nbVertex ++;
}
// uvs
var faces = geometry.faces;
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
var hasVertexUvs = faces.length === faceVertexUvs.length;
if ( hasVertexUvs ) {
for ( var i = 0, l = faceVertexUvs.length; i < l; i ++ ) {
var vertexUvs = faceVertexUvs[ i ];
for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) {
var uv = vertexUvs[ j ];
output += 'vt ' + uv.x + ' ' + uv.y + '\n';
nbVertexUvs ++;
}
}
}
// normals
var normalMatrixWorld = new THREE.Matrix3();
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
for ( var j = 0, jl = vertexNormals.length; j < jl; j ++ ) {
var normal = vertexNormals[ j ].clone();
normal.applyMatrix3( normalMatrixWorld );
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
} else {
var normal = face.normal.clone();
normal.applyMatrix3( normalMatrixWorld );
for ( var j = 0; j < 3; j ++ ) {
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
}
}
// material
if (material.name !== '')
output += 'usemtl ' + material.name + '\n';
else
output += 'usemtl material' + material.id + '\n';
materials[material.id] = material;
// faces
for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) {
var face = faces[ i ];
output += 'f ';
output += ( indexVertex + face.a + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ) + ' ';
output += ( indexVertex + face.b + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 1 ) : '' ) + '/' + ( indexNormals + j + 1 ) + ' ';
output += ( indexVertex + face.c + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 2 ) : '' ) + '/' + ( indexNormals + j + 2 ) + '\n';
}
} else {
console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh );
// TODO: Support only BufferGeometry and use use setFromObject()
}
// update index
indexVertex += nbVertex;
indexVertexUvs += nbVertexUvs;
indexNormals += nbNormals;
};
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) parseMesh( child );
} );
// mtl output
var mtlOutput = '';
for (var key in materials) {
var mat = materials[key];
if (mat.name !== '')
mtlOutput += 'newmtl ' + mat.name + '\n';
else
mtlOutput += 'newmtl material' + mat.id + '\n';
mtlOutput += 'Ns 10.0000\n';
mtlOutput += 'Ni 1.5000\n';
mtlOutput += 'd 1.0000\n';
mtlOutput += 'Tr 0.0000\n';
mtlOutput += 'Tf 1.0000 1.0000 1.0000\n';
mtlOutput += 'illum 2\n';
mtlOutput += 'Ka 0 0 1\n';
mtlOutput += 'Kd 0 0 1\n';
mtlOutput += 'Ks 0.0000 0.0000 0.0000\n';
mtlOutput += 'Ke 0.0000 0.0000 0.0000\n';
mtlOutput += 'map_Kd '+mat.materials[0].map.image.baseURI+'\n';
console.log(mat)
if (mat.map && mat.map instanceof THREE.Texture) {
var file = mat.map.image.currentSrc.slice( mat.map.image.currentSrc.slice.lastIndexOf("/"), mat.map.image.currentSrc.length - 1 );
mtlOutput += 'map_Ka ' + file + '\n';
mtlOutput += 'map_Kd ' + file + '\n';
}
}
return {
obj: output,
mtl: mtlOutput
}
}
};

318
js/plugin_loader.js Normal file
View File

@ -0,0 +1,318 @@
/*
Plugin Loader for Blockbench
By JannisX11
*/
var onUninstall, onInstall;
var Plugins = {
apipath: 'http://blockbench.net/api/plugins.json',
Vue: [], //Vue Object
installed: [], //Simple List of Names
json: undefined, //Json from website
data: [], //Vue Object Data
loadingStep: false,
updateSearch: function() {
Plugins.Vue._data.showAll = !Plugins.Vue._data.showAll
Plugins.Vue._data.showAll = !Plugins.Vue._data.showAll
},
devReload: function() {
Plugins.data.forEach(function(pl) {
if (pl.fromFile) {
pl.reload()
}
})
}
}
if (isApp) {
Plugins.path = __dirname.replace('resources'+osfs+'app.asar', 'plugins'+osfs)
fs.readdir(Plugins.path, function(err) {
if (err) {
fs.mkdir(Plugins.path, function(a) {})
}
})
} else {
Plugins.apipath = '../api/plugins.json'
}
$.getJSON('http://blockbench.net/api/plugins.json', function(data) {
Plugins.json = data
if (Plugins.loadingStep === true) {
loadInstalledPlugins()
} else {
Plugins.loadingStep = true
}
}).fail(function() {
console.log('Could not connect to plugin server')
$('#plugin_available_empty').text('Could not connect to plugin server')
if (Plugins.loadingStep === true) {
loadInstalledPlugins()
} else {
Plugins.loadingStep = true
}
})
$(document).ready(function() {
if (Plugins.loadingStep === true) {
loadInstalledPlugins()
} else {
Plugins.loadingStep = true
}
})
function loadInstalledPlugins() {
var storage_data = localStorage.getItem('installed_plugins')
if (storage_data !== null) {
Plugins.installed = JSON.parse(storage_data)
}
if (Plugins.json !== undefined) {
for (var id in Plugins.json) {
var plugin = Plugins.json[id]
var obj = {
id: id,
title: plugin.title,
author: plugin.author,
description: plugin.description,
icon: plugin.icon,
variant: plugin.variant,
installed: Plugins.installed.includes(id)
}
if (obj.installed) {
loadPlugin(id)
}
Plugins.data.push(obj)
Plugins.data.sort(function(a,b) {
return sort_collator.compare(a.title, b.title)
});
}
} else if (Plugins.installed.length > 0) {
Plugins.installed.forEach(function(id) {
loadPlugin(id, function() {
//Plugin Data Comes from the plugin file
if (plugin_data === undefined) return;
var obj = {
id: id,
title: plugin_data.title,
author: plugin_data.author,
description: plugin_data.description,
icon: plugin_data.icon,
variant: plugin_data.variant,
installed: true
}
Plugins.data.push(obj)
Plugins.data.sort(function(a,b) {
return sort_collator.compare(a.title, b.title)
});
})
})
}
if (Plugins.installed.length > 0) {
console.log('Loaded '+Plugins.installed.length+' plugin'+pluralS(Plugins.installed.length))
}
Plugins.Vue = new Vue({
el: '#plugin_list',
data: {
showAll: false,
items: Plugins.data
},
computed: {
installedPlugins() {
var name = $('#plugin_search_bar').val().toUpperCase()
return this.items.filter(item => {
if (this.showAll || item.installed) {
if (name.length > 0) {
return (
item.id.toUpperCase().includes(name) ||
item.title.toUpperCase().includes(name) ||
item.description.toUpperCase().includes(name) ||
item.author.toUpperCase().includes(name)
)
}
return true;
}
return false;
})
}
},
methods: {
install: function(event) {
var id = $(event.target.parentElement.parentElement).attr('plugin')
if (isApp) {
downloadPlugin(id)
} else {
loadPlugin(id)
}
},
uninstall: function() {
var id = $(event.target.parentElement.parentElement).attr('plugin')
uninstallPlugin(id)
},
update: function() {
if (isApp) {
var id = $(event.target.parentElement.parentElement).attr('plugin')
downloadPlugin(id)
}
},
checkIfInstallable: function(plugin) {
var result =
plugin.variant === 'both' ||
(
isApp === (plugin.variant === 'desktop') &&
isApp !== (plugin.variant === 'web')
);
return result;
}
}
})
}
function saveInstalledPlugins() {
localStorage.setItem('installed_plugins', JSON.stringify(Plugins.installed))
hideDialog()
}
function loadPlugin(id, cb, install) {
if (isApp === true) {
$.getScript(Plugins.path + id + '.js', function(a) {
if (onUninstall) {
Plugins.data.findInArray('id', id).uninstall = onUninstall
onUninstall = undefined
}
if (install && onInstall) {
onInstall()
}
onInstall = undefined
if (cb !== undefined) cb()
}).fail(function() {
console.log('Could not find file of plugin "'+id+'". Uninstalling it instead.')
var index = Plugins.installed.indexOf(id)
if (index > -1) {
Plugins.installed.splice(index, 1)
}
var data_obj = Plugins.data.findInArray('id', id)
data_obj.installed = false
if (data_obj.uninstall) {
data_obj.uninstall()
}
})
} else {
$.getScript('http://blockbench.net/api/plugins/'+id+'.js', function() {
if (onUninstall) {
Plugins.data.findInArray('id', id).uninstall = onUninstall
onUninstall = undefined
}
if (install && onInstall) {
onInstall()
}
onInstall = undefined
if (cb) cb()
})
}
if (Plugins.installed.includes(id) === false) {
Plugins.installed.push(id)
}
Plugins.data.findInArray('id', id).installed = true
}
function loadPluginFromFile() {
function readFromPluginFile(content, path, hideWarning) {
if (!hideWarning) {
if (isApp) {
if (!confirm('Do you want to allow this plugin to make changes to your PC? Only load plugins from people you trust.')) return;
} else {
if (!confirm('Do you want to load this plugin? Only load plugins from people you trust.')) return;
}
}
try {
eval(content)
} catch (err) {
showQuickMessage('Invalid Plugin File, See Console')
console.error(err)
return;
}
var obj = {
author: 'x11',
icon: 'refresh',
installed: true,
id: 'test',
title: 'Plugin',
variant: 'both',
description: '',
fromFile: true,
filePath: path,
uninstall: function() {
var index = Plugins.data.indexOf(this)
if (index >= 0) Plugins.data.splice(index, 1)
if (this.uninstallMethod) {
this.uninstallMethod()
}
},
reload: function() {
if (isApp) {
obj.uninstall()
fs.readFile(path, 'utf-8', function (err, data) {
if (err) {
console.log(err)
return;
}
readFromPluginFile(data, path, true)
})
}
},
uninstallMethod: false
}
$.extend(true, obj, plugin_data)
obj.uninstallMethod = onUninstall
onUninstall = undefined
Plugins.data.push(obj)
Plugins.data.sort(function(a,b) {
return sort_collator.compare(a.title, b.title)
});
}
Blockbench.import('.js', readFromPluginFile, ['bbplugin', 'js'])
}
function downloadPlugin(id) {
//$('.uc_btn').attr('disabled', true)
var file = originalFs.createWriteStream(Plugins.path+id+'.js')
var request = http.get('http://blockbench.net/api/plugins/'+id+'.js', function(response) {
response.pipe(file);
response.on('end', function() {
setTimeout(function() {
loadPlugin(id, undefined, true)
}, 100)
})
});
}
function uninstallPlugin(id) {
if (isApp) {
var filepath = Plugins.path + id + '.js'
if (fs.existsSync(filepath)) {
fs.unlink(filepath, (err) => {
if (err) {
console.log(err);
return;
}
});
} else {
//File does not exist
}
}
var index = Plugins.installed.indexOf(id)
if (index > -1) {
Plugins.installed.splice(index, 1)
}
var data_obj = Plugins.data.findInArray('id', id)
data_obj.installed = false
if (data_obj.uninstall) {
data_obj.uninstall()
}
}
function switchPluginTabs(installed) {
$('#plugins .tab').removeClass('open')
if (installed) {
$('#installed_plugins').addClass('open')
Plugins.Vue._data.showAll = false
} else {
$('#all_plugins').addClass('open')
Plugins.Vue._data.showAll = true
}
}

560
js/settings.js Normal file
View File

@ -0,0 +1,560 @@
var keybinds, settings, display_presets;
var Project = new Object()
projectTagSetup()
keybindSetup()
settingSetup()
displayPresetsSetup()
$(document).keydown(function(e) {
holding_shift = e.shiftKey;
});
$(document).keyup(function(e) {
holding_shift = false;
});
//Setup
function keybindSetup(get) {
var obj = {
headline1: {is_title: true, title: "Misc"},
canvas_rotate: {shift: false, ctrl: false, alt: false, code: 1, name: 'Rotate View', char: 'Left-Click', update: true},
canvas_drag:{shift: false, ctrl: false, alt: false, code: 3, name: 'Drag View', char: 'Right-Click', update: true},
confirm: {shift: false, ctrl: false, alt: false, code: 13, name: 'Confirm', char: 'ENTER'},
cancel: {shift: false, ctrl: false, alt: false, code: 27, name: 'Cancel', char: 'ESCAPE'},
screenshot_clean:{shift: false, ctrl: true, alt: false, code: 80, name: 'Screenshot', char: 'Ctrl + P'},
headline2: {is_title: true, title: "File"},
open_file: {shift: false, ctrl: true, alt: false, code: 79, name: 'Open File', char: 'Ctrl + O'},
save: {shift: false, ctrl: true, alt: false, code: 83, name: 'Save', char: 'Ctrl + S'},
save_as: {shift: true, ctrl: true, alt: false, code: 83, name: 'Save As', char: 'Ctrl + Shift + S'},
open_texture: {shift: false, ctrl: true, alt: false, code: 84, name: 'Import Texture', char: 'Ctrl + T'},
toggle_mode:{shift: false, ctrl: true, alt: false, code: 9, name: 'Toggle Mode', char: 'Ctrl + TAB'},
settings: {shift: false, ctrl: true, alt: false, code: 69, name: 'Settings', char: 'Ctrl + E'},
headline3: {is_title: true, title: "Edit"},
undo: {shift: false, ctrl: true, alt: false, code: 90, name: 'Undo', char: 'Ctrl + Z'},
redo: {shift: false, ctrl: true, alt: false, code: 89, name: 'Redo', char: 'Ctrl + Y'},
create_selection:{shift: false, ctrl: true, alt: false, code: 70, name: 'Create Selection', char: 'Ctrl + F'},
select_all: {shift: false, ctrl: true, alt: false, code: 65, name: 'Select All', char: 'Ctrl + A'},
invert_select:{shift:false,ctrl: true, alt: false, code: 65, name: 'Select All', char: 'Ctrl + A'},
add_cube: {shift: false, ctrl: true, alt: false, code: 78, name: 'Add Cube', char: 'Ctrl + N'},
new_group: {shift: false, ctrl: true, alt: false, code: 71, name: 'Add Group', char: 'Ctrl + G'},
duplicate: {shift: false, ctrl: true, alt: false, code: 68, name: 'Duplicate Cube', char: 'Ctrl + D'},
delete: {shift: false, ctrl: false, alt: false,code: 46, name: 'Delete Selected', char: 'DELETE'},
rename: {shift: false, ctrl: false, alt: false,code: 113,name: 'Rename', char: 'F2'},
headline4: {is_title: true, title: "Textures"},
uv_copy: {shift: false, ctrl: true, alt: false, code: 67, name: 'Copy UV', char: 'Ctrl + C'},
uv_copy_all:{shift: true, ctrl: true, alt: false, code: 67, name: 'Copy UV All', char: 'Ctrl + Shift + C'},
uv_paste: {shift: false, ctrl: true, alt: false, code: 86, name: 'Paste UV', char: 'Ctrl + V'},
uv_paste_all:{shift: true, ctrl: true, alt: false, code: 86, name: 'Paste UV All', char: 'Ctrl + Shift + V'},
headline5: {is_title: true, title: "Display Mode"},
copy_disp: {shift: false, ctrl: true, alt: false, code: 67, name: 'Copy Display Settings', char: 'Ctrl + C'},
paste_disp: {shift: false, ctrl: true, alt: false, code: 86, name: 'Paste Display Settings', char: 'Ctrl + V'},
reload_tex: {shift: false, ctrl: true, alt: false, code: 82, name: 'Reload Textures', char: 'Ctrl + R'},
headline6: {is_title: true, title: "Tool"},
tool_translate:{shift: false, ctrl: false, alt: false, code: 86, name: 'Move Tool', char: 'V'},
tool_scale: {shift: false, ctrl: false, alt: false, code: 83, name: 'Scale Tool', char: 'S'},
tool_brush: {shift: false, ctrl: false, alt: false, code: 66, name: 'Brush', char: 'B'},
tool_swap: {shift: false, ctrl: false, alt: false, code: 32, name: 'Swap Move and Scale', char: 'SPACE'},
headline7: {is_title: true, title: "Movement"},
move_north: {shift: false, ctrl: false, alt: false, code: 38, name: 'Move South', char: 'ARROWUP'},
move_south: {shift: false, ctrl: false, alt: false, code: 40, name: 'Move North', char: 'ARROWDOWN'},
move_west: {shift: false, ctrl: false, alt: false, code: 37, name: 'Move West', char: 'ARROWLEFT'},
move_east: {shift: false, ctrl: false, alt: false, code: 39, name: 'Move East', char: 'ARROWRIGHT'},
move_up: {shift: false, ctrl: false, alt: false, code: 33, name: 'Move Up', char: 'PAGEUP'},
move_down: {shift: false, ctrl: false, alt: false, code: 34, name: 'Move Down', char: 'PAGEDOWN'},
headline8: {is_title: true, title: "View"},
wireframe: {shift: false, ctrl: false, alt: false, code: 90, name: 'Toggle Wireframe', char: 'Z'},
reset_view: {shift: false, ctrl: false, alt: false, code: 96, name: 'Reset View', char: 'NUMPAD 0'},
view_normal: {shift: false, ctrl: false, alt: false, code: 101, name: 'Normal View', char: 'NUMPAD 5'},
view_0: {shift: false, ctrl: false, alt: false, code: 104, name: 'Top View', char: 'NUMPAD 8'},
view_1: {shift: false, ctrl: false, alt: false, code: 98, name: 'Bottom View', char: 'NUMPAD 2'},
view_2: {shift: false, ctrl: false, alt: false, code: 100, name: 'South View', char: 'NUMPAD 4'},
view_3: {shift: false, ctrl: false, alt: false, code: 102, name: 'North View', char: 'NUMPAD 6'},
view_4: {shift: false, ctrl: false, alt: false, code: 103, name: 'East View', char: 'NUMPAD 7'},
view_5: {shift: false, ctrl: false, alt: false, code: 105, name: 'West View', char: 'NUMPAD 9'}
}
if (get !== true) {
keybinds = obj
if (localStorage.getItem('keybinds') != null) {
var stored_keys = JSON.parse(localStorage.getItem('keybinds'))
for (var key in stored_keys) {
if (stored_keys.hasOwnProperty(key) && !stored_keys[key].is_title && keybinds.hasOwnProperty(key)) {
keybinds[key].shift = stored_keys[key].shift
keybinds[key].ctrl = stored_keys[key].ctrl
keybinds[key].alt = stored_keys[key].alt
keybinds[key].code = stored_keys[key].code
keybinds[key].char = stored_keys[key].char
}
}
}
} else {
return obj;
}
}
function settingSetup() {
settings = {
//Preview
headline2: {is_title: true, title: "Preview"},
origin: {value: true, name: 'Rotation Origin', desc: 'Show object origin'},
control_size: {value: 10, is_number: true, name: 'Axis Control Size', desc: 'Size of the 3 axis control tool'},
shading: {value: true, name: 'Shading', desc: 'Enable shading'},
transparency: {value: true, name: 'Transparency', desc: 'Render transparent textures transparent'},
texture_fps: {value: 2, is_number: true, name: 'Animated Texture FPS', desc: 'Frames per second for animated textures'},
status_bar: {value: true, name: 'Status Bar', desc: 'Show the status bar that displays fps etc.'},
swap_sidebar: {value: false, name: 'Swap Sidebars', desc: 'Swaps the right and the left sidebar'},
//Grid
headline1: {is_title: true, title: "Grid"},
base_grid: {value: true, name: 'Small Grid', desc: 'Show small grid and axes'},
large_grid: {value: false, name: 'Large Grid', desc: 'Show 3x3 block grid'},
full_grid: {value: false, name: 'Full Large Grid', desc: 'Show 3x3 precise grid'},
large_box: {value: false, name: 'Large Box', desc: 'Show 3x3 block boundaries'},
display_grid: {value: true, name: 'Display Mode', desc: 'Show grid in display mode'},
//Edit
headline3: {is_title: true, title: "Edit"},
entity_mode: {value: false, name: 'Entity Model Mode', desc: 'Unrestricted editing mode for Bedrock and Optifine models'},
undo_limit: {value: 20, is_number: true, name: 'Undo Limit', desc: 'Number of steps you can undo'},
move_origin: {value: false, name: 'Move on Relative Axes', desc: 'Move rotated elements on their own axes if possible'},
snapnslide: {value: false, name: 'Snap Slider', desc: 'Snaps combo-sliders to their valid positions'},
autouv: {value: true, name: 'Auto UV', desc: 'Enable AutoUV by default'},
create_rename:{value: false, name: 'Rename new Cube', desc: 'Focus name field when creating new element or group'},
canvas_unselect:{value: false, name: 'Canvas Click Unselect', desc: 'Unselects all elements when clicking on the canvas background'},
edit_size: {value: 16, is_number: true, name: 'Grid Resolution', desc: 'Resolution of the grid that cubes snap to'},
show_actions: {value: false, name: 'Tell Actions', desc: 'Display every action in the status bar'},
//Export
headline4: {is_title: true, title: "Export"},
minifiedout: {value: false,name: 'Minified Export', desc: 'Write JSON file in one line'},
max_json_length:{value: 56, is_number: true, name: 'Maximum Line Length', desc: 'Break JSON lines after this number'},
round_digits: {value: 4, is_number: true, name: 'Round numbers', desc: 'Round numbers'},
export_groups:{value: true, name: 'Export Groups', desc: 'Save groups in blockmodel files'},
obj_textures: {value: true, name: 'Export Textures', desc: 'Export textures when exporting OBJ file'},
comment: {value: true, name: 'File Comment', desc: 'Add a credit comment to file'},
comment_text: {value: 'Made with Blockbench, a free, modern block model editor by JannisX11', is_string: true},
default_path: {value: false, hidden: true}
}
if (localStorage.getItem('settings') != null) {
var stored_settings = JSON.parse(localStorage.getItem('settings'))
for (var key in stored_settings) {
if (stored_settings.hasOwnProperty(key) && !stored_settings[key].is_title && settings.hasOwnProperty(key)) {
settings[key].value = stored_settings[key].value
}
}
if (settings.edit_size.value < 3) {
settings.edit_size.value = 16
}
}
}
function projectTagSetup() {
Project.name = "";
Project.parent = "";
Project.description = "";
Project.texture_width = 64;
Project.texture_height = 32;
Project.ambientocclusion = true;
}
function displayPresetsSetup() {
display_presets = [
{name: 'Vanilla Item', fixed: true, areas: {
ground: {
rotation: [ 0, 0, 0 ],
translation: [ 0, 2, 0],
scale:[ 0.5, 0.5, 0.5 ]
},
head: {
rotation: [ 0, 180, 0 ],
translation: [ 0, 13, 7],
scale:[ 1, 1, 1]
},
thirdperson_righthand: {
rotation: [ 0, 0, 0 ],
translation: [ 0, 3, 1 ],
scale: [ 0.55, 0.55, 0.55 ]
},
thirdperson_lefthand: {
rotation: [ 0, 0, 0 ],
translation: [ 0, 3, 1 ],
scale: [ 0.55, 0.55, 0.55 ]
},
firstperson_righthand: {
rotation: [ 0, -90, 25 ],
translation: [ 1.13, 3.2, 1.13],
scale: [ 0.68, 0.68, 0.68 ]
},
firstperson_lefthand: {
rotation: [ 0, -90, 25 ],
translation: [ 1.13, 3.2, 1.13],
scale: [ 0.68, 0.68, 0.68 ]
},
fixed: {
rotation: [ 0, 180, 0 ],
translation: [ 0, 0, 0 ],
scale: [ 1, 1, 1 ],
}
}
},
{name: 'Vanilla Block', fixed: true, areas: {
gui: {
rotation: [ 30, 225, 0 ],
translation: [ 0, 0, 0],
scale:[ 0.625, 0.625, 0.625 ]
},
ground: {
rotation: [ 0, 0, 0 ],
translation: [ 0, 3, 0],
scale:[ 0.25, 0.25, 0.25 ]
},
fixed: {
rotation: [ 0, 0, 0 ],
translation: [ 0, 0, 0],
scale:[ 0.5, 0.5, 0.5 ]
},
thirdperson_righthand: {
rotation: [ 75, 45, 0 ],
translation: [ 0, 2.5, 0],
scale: [ 0.375, 0.375, 0.375 ]
},
thirdperson_lefthand: {
rotation: [ 75, 45, 0 ],
translation: [ 0, 2.5, 0],
scale: [ 0.375, 0.375, 0.375 ]
},
firstperson_righthand: {
rotation: [ 0, 45, 0 ],
translation: [ 0, 0, 0 ],
scale: [ 0.40, 0.40, 0.40 ]
},
firstperson_lefthand: {
rotation: [ 0, 225, 0 ],
translation: [ 0, 0, 0 ],
scale: [ 0.40, 0.40, 0.40 ]
}
}
},
{name: 'Vanilla Handheld', fixed: true, areas: {
thirdperson_righthand: {
rotation: [ 0, -90, 55 ],
translation: [ 0, 4.0, 0.5 ],
scale: [ 0.85, 0.85, 0.85 ]
},
thirdperson_lefthand: {
rotation: [ 0, 90, -55 ],
translation: [ 0, 4.0, 0.5 ],
scale: [ 0.85, 0.85, 0.85 ]
},
firstperson_righthand: {
rotation: [ 0, -90, 25 ],
translation: [ 1.13, 3.2, 1.13 ],
scale: [ 0.68, 0.68, 0.68 ]
},
firstperson_lefthand: {
rotation: [ 0, 90, -25 ],
translation: [ 1.13, 3.2, 1.13 ],
scale: [ 0.68, 0.68, 0.68 ]
}
}
},
{name: 'Vanilla Handheld Rod', fixed: true, areas: {
thirdperson_righthand: {
rotation: [ 0, 90, 55 ],
translation: [ 0, 4.0, 2.5 ],
scale: [ 0.85, 0.85, 0.85 ]
},
thirdperson_lefthand: {
rotation: [ 0, -90, -55 ],
translation: [ 0, 4.0, 2.5 ],
scale: [ 0.85, 0.85, 0.85 ]
},
firstperson_righthand: {
rotation: [ 0, 90, 25 ],
translation: [ 0, 1.6, 0.8 ],
scale: [ 0.68, 0.68, 0.68 ]
},
firstperson_lefthand: {
rotation: [ 0, -90, -25 ],
translation: [ 0, 1.6, 0.8 ],
scale: [ 0.68, 0.68, 0.68 ]
}
}
}
]
if (localStorage.getItem('display_presets') != null) {
var stored_display_presets = JSON.parse(localStorage.getItem('display_presets'))
$.extend(display_presets, stored_display_presets)
}
}
$(document).keydown(function(e) {
if (e.which === 16) {
showShiftTooltip()
}
if (e.ctrlKey === true && e.which == 73 && isApp) {
app.getCurrentWindow().toggleDevTools()
}
if (open_dialog !== false) {
if (open_dialog === 'uv_dialog') {
if (compareKeys(e, keybinds.uv_copy)) {
uv_dialog.copy(e)
}
if (compareKeys(e, keybinds.uv_paste)) {
uv_dialog.paste(e)
}
}
if (compareKeys(e, keybinds.confirm)) {
$('.dialog#'+open_dialog).find('.confirm_btn:not([disabled])').click()
} else if (compareKeys(e, keybinds.cancel) === true) {
$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()
}
return;
}
if (currently_renaming === true) {
if (compareKeys(e, keybinds.confirm)) {
stopRenameCubes()
}
return;
}
if ($('input[type="text"]:focus, input[type="number"]:focus, div[contenteditable="true"]:focus').length > 0) {
if (compareKeys(e, keybinds.confirm)) {
$(document).click()
}
return;
}
if (compareKeys(e, keybinds.screenshot_clean)) {
Screencam.cleanCanvas()
}
if (compareKeys(e, keybinds.open_file)) {
openFile(true)
}
if (compareKeys(e, keybinds.save)) {
saveFile()
}
if (compareKeys(e, keybinds.save_as)) {
saveFileBlock()
}
if (compareKeys(e, keybinds.open_texture)) {
openTexture()
}
if (compareKeys(e, keybinds.toggle_mode)) {
display_mode ? exitDisplaySettings() : enterDisplaySettings()
}
if (compareKeys(e, keybinds.settings)) {
showDialog('settings');setSettingsTab('setting')
}
if (compareKeys(e, keybinds.wireframe)) {
toggleWireframe()
}
if (display_mode === false) {
//Edit Mode
if (compareKeys(e, keybinds.undo)) {
Undo.undo()
} else if (compareKeys(e, keybinds.redo)) {
Undo.redo()
}
if (compareKeys(e, keybinds.add_cube)) {
addCube(0,0,0,canvas_grid,canvas_grid,canvas_grid)
}
if (compareKeys(e, keybinds.new_group)) {
addGroup()
}
if (compareKeys(e, keybinds.duplicate)) {
duplicateCubes()
}
if (compareKeys(e, keybinds.rename)) {
renameCubes()
}
if (compareKeys(e, keybinds.select_all)) {
e.preventDefault()
selectAll()
}
if (compareKeys(e, keybinds.delete)) {
if ($(':focus, .editing').length == 0) {
deleteCubes()
}
}
if (compareKeys(e, keybinds.reload_tex) === true && isApp) {
reloadTextures()
}
if (compareKeys(e, keybinds.create_selection)) {
showDialog('selection_creator')
}
if (compareKeys(e, keybinds.tool_translate)) {
setTool('translate')
} else if (compareKeys(e, keybinds.tool_scale)) {
setTool('scale')
} else if (compareKeys(e, keybinds.tool_brush)) {
setTool('brush')
} else if (compareKeys(e, keybinds.tool_swap)) {
toggleTools()
}
if (selected.length > 0) {
//Selected
if (compareKeys(e, keybinds.uv_copy)) {
main_uv.copy({shiftKey: false})
}
if (compareKeys(e, keybinds.uv_copy_all)) {
main_uv.copy({shiftKey: true})
}
if (compareKeys(e, keybinds.uv_paste)) {
main_uv.paste({shiftKey: false})
}
if (compareKeys(e, keybinds.uv_paste_all)) {
main_uv.paste({shiftKey: true})
}
if (compareKeys(e, keybinds.move_north)) {
moveCubesRelative(-1, 2)
}
if (compareKeys(e, keybinds.move_south)) {
moveCubesRelative(1, 2)
}
if (compareKeys(e, keybinds.move_west)) {
moveCubesRelative(-1, 0)
}
if (compareKeys(e, keybinds.move_east)) {
moveCubesRelative(1, 0)
}
if (compareKeys(e, keybinds.move_up)) {
moveCubesRelative(-1, 1)
}
if (compareKeys(e, keybinds.move_down)) {
moveCubesRelative(1, 1)
}
}
//View
if (compareKeys(e, keybinds.view_normal)) {
setCameraType('pers')
} else if (compareKeys(e, keybinds.reset_view)) {
resetCamera()
//Ortho
} else if (compareKeys(e, keybinds.view_0)) {
setCameraType('ortho', 0)
} else if (compareKeys(e, keybinds.view_1)) {
setCameraType('ortho', 1)
} else if (compareKeys(e, keybinds.view_2)) {
setCameraType('ortho', 2)
} else if (compareKeys(e, keybinds.view_3)) {
setCameraType('ortho', 3)
} else if (compareKeys(e, keybinds.view_4)) {
setCameraType('ortho', 4)
} else if (compareKeys(e, keybinds.view_5)) {
setCameraType('ortho', 5)
}
} else if (display_mode === true) { //Display Mode
if (compareKeys(e, keybinds.copy_disp)) {
copyDisplaySlot()
}
if (compareKeys(e, keybinds.paste_disp)) {
pasteDisplaySlot()
}
}
})
function saveLocalStorages() {
localStorage.setItem('canvas_scenes', JSON.stringify(canvas_scenes))
localStorage.setItem('settings', JSON.stringify(omitKeys(settings, ['name', 'desc'], true)) )
}
function saveSettings() {
updateMenu()
for (var mat in Canvas.materials) {
if (Canvas.materials.hasOwnProperty(mat))
Canvas.materials[mat].transparent = settings.transparency.value
}
setScreenRatio()
calcCanvasGridSize()
buildGrid()
setShading()
if (settings.snapnslide.value === true) {
$('.nslide').draggable( "option", "grid", [ 50, 100 ] );
} else {
$('.nslide').draggable( "option", "grid", false );
}
if (settings.swap_sidebar.value === true) {
$('body').addClass('rtl')
} else {
$('body').removeClass('rtl')
}
if (settings.status_bar.value) {
$('body').css('grid-template-rows', '32px calc(100% - 58px) 26px')
} else {
$('body').css('grid-template-rows', '32px calc(100% - 32px) 0px')
}
if (entityMode.state !== settings.entity_mode.value) {
entityMode.state = settings.entity_mode.value
settings.entity_mode.value ? entityMode.join() : entityMode.leave()
}
TextureAnimator.updateSpeed()
hideDialog()
updateUIColor()
updateSelection()
Blockbench.dispatchEvent( 'update_settings')
}
function toggleSetting(setting) {
if (settings[setting].value === true) {
settings[setting].value = false
} else {
settings[setting].value = true
}
saveSettings()
}
function toggleWireframe() {
Prop.wireframe = !Prop.wireframe
Canvas.updateAll()
}
var entityMode = {
state: false,
join: function() {
settings.entity_mode.value = true
$('body').addClass('entity_mode')
$('label[for="project_parent"]').text('Mob Geometry Name')
$('#cube_rescale_tool div').text('Reset Bone')
$('input#cube_rotate').attr('min', '-180').attr('max', '180').attr('step', '5.625').addClass('entity_mode')
main_uv.buildDom().setToMainSlot().setFace('north')
$('.block_mode_only').hide()
},
leave: function() {
settings.entity_mode.value = false
$('body').removeClass('entity_mode')
$('label[for="project_parent"]').text('Parent Model')
$('#cube_rescale_tool div').text('Rescale')
$('input#cube_rotate').attr('min', '-67.5').attr('max', '67.5').attr('step', '22.5').removeClass('entity_mode')
$('.block_mode_only').show()
main_uv.buildDom(true).setToMainSlot()
elements.forEach(function(s, i) {
//Push elements into 3x3 block box
[0, 1, 2].forEach(function(ax) {
var overlap = s.from[ax] + s.to[ax] - 32
if (overlap > 0) {
//If positive site overlaps
s.from[ax] -= overlap
s.to[ax] -= overlap
overlap = 16 + s.from[ax]
if (overlap < 0) {
s.from[ax] = -16
}
} else {
overlap = s.from[ax] + 16
if (overlap < 0) {
s.from[ax] -= overlap
s.to[ax] -= overlap
if (s.from[ax] + s.to[ax] > 32) {
s.to[ax] = 32
}
}
}
})
})
}
}

412
js/textures.js Normal file
View File

@ -0,0 +1,412 @@
//Textures
class Texture {
constructor(data) {
this.path = ''
this.name = ''
this.folder = '';
this.iconpath = ''
this.particle = false
this.selected = false
this.error = false;
this.frameCount = 1
this.show_icon = true
this.average_color = {r:0, g:0, b:0}
this.dark_box = false
this.img = 0;
this.uuid = guid()
if (typeof data === 'object') {
this.extend(data)
}
if (!this.id) {
var i = 0;
while (true) {
var matches = $.grep(textures, function(e) {return e.id == i})
if (matches.length > 0) {
i++;
} else {
this.id = i;
return;
}
}
}
}
load(isDefault) {
var scope = this;
this.error = false;
this.show_icon = true
this.frameCount = 1
if (Canvas.materials[scope.uuid] !== undefined) {
Canvas.materials[scope.uuid].dispose()
}
var img = this.img = new Image()
img.src = this.iconpath
img.onerror = function() {
this.src = 'assets/missing.png'
scope.error = true;
scope.show_icon = false
console.log('Error loading '+scope.iconpath)
if (isApp && !isDefault) {
scope.fromDefaultPack()
}
}
var tex = new THREE.Texture(img)
img.tex = tex;
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.NearestFilter
img.onload = function() {
this.tex.needsUpdate = true;
scope.res = img.naturalWidth;
scope.average_color = getAverageRGB(this)
scope.dark_box = (scope.average_color.r + scope.average_color.g + scope.average_color.b) >= 383
//Width / Animation
if (img.naturalWidth !== img.naturalHeight) {
if (img.naturalHeight % img.naturalWidth === 0) {
scope.frameCount = img.naturalHeight / img.naturalWidth
Canvas.updateAllUVs()
} else if (settings.entity_mode.value === false) {
scope.error = true;
showQuickMessage('Texture needs to be square')
}
}
if (textures.indexOf(scope) === 0) {
Project.texture_width = img.naturalWidth
Project.texture_height = img.naturalHeight
}
if ($('.dialog#texture_edit:visible').length >= 1 && scope.selected === true) {
loadTextureMenu(scope)
}
TextureAnimator.updateButton()
Canvas.updateAllFaces()
}
var mat = new THREE.MeshLambertMaterial({color: 0xffffff, map: tex, transparent: settings.transparency.value});
Canvas.materials[this.uuid] = mat
return this;
}
fromPath(path) {
this.path = path
this.name = pathToName(path, true)
if (path.includes('data:image')) {
this.iconpath = path
} else {
this.iconpath = path + '?' + tex_version
}
this.generateFolder(path)
if (!isApp && Project.dataURLTextures) {
if (this.img && this.img.src) {
this.img.src = 'assets/missing.png'
}
this.error = true;
this.show_icon = false
} else {
this.load()
}
return this;
}
fromDataURL(data_url) {
this.path = this.folder+'/'+this.name
this.iconpath = data_url
this.load()
return this;
}
fromDefaultPack() {
if (settings.default_path && settings.default_path.value) {
console.log('Trying to get texture from default pack')
this.path = settings.default_path.value + osfs + this.folder + osfs + this.name
this.iconpath = this.path + '?' + tex_version
this.load(true)
}
}
reopen() {
var scope = this;
if (isApp) {
app.dialog.showOpenDialog(currentwindow, {filters: [{name: 'PNG Texture', extensions: ['png']}]}, function (fileNames) {
if (fileNames !== undefined) {
fs.readFile(fileNames[0], function (err) {
if (err) {
console.log(err)
}
scope.path = fileNames[0]
scope.iconpath = scope.path + '?' + tex_version;
scope.name = scope.path.split(osfs).slice(-1)[0]
if (scope.path.includes(osfs +'textures'+osfs)) {
var arr = scope.path.split(osfs+'textures'+osfs)
arr = arr[arr.length-1].split(osfs)
arr.pop()
scope.folder = arr.join('/')
} else {
var arr = scope.path.split(osfs)
scope.folder = arr[arr.length-2]
}
var img = new Image()
try {
img.src = fileNames[0]
} catch(err) {
img.src = 'missing.png'
}
var tex = new THREE.Texture(img)
img.tex = tex;
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.LinearMipMapLinearFilter
img.onload = function() {
this.tex.needsUpdate = true;
scope.res = img.naturalWidth;
}
Canvas.materials[scope.uuid] = new THREE.MeshBasicMaterial({color: 0xffffff, map: tex, transparent: true});
scope.load()
Canvas.updateAllFaces()
})
}
})
} else {
var file = $('.dialog:visible #texture_change').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
scope.iconpath = reader.result
var img = new Image()
try {
img.src = reader.result
} catch(err) {
console.log(err)
img.src = 'missing.png'
}
var tex = new THREE.Texture(img)
img.tex = tex;
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.LinearMipMapLinearFilter
img.onload = function() {
this.tex.needsUpdate = true;
scope.res = img.naturalWidth;
}
Canvas.materials[scope.uuid] = new THREE.MeshLambertMaterial({color: 0xffffff, map: tex, transparent: true});
scope.load()
Canvas.updateAllFaces()
main_uv.loadData()
}
if (file) {
reader.readAsDataURL(file)
}
}
Blockbench.dispatchEvent( 'change_texture_path', {texture: scope} )
}
refresh(single) {
if (single) {
tex_version++;
}
this.iconpath = this.path + '?' + tex_version;
this.iconpath = this.iconpath.replace(/\?\d+$/, '?' + tex_version)
this.load()
if (single) {
Canvas.updateAllFaces()
main_uv.loadData()
loadTextureDraggable()
}
}
reloadTexture() {
this.refresh(true)
}
enableParticle() {
textures.forEach(function(s) {
s.particle = false;
})
this.particle = true
return this;
}
javaTextureLink() {
return this.folder+'/'+this.name.split('.png').join('')
}
fillParticle() {
var particle_tex = false
textures.forEach(function(t) {
if (t.particle) {
particle_tex = t
}
})
if (!particle_tex) {
this.enableParticle()
}
return this;
}
select() {
textures.forEach(function(s) {
s.selected = false;
})
this.selected = true
textures.selected = this
return this;
}
generateFolder(path) {
if (path.includes(osfs+'textures'+osfs)) {
var arr = path.split(osfs+'textures'+osfs)
arr = arr[arr.length-1].split(osfs)
arr.pop()
this.folder = arr.join('/')
} else {
var arr = path.split(osfs)
this.folder = arr[arr.length-2]
}
return this;
}
add() {
if (!textures.includes(this)) {
textures.push(this)
}
Blockbench.dispatchEvent( 'add_texture', {texture: this})
loadTextureDraggable()
return this;
}
extend(properties) {
for (var key in properties) {
if (properties.hasOwnProperty(key)) {
this[key] = properties[key]
}
}
}
apply(all) {
if (selected.length === 0) return;
var scope = this;
if (all || settings.entity_mode.value) {
var sides = ['north', 'east', 'south', 'west', 'up', 'down']
} else {
var sides = [main_uv.face]
}
selected.forEach(function(s) {
sides.forEach(function(side) {
elements[s].faces[side].texture = '#'+scope.id
})
})
Canvas.updateSelectedFaces()
main_uv.loadData()
setUndo('Applied texture')
}
openFolder() {
if (!isApp) return;
shell.showItemInFolder(this.path)
}
remove() {
textures.splice(textures.indexOf(this), 1)
Canvas.updateAll()
$('#uv_frame').css('background', 'transparent')
TextureAnimator.updateButton()
hideDialog()
}
}
function applyTexture(all, id) {
if (selected.length === 0) return;
if (id === undefined) {
textures.forEach(function(s) {
if (s.selected) {
id = s.id
}
})
}
if (id === undefined) return;
getTextureById(id).apply(all)
}
function reloadTextures() {
tex_version++;
textures.forEach(function(t) {
t.iconpath = t.path + '?' + tex_version;
t.refresh(false)
})
Canvas.updateAllFaces()
main_uv.loadData()
loadTextureDraggable()
}
function getSelectedTextureIndex() {
var index = false
textures.forEach(function(s, i) {
if (s.selected === true) {
index = i
}
})
return index;
}
function openTextureMenu(index) {
if (index === undefined) {
index = getSelectedTextureIndex()
if (index === false) return;
} else {
textures[index].select()
}
showDialog('texture_edit')
loadTextureMenu(textures.selected)
if (isApp) {
$('#texture_edit #change_file_button').click( function() {
textures.selected.reopen()
})
} else {
$('#texture_edit #texture_change').off('change')
$('#texture_edit #texture_change').on('change', function() {
textures.selected.reopen()
})
}
}
function loadTextureMenu(tex) {
var arr = tex.path.split(osfs)
arr.splice(-1)
var path = arr.join('<span class="slash">/</span>') + '<span class="slash">/</span><span class="accent_color">' + tex.name + '</span>'
$('#texture_edit #te_title').text(tex.name)
$('#texture_edit #te_path').html(path)
$('#texture_edit input#te_variable').val(tex.id)
$('#texture_edit input#te_folder').val(tex.folder)
$('#texture_menu_thumbnail').html(tex.img)
}
function saveTextureMenu() {
hideDialog()
index = getSelectedTextureIndex()
if (index === false) return;
var tex = textures[index]
tex.id = $('#texture_edit input#te_variable').val()
tex.folder = $('#texture_edit input#te_folder').val()
$('#texture_edit #change_file_button').unbind('click')
$('#texture_edit #file_upload').unbind('input')
}
function loadTextureDraggable() {
Vue.nextTick(function() {
setTimeout(function() {
$('li.texture').draggable({
revertDuration: 0,
helper: function(e) {
var t = $(e.target)
if (!t.hasClass('texture')) t = t.parent()
if (!t.hasClass('texture')) t = t.parent()
return t.find('.texture_icon_wrapper').clone().addClass('texture_drag_helper').attr('texid', t.attr('texid'))
},
cursorAt: { left: 24, top: 24 },
revert: 'invalid',
appendTo: 'body',
zIndex: 19,
stop: function(event, ui) {
setTimeout(function() {
if ($('canvas#canvas:hover').length > 0) {
if (canvasClick(event)) {
getTextureById(ui.helper.attr('texid')).apply()
}
}
}, 10)
}
})
}, 42)
})
}

43378
js/three.js Normal file

File diff suppressed because one or more lines are too long

86
js/tree.vue.js Normal file
View File

@ -0,0 +1,86 @@
(function () {
'use strict';
var VueTreeItem = Vue.extend({
template:
'<li class="outliner_node" v-bind:class="{ parent_li: node.children && node.children.length > 0}" v-bind:id="node.uuid">' +
'<div @contextmenu.prevent.stop="node.showContextMenu($event)" class="outliner_object" v-on:dblclick="node.rename($event)" v-on:click="node.select($event)" :title="node.title" v-bind:class="{ cube: node.title === \'Cube\', group: node.title === \'Group\', selected: node.display.isselected }">' +
//Opener
'<i v-if="node.children && node.children.length > 0" v-on:click="toggle(node)" class="fa icon-open-state" :class=\'{"fa-caret-right": !node.isOpen, "fa-caret-down": node.isOpen}\'></i>' +
'<i v-else class="outliner_opener_placeholder"></i>' +
//Main
'<i v-if="showIcon(node)" :class="nodeClass(node)"></i>' +
'<input type="text" class="cube_name" v-model="node.name" disabled>' +
'<a v-for="btn in node.buttons" class="ml5" href="javascript:" :title="btn.title" v-on:click.stop="btnClick(btn, node)" v-bind:class="{advanced_option: btn.advanced_option}">' +
'<i v-if="node.isIconEnabled(btn.title) === true" :class="btn.icon"></i>' +
'<i v-else :class="btn.icon_off"></i>' +
'</a>' +
'</div>' +
//Other Entries
'<ul v-show="node.isOpen">' +
//'<li v-show="node.showLoading && node._loading"><i class="fa fa-spinner fa-pulse"></i></li>' +
'<vue-tree-item v-for="item in node.children" :node="item" v-key="item.uuid"></vue-tree-item>' +
'</ul>' +
'</li>',
props: {
node: {
type: Object
}
},
methods: {
showIcon: function (node) {
return node.icon || node.openedIcon || node.closedIcon;
},
nodeClass: function (node) {
if (node.isOpen) {
return node.openedIcon || node.icon;
} else {
return node.closedIcon || node.icon;
}
},
toggle: function (node) {
if (node.hasOwnProperty('isOpen')) {
node.isOpen = !node.isOpen;
} else {
Vue.set(node, 'isOpen', true);
}
},
btnClick: function (btn, node) {
if (typeof btn.click === 'function') {
btn.click(node);
}
}
},
watch: {
'node.isOpen': function (val) {
if (!this.node.hasOwnProperty('_loading')) {
Vue.set(this.node, '_loading', false);
}
if (val) {
if (typeof this.node.onOpened === 'function') {
this.node.onOpened(this.node);
}
} else {
if (typeof this.node.onClosed === 'function') {
this.node.onClosed(this.node);
}
}
}
}
});
Vue.component('vue-tree-item', VueTreeItem);
var VueTree = Vue.extend({
template: '<div class="vue-tree"><ul>' +
'<tree-item :node.sync="option.root"></tree-item>' +
'</ul></div>',
props: {
option: {
type: Object
}
},
components: {
'tree-item': VueTreeItem
}
});
Vue.component('vue-tree', VueTree);
})();

302
js/util.js Normal file
View File

@ -0,0 +1,302 @@
var asyncLoop = function(o){
var i=-1;
var async_loop = function(){
i++;
if(i==o.length){o.callback(); return;}
o.functionToLoop(async_loop, i);
}
async_loop();//init
}
function pathToName(path, extension) {
var path_array = path.split('/').join('\\').split('\\')
if (extension) {
return path_array[path_array.length-1]
} else {
return path_array[path_array.length-1].split('.').slice(0, -1).join('.')
}
}
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
Array.prototype.equals = function (array) {
if (!array)
return false;
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
if (this[i] instanceof Array && array[i] instanceof Array) {
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
return false;
}
}
return true;
}
Array.prototype.remove = function (item) { {
var index = this.indexOf(item)
if (index > -1) {
this.splice(index, 1)
return index;
}
return false;
}
}
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
function omitKeys(obj, keys, dual_level) {
var dup = {};
for (key in obj) {
if (keys.indexOf(key) == -1) {
if (dual_level === true && typeof obj[key] === 'object') {
dup[key] = {}
for (key2 in obj[key]) {
if (keys.indexOf(key2) == -1) {
dup[key][key2] = obj[key][key2];
}
}
} else {
dup[key] = obj[key];
}
}
}
return dup;
}
function stringify (obj, options) {
options = options || {}
var indent = JSON.stringify([1], null, get(options, 'indent', 2)).slice(2, -3)
var maxLength = (indent === '' ? Infinity : get(options, 'maxLength', 80))
return (function _stringify (obj, currentIndent, reserved) {
if (obj && typeof obj.toJSON === 'function') {
obj = obj.toJSON()
}
var string = JSON.stringify(obj)
if (string === undefined) {
return string
}
var length = maxLength - currentIndent.length - reserved
if (string.length <= length) {
var prettified = prettify(string)
if (prettified.length <= length) {
return prettified
}
}
if (typeof obj === 'object' && obj !== null) {
var nextIndent = currentIndent + indent
var items = []
var delimiters
var comma = function (array, index) {
return (index === array.length - 1 ? 0 : 1)
}
if (Array.isArray(obj)) {
for (var index = 0; index < obj.length; index++) {
items.push(
_stringify(obj[index], nextIndent, comma(obj, index)) || 'null'
)
}
delimiters = '[]'
} else {
Object.keys(obj).forEach(function (key, index, array) {
var keyPart = JSON.stringify(key) + ': '
var value = _stringify(obj[key], nextIndent,
keyPart.length + comma(array, index))
if (value !== undefined) {
items.push(keyPart + value)
}
})
delimiters = '{}'
}
if (items.length > 0) {
return [
delimiters[0],
indent + items.join(',\n' + nextIndent),
delimiters[1]
].join('\n' + currentIndent)
}
}
return string
}(obj, '', 0))
}
var stringOrChar = /("(?:[^"]|\\.)*")|[:,]/g
function prettify (string) {
return string.replace(stringOrChar, function (match, string) {
return string ? match : match + ' '
})
}
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function trimFloatNumber(val) {
if (val == '') return val;
var string = val.toFixed(4)
string = string.replace(/0+$/g, '').replace(/\.$/g, '')
return string;
}
Array.prototype.findInArray = function(key, value) {
if (this.length === 0) return {};
var i = 0
while (i < this.length) {
if (this[i][key] === value) return this[i]
i++;
}
return {};
}
function get (options, name, defaultValue) {
return (name in options ? options[name] : defaultValue)
}
function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
function compareKeys(event, action) {
if (action &&
action.code === event.which &&
action.ctrl === event.ctrlKey &&
action.shift === event.shiftKey &&
action.alt === event.altKey) {
event.preventDefault()
return true;
} else {
return false;
}
}
function getAverageRGB(imgEl) {
var blockSize = 5, // only visit every 5 pixels
defaultRGB = {r:0,g:0,b:0}, // for non-supporting envs
canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
data, width, height,
i = -4,
length,
rgb = {r:0,g:0,b:0},
count = 0;
if (!context) {
return defaultRGB;
}
height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
context.drawImage(imgEl, 0, 0);
try {
data = context.getImageData(0, 0, width, height);
} catch(e) {
/* security error, img on diff domain */alert('x');
return defaultRGB;
}
length = data.data.length;
while ( (i += blockSize * 4) < length ) {
++count;
rgb.r += data.data[i];
rgb.g += data.data[i+1];
rgb.b += data.data[i+2];
}
// ~~ used to floor values
rgb.r = ~~(rgb.r/count);
rgb.g = ~~(rgb.g/count);
rgb.b = ~~(rgb.b/count);
return rgb;
}
function autoStringify(object) {
if (settings.minifiedout.value === true) {
var string = JSON.stringify(object)
} else {
var string = stringify(object, {indent: '\t', maxLength: parseInt(settings.max_json_length.value)})
}
string.replace(/-?[0-9]+\.-?[0-9]{5,16}/g, function(s) {
var parts = s.split('.')
if (parts[1].length > settings.round_digits.value) {
return parts[0] + '.' + parts[1].substr(0, settings.round_digits.value)
} else {
return s;
}
})
return string;
}
function pluralS(arr) {
if (arr.length === 1 || arr === 1) {
return '';
} else {
return 's';
}
}
function getAxisLetter(number) {
switch (number) {
case 0: return 'x'; break;
case 1: return 'y'; break;
case 2: return 'z'; break;
}
}
function getAxisNumber(letter) {
switch (letter.toLowerCase()) {
case 'x': return 0; break;
case 'y': return 1; break;
case 'z': return 2; break;
}
}
function limitNumber(number, min, max) {
if (number > max) number = max;
if (number < min) number = min;
return number;
}
function getSnapFactor(event) {
if (event.shiftKey) {
return canvas_grid / 4;
} else if (event.ctrlKey) {
return canvas_grid / 10;
} else {
return canvas_grid;
}
}
function compareVersions(string1/*new*/, string2/*old*/) {
// Is string1 newer than string2 ?
var arr1 = string1.split('.')
var arr2 = string2.split('.')
var i = 0;
var num1 = 0;
var num2 = 0;
while (i < arr1.length) {
num1 = parseInt(arr1[i])
num2 = parseInt(arr2[i])
if (num1 > num2) {
return true;
} else if (num1 < num2) {
return false
}
i++;
}
return false;
}

1252
js/uv.js Normal file

File diff suppressed because it is too large Load Diff

8
js/vue.min.js vendored Normal file

File diff suppressed because one or more lines are too long

281
js/web.js Normal file
View File

@ -0,0 +1,281 @@
(function() {
$.getScript("js/file_saver.js");
})()
$('.open-in-browser').click((event) => {
event.preventDefault();
window.open(event.target.href, '_blank');
});
var lastImportEvent;
function tryLoadPOSTModel() {
if ($('#post_model').text() !== '') {
if ($('#post_textures').text() !== '') {
Project.dataURLTextures = true
}
loadFile($('#post_model').text(), 'model', true)
$('#post_model').remove()
if ($('#post_textures').text() !== '') {
var data = JSON.parse( $('#post_textures').text() )
for (var key in data) {
if (data.hasOwnProperty(key)) {
var tex = getTextureById(key+'');
if (!tex) return;
tex.img.src = ''
tex.iconpath = data[key]
}
}
textures.forEach(function(tex) {
tex.load()
})
}
return false;
} else {
return showSplashScreen
}
}
//Loader Open
function openFile(makeNew) {
g_makeNew = makeNew
fileLoaderLoad('.json', false, readFile)
$('#file_folder').val('')
}
function importExtrusion(makeNew) {
g_makeNew = makeNew
fileLoaderLoad('.png', true, readExtrusion)
}
//Texture
function openTexture() {
fileLoaderLoad('.png', true, readTexture)
}
function loadBackgroundImage(event) {
if (event !== undefined) {
if (event.altKey === true) {
textPrompt('Background Image Path', 'active_scene.background.image', true)
return;
}
}
fileLoaderLoad('image/*', false, readBackgroundImage)
}
//Main
function fileLoaderLoad(type, showInputs, importFunction) {
//Meta
$('#file_name').val('')
if (showInputs === true) {
$('#file_loader_meta').show()
} else {
$('#file_loader_meta').hide()
}
//Loader
$('#file_upload').attr('accept', type)
//Clear Events
try {
$('#web_import_btn')[0].removeEventListener('click', lastImportEvent)
$('#file_upload')[0].removeEventListener('change', lastImportEvent)
} catch (err) {}
//Add Events
$('#web_import_btn')[0].addEventListener('click', importFunction)
$('#file_upload')[0].addEventListener('change', function() {
var path_parts = $(this).val().split('\\')
$('#file_name').val(path_parts[path_parts.length-1])
})
lastImportEvent = importFunction
showDialog('file_loader')
}
//Loader Read
function readTexture() {
hideDialog()
var file = $('#file_upload').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
var path = reader.result
var name = $('#file_name').val()
if (name == undefined) {
name = 'Texture'
}
var folder = $('#file_folder').val()
if (folder == "") {
folder = "blocks"
}
new Texture({folder: folder, name: name}).add().fromDataURL(path).fillParticle()
}
if (file) {
reader.readAsDataURL(file)
} else {
}
}
function readFile() {
hideDialog()
var file = $('#file_upload').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
loadFile(reader.result, 'model', g_makeNew)
}
if (file) {
reader.readAsText(file)
} else {
}
}
function reopenTexture(texture) {
var file = $('.dialog:visible #texture_change').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
texture.iconpath = reader.result
var img = new Image()
try {
img.src = reader.result
} catch(err) {
console.log(err)
img.src = 'missing.png'
}
var tex = new THREE.Texture(img)
img.tex = tex;
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.LinearMipMapLinearFilter
var thisTexture = texture;
img.onload = function() {
this.tex.needsUpdate = true;
thisTexture.res = img.naturalWidth;
}
texture.material = new THREE.MeshBasicMaterial({color: 0xffffff, map: tex, transparent: true});
texture.reload()
Canvas.updateAllFaces()
Blockbench.dispatchEvent( 'change_texture_path', {texture: texture} )
}
if (file) {
reader.readAsDataURL(file)
}
}
function readExtrusion() {
hideDialog()
var file = $('#file_upload').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
if (g_makeNew) {
if (newProject() == false) return;
}
var path = reader.result
var name = $('#file_name').val()
if (name == undefined) {
name = 'Texture'
}
var folder = $('#file_folder').val()
if (folder == "") {
folder = "blocks"
}
new Texture({folder: folder, name: name}).add().fromDataURL(path).fillParticle()
showDialog('image_extruder')
drawExtrusionImage(path)
}
if (file) {
reader.readAsDataURL(file)
} else {
}
}
function readBackgroundImage() {
hideDialog()
var file = $('#file_upload').get(0).files[0]
var reader = new FileReader()
reader.onloadend = function() {
var path = reader.result
active_scene.background.image = path
enterScene(true)
}
if (file) {
reader.readAsDataURL(file)
}
}
//Saver
function saveFileBlock() {
saveFile()
}
function saveFileOptifine() {
var data = buildOptifineModel()
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
saveAs(blob, 'model.jpm')
showQuickMessage('Saved Optifine entity model')
}
function saveFileEntity() {
var obj = {}
var model_name = Project.parent
if (model_name == '') model_name = 'geometry.unknown'
obj[model_name] = buildEntityModel()
var data = autoStringify(obj)
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
saveAs(blob, 'model.json')
showQuickMessage('Saved as bedrock entity model')
}
function saveFileObj() {
scene.remove(three_grid)
scene.remove(Transformer)
var exporter = new THREE.OBJExporter();
var content = exporter.parse( scene, 'model');
scene.add(three_grid)
scene.add(Transformer)
//OBJECT
var blob = new Blob([content.obj], {type: "text/plain;charset=utf-8"});
saveAs(blob, 'model.obj')
//MATERIAL
var blob = new Blob([content.mtl], {type: "text/plain;charset=utf-8"});
saveAs(blob, 'model.mtl')
showQuickMessage('Saved as .obj model')
}
function saveFile() {
var data = buildBlockModel()
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
saveAs(blob, 'model.json')
}
//Misc
window.onbeforeunload = function() {
if (Prop.project_saved === false) {
return true;
}
}
function showSaveDialog(close) {
if (Prop.project_saved === false && elements.length > 0) {
var answer = confirm('Your current work will be lost. Are you sure?')
if (answer == true) {
if (close) {
//preventClosing = false
}
return true;
} else {
return false;
}
} else {
if (close) {
preventClosing = false
app.getCurrentWindow().close()
}
return true;
}
}
function checkForUpdates() {
showQuickMessage('Webapp is up-to-date')
}

44
main.js Normal file
View File

@ -0,0 +1,44 @@
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')
let win
function createWindow () {
win = new BrowserWindow({
icon:'icon.ico',
show: false,
backgroundColor: '#21252b',
webPreferences: {
experimentalFeatures: true,
webgl: true
}
})
win.setMenu(null);
win.maximize()
win.show()
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.php'),
protocol: 'file:',
slashes: true
}))
win.on('closed', () => {
win = null
})
//win.webContents.openDevTools()
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "Blockbench",
"description": "Minecraft Block Model Editor",
"version": "1.9.2",
"author": "JannisX11",
"main": "main.js",
"build": {
"appId": "blockbench",
"mac": {
"category": "macOS.application"
}
},
"mac": {
"target": "dmg"
},
"scripts": {
"pack": "build --dir",
"dist": "build"
},
"devDependencies": {
"async": "^2.4.1",
"electron": "^1.7.5",
"electron-winstaller": "^2.5.2"
}
}