mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
v3.5.0
This commit is contained in:
parent
b859ba6533
commit
47c38b2036
@ -19,7 +19,7 @@ jobs:
|
||||
- electron-builder -w --ia32 --publish=always -c.productName='Blockbench_32bit'
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: GH_TOKEN
|
||||
api_key: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file: dist/win-unpacked/resources/app.asar
|
||||
|
||||
|
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "dev",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
66
assets/logo_cutout.svg
Normal file
66
assets/logo_cutout.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.3 KiB |
@ -32,7 +32,7 @@
|
||||
background-color: var(--color-ui);
|
||||
color: inherit;
|
||||
border: none;
|
||||
box-shadow: 0 0px 40px #000;
|
||||
box-shadow: 0 0px 40px rgba(0, 0, 0, 0.5);
|
||||
left: unset;
|
||||
right: unset;
|
||||
bottom: unset;
|
||||
@ -69,6 +69,7 @@
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
height: auto;
|
||||
clear: both;
|
||||
}
|
||||
.dialog_bar::after {
|
||||
content: "";
|
||||
@ -89,6 +90,12 @@
|
||||
.dialog_bar input[type=checkbox] {
|
||||
padding: 0 4px;
|
||||
}
|
||||
.dialog_vector_group {
|
||||
display: flex;
|
||||
}
|
||||
.dialog_vector_group > input {
|
||||
min-width: 30px;
|
||||
}
|
||||
.tab_bar {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
@ -173,6 +180,9 @@
|
||||
}
|
||||
|
||||
/*Settings Dialog*/
|
||||
dialog#settings {
|
||||
width: min(100%, 600px);
|
||||
}
|
||||
#settings_tab_bar {
|
||||
margin: -24px;
|
||||
margin-bottom: 0;
|
||||
@ -254,7 +264,7 @@
|
||||
padding-left: 4px;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
#settingslist input[type=text] {
|
||||
#settingslist input[type=text], #settingslist input[type=password] {
|
||||
padding: 10px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
@ -265,14 +275,22 @@
|
||||
#settingslist div.bar_select select {
|
||||
width: 100%;
|
||||
}
|
||||
#settingslist li li i {
|
||||
#settingslist li li .setting_icon i {
|
||||
font-size: 26pt;
|
||||
width: 34px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
#settingslist li li:hover i {
|
||||
#settingslist li li:hover .setting_icon i {
|
||||
color: var(--color-light);
|
||||
}
|
||||
.password_toggle {
|
||||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
margin-top: -1px;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
/*Keybinds*/
|
||||
#keybindlist {
|
||||
@ -356,6 +374,9 @@
|
||||
background-color: var(--color-back) !important;
|
||||
height: 56px;
|
||||
}
|
||||
#css_editor {
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
/*About*/
|
||||
#about_page_title {
|
||||
@ -695,6 +716,47 @@
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Toolbar Dialog*/
|
||||
#bar_item_list {
|
||||
max-height: 400px;
|
||||
margin-bottom: 20px;
|
||||
overflow-y: scroll;
|
||||
min-height: 80px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-right: none;
|
||||
}
|
||||
#bar_item_list li {
|
||||
padding: 4px;
|
||||
}
|
||||
#bar_item_list li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#bar_item_list li div.icon_wrapper {
|
||||
display: inline-block;
|
||||
height: 26px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
#bar_item_list li:not(:hover) div.icon_wrapper.add, #bar_item_list li:hover div.icon_wrapper.normal {
|
||||
display: none;
|
||||
}
|
||||
#bar_items_current {
|
||||
background-color: var(--color-back);
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
min-height: 34px;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
#bar_items_current li {
|
||||
min-width: 20px;
|
||||
}
|
||||
#bar_items_current li .toolbar_separator {
|
||||
width: 12px;
|
||||
background-color: var(--color-button);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
/*Action Control*/
|
||||
#action_selector {
|
||||
position: absolute;
|
||||
@ -707,7 +769,7 @@
|
||||
top: 200px;
|
||||
width: 360px;
|
||||
height: 42px;
|
||||
box-shadow: 0 0 5px black;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
#action_selector > input {
|
||||
width: 100%;
|
||||
@ -727,7 +789,7 @@
|
||||
color: var(--color-text);
|
||||
width: 340px;
|
||||
margin-left: 8px;
|
||||
box-shadow: 0 0 5px black;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
#action_selector > div > ul {
|
||||
background-color: var(--color-bright_ui);
|
||||
|
305
css/general.css
305
css/general.css
@ -99,7 +99,7 @@
|
||||
background-color: var(--color-dark) !important;
|
||||
}
|
||||
|
||||
/*General*/
|
||||
/*UI Elements*/
|
||||
canvas.preview {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@ -139,10 +139,16 @@
|
||||
.list {
|
||||
background-color: var(--color-back);
|
||||
height: calc(100% - 86px);
|
||||
width: calc(100% - 2px);
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
flex-grow: 1;
|
||||
}
|
||||
#left_bar .list {
|
||||
width: calc(100% - 2px);
|
||||
}
|
||||
.list::-webkit-scrollbar-track {
|
||||
background: var(--color-back);
|
||||
}
|
||||
ul.list_style li {
|
||||
list-style: initial;
|
||||
margin-left: 20px;
|
||||
@ -167,7 +173,7 @@
|
||||
padding: 0 12px;
|
||||
background-color: var(--color-bright_ui);
|
||||
color: var(--color-accent_text);
|
||||
box-shadow: 0 0 2px black;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);;
|
||||
text-align: center;
|
||||
overflow-wrap: break-word;
|
||||
cursor: default;
|
||||
@ -190,7 +196,7 @@
|
||||
max-width: 200px;
|
||||
background-color: var(--color-bright_ui);
|
||||
color: var(--color-accent_text);
|
||||
box-shadow: 0 0 2px black;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
top: 40px;
|
||||
@ -263,45 +269,6 @@
|
||||
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
|
||||
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
|
||||
|
||||
/*Menu Bar*/
|
||||
ul#menu_bar {
|
||||
height: 100%;
|
||||
}
|
||||
li.menu_bar_point {
|
||||
font-size: 17px;
|
||||
padding: 0 8px;
|
||||
padding-top: 2px;
|
||||
display: inline-block;
|
||||
height: 29px;
|
||||
font-weight: normal;
|
||||
}
|
||||
li.menu_bar_point.opened {
|
||||
color: var(--color-light);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
li.menu_bar_point:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
|
||||
#mode_selector {
|
||||
float: right;
|
||||
font-size: 1.1em;
|
||||
height: 30px;
|
||||
}
|
||||
#mode_selector li {
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
margin: 0 5px;
|
||||
overflow: hidden;
|
||||
padding-top: 2px;
|
||||
font-size: 18px;
|
||||
}
|
||||
#mode_selector li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#mode_selector li.selected {
|
||||
border-bottom: 3px solid var(--color-accent);
|
||||
}
|
||||
|
||||
/*Actions*/
|
||||
.toolbar {
|
||||
@ -312,7 +279,7 @@
|
||||
float: none;
|
||||
}
|
||||
.toolbar.narrow, .toolbar_wrapper.narrow > .toolbar {
|
||||
width: auto;
|
||||
width: fit-content;
|
||||
}
|
||||
.toolbar_wrapper.narrow .toolbar .content {
|
||||
float: left;
|
||||
@ -328,14 +295,10 @@
|
||||
.toolbar.vertical .toolbar_menu {
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
.toolbar_wrapper > .toolbar.vertical .tool .tooltip {
|
||||
|
||||
}
|
||||
.toolbar > .tool.toolbar_menu {
|
||||
float: right;
|
||||
width: 14px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.toolbar > .tool.toolbar_menu > i {
|
||||
width: 16px;
|
||||
@ -478,7 +441,7 @@
|
||||
}
|
||||
.contextMenu li.parent::before {
|
||||
content: "\f105";
|
||||
display: inline-block;
|
||||
display: block;
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-weight: 900;
|
||||
font-size: inherit;
|
||||
@ -520,248 +483,4 @@
|
||||
padding: 0;
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
@media (max-device-width: 480px) {
|
||||
.contextMenu li.focused > .contextMenu.sub {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*Start Screen*/
|
||||
#start_screen {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#start_screen h3 {
|
||||
margin: 0;
|
||||
}
|
||||
#start_screen .bar.next_to_title {
|
||||
margin-top: -40px;
|
||||
margin-right: -12px;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
#start_screen .recent_project {
|
||||
margin: 2px 0;
|
||||
display: flex;
|
||||
}
|
||||
#start_screen .recent_project .icon_wrapper {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#start_screen .recent_project_name {
|
||||
font-size: 1.1em;
|
||||
overflow-x: hidden;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
margin: 0 4px;
|
||||
}
|
||||
#start_screen .recent_project_date {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
span.recent_project_date:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 26px;
|
||||
margin-left: -20px;
|
||||
background: linear-gradient(90deg, transparent, var(--color-ui));
|
||||
}
|
||||
|
||||
#start_screen .recent_project.thumbnail {
|
||||
width: 242px;
|
||||
height: 150px;
|
||||
|
||||
width: 168px;
|
||||
height: 128px;
|
||||
position: relative;
|
||||
float: left;
|
||||
background-color: var(--color-back);
|
||||
margin: 1px;
|
||||
background-size: 150px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#start_screen .recent_project.thumbnail:hover {
|
||||
background-color: var(--color-ui);
|
||||
}
|
||||
#start_screen .recent_project.thumbnail .recent_project_name {
|
||||
font-size: 1em;
|
||||
overflow-x: hidden;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
height: 24px;
|
||||
right: 6px;
|
||||
left: 6px;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#start_screen > content {
|
||||
display: block;
|
||||
margin-top: 40px;
|
||||
max-width: 900px;
|
||||
height: auto;
|
||||
max-height: calc(100% - 80px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: var(--color-ui);
|
||||
overflow-y: scroll;
|
||||
image-rendering: auto;
|
||||
}
|
||||
#start_screen > content > section {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
#start_screen section left, #start_screen section right {
|
||||
display: block;
|
||||
padding: 24px;
|
||||
max-height: 600px;
|
||||
}
|
||||
#start_screen section right > ul {
|
||||
max-height: 465px;
|
||||
overflow-y: auto;
|
||||
padding-right: 5px;
|
||||
}
|
||||
#start_screen left {
|
||||
flex-grow: 0;
|
||||
background-size: cover;
|
||||
}
|
||||
#start_screen left i.graphic_icon {
|
||||
font-size: 40px;
|
||||
width: 12px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
#start_screen right {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#start_screen i.start_screen_close_button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
#start_screen i.start_screen_close_button:not(:hover) {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@media (max-device-width: 480px) {
|
||||
#start_screen {
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
#start_screen > content {
|
||||
margin-top: 0px;
|
||||
margin-top: 0px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
max-height: 100%;
|
||||
}
|
||||
#start_screen > content > section {
|
||||
display: block;
|
||||
}
|
||||
#start_screen content section right {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
#start_screen content section left {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
#start_screen content section left {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#start-files li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#start-files left {
|
||||
width: 36%;
|
||||
}
|
||||
#start-files right {
|
||||
width: 64%;
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
#start_screen left > ul {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
#start_screen right i {
|
||||
vertical-align: sub;
|
||||
}
|
||||
#start-files left li {
|
||||
padding: 4px 0;
|
||||
}
|
||||
#start-files left span.icon_wrapper {
|
||||
height: 22px;
|
||||
}
|
||||
#start-files left i {
|
||||
font-size: 20pt;
|
||||
height: 22px;
|
||||
margin: 2px 12px 0px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/*Toolbar Dialog*/
|
||||
#bar_item_list {
|
||||
max-height: 400px;
|
||||
margin-bottom: 20px;
|
||||
overflow-y: scroll;
|
||||
min-height: 80px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-right: none;
|
||||
}
|
||||
#bar_item_list li {
|
||||
padding: 4px;
|
||||
}
|
||||
#bar_item_list li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#bar_item_list li div.icon_wrapper {
|
||||
display: inline-block;
|
||||
height: 26px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
#bar_item_list li:not(:hover) div.icon_wrapper.add, #bar_item_list li:hover div.icon_wrapper.normal {
|
||||
display: none;
|
||||
}
|
||||
#bar_items_current {
|
||||
background-color: var(--color-back);
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
min-height: 34px;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
#bar_items_current li {
|
||||
min-width: 20px;
|
||||
}
|
||||
#bar_items_current li .toolbar_separator {
|
||||
width: 12px;
|
||||
background-color: var(--color-button);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
/*Status Bar*/
|
||||
#status_bar {
|
||||
position: relative;
|
||||
display: block;
|
||||
background: var(--color-back);
|
||||
}
|
||||
#status_bar > div {
|
||||
float: left;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
#status_bar > div#status_fps {
|
||||
float: right;
|
||||
}
|
||||
#status_bar > div#status_saved {
|
||||
padding-top: 2px;
|
||||
}
|
||||
#status_bar #status_progress {
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
background: var(--color-accent);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
451
css/panels.css
451
css/panels.css
@ -1,307 +1,4 @@
|
||||
|
||||
/*Layout*/
|
||||
#page_wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 332px auto 314px;
|
||||
grid-template-rows: 30px minmax(200px, 5000px) 26px;
|
||||
grid-template-areas:
|
||||
"left_bar toolbar toolbar"
|
||||
"left_bar center right_bar"
|
||||
"left_bar status_bar right_bar";
|
||||
height: calc(100% - 26px);
|
||||
width: 100%;
|
||||
border: 2px solid var(--color-border);
|
||||
border-top: none;
|
||||
}
|
||||
#loading_error_message {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--color-dark);
|
||||
border: 2px solid var(--color-accent);
|
||||
text-align: center;
|
||||
padding-top: 160px;
|
||||
position: absolute;
|
||||
z-index: 250;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-color: var(--color-ui);;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#left_bar {
|
||||
grid-area: left_bar;
|
||||
}
|
||||
#right_bar {
|
||||
grid-area: right_bar;
|
||||
}
|
||||
|
||||
.panel.grow {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
min-height: 133px;
|
||||
}
|
||||
.panel:not(:last-child) {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
h3.panel_handle {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 6px 12px;
|
||||
background: var(--color-ui);
|
||||
margin: 0;
|
||||
}
|
||||
.panel p {
|
||||
margin-left: 12px;
|
||||
}
|
||||
body > h3.panel_handle {
|
||||
box-shadow: 0 0 16px black;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#center {
|
||||
grid-area: center;
|
||||
background-color: var(--color-dark);
|
||||
overflow: hidden;
|
||||
min-width: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
div#center > div {
|
||||
max-height: 100%;
|
||||
}
|
||||
div#preview {
|
||||
flex-grow: 1;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
#status_bar {
|
||||
grid-area: status_bar;
|
||||
}
|
||||
.single_canvas_wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
cursor: inherit;
|
||||
}
|
||||
.quad_canvas_wrapper {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
position: absolute;
|
||||
cursor: inherit;
|
||||
}
|
||||
.quad_canvas_wrapper.qcw_x {
|
||||
border-right: 2px solid var(--color-grid);
|
||||
}
|
||||
.quad_canvas_wrapper.qcw_y {
|
||||
border-bottom: 2px solid var(--color-grid);
|
||||
}
|
||||
.quad_canvas_wrapper:not(.qcw_x) {
|
||||
right: 0;
|
||||
}
|
||||
.quad_canvas_wrapper:not(.qcw_y) {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.resizer {
|
||||
position: absolute !important;
|
||||
z-index: 12;
|
||||
}
|
||||
.resizer.vertical { /* | */
|
||||
cursor: ew-resize;
|
||||
width: 6px;
|
||||
}
|
||||
.resizer.horizontal { /* __ */
|
||||
cursor: ns-resize;
|
||||
height: 6px;
|
||||
}
|
||||
.resizer.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Head Bars*/
|
||||
#main_toolbar {
|
||||
background-color: var(--color-ui);;
|
||||
grid-area: toolbar;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
}
|
||||
#main_toolbar > * {
|
||||
display: inline-block;
|
||||
}
|
||||
.toolbar_wrapper.tool_options {
|
||||
flex-grow: 1;
|
||||
}
|
||||
header {
|
||||
background-color: var(--color-border);;
|
||||
grid-area: titlebar;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
height: 26px;
|
||||
}
|
||||
header > * {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
header ::-webkit-scrollbar {
|
||||
height: 0;
|
||||
}
|
||||
div#title {
|
||||
width: auto;
|
||||
padding-right: 8px;
|
||||
padding-left: 6px;
|
||||
margin-left: 4px;
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
font-family: montserrat, arial, sans-serif;
|
||||
color: var(--color-light);
|
||||
vertical-align: top;
|
||||
min-width: 62px;
|
||||
margin-top: -0.6px;
|
||||
}
|
||||
div#title i {
|
||||
display: none;
|
||||
padding-top: 1px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
#title span {
|
||||
min-width: 114px;
|
||||
display: inline-block;
|
||||
}
|
||||
@media (max-width:950px) {
|
||||
#title span {
|
||||
display: none;
|
||||
}
|
||||
div#title i {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.app-drag-region {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
div#header_free_bar.app-drag-region {
|
||||
flex-grow: 1;
|
||||
}
|
||||
div#header_free_bar.app-drag-region.resize_space {
|
||||
margin-top: 4px;
|
||||
height: calc(100% - 4px);
|
||||
}
|
||||
#web_download_button {
|
||||
margin-left: auto;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
#web_download_button a {
|
||||
text-decoration: none !important;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0 12px;
|
||||
}
|
||||
#web_download_button:hover a {
|
||||
color: var(--color-accent_text);
|
||||
}
|
||||
#windows_window_menu {
|
||||
margin-left: auto;
|
||||
}
|
||||
#windows_window_menu li {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
width: 42px;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#windows_window_menu li:hover {
|
||||
color: var(--color-light);
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
#windows_window_menu li.wwm_r:hover {
|
||||
background-color: var(--color-close);
|
||||
}
|
||||
#windows_window_menu li i:not(.material-icons) {
|
||||
font-size: 10pt;
|
||||
}
|
||||
#windows_window_menu i.material-icons {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
#mac_window_menu {
|
||||
width: 68px;
|
||||
}
|
||||
|
||||
/*Mobile*/
|
||||
@media (max-device-width: 480px) {
|
||||
|
||||
#page_wrapper {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(200px, 5000px) 26px;
|
||||
grid-template-areas:
|
||||
"toolbar"
|
||||
"center"
|
||||
"status_bar";
|
||||
grid-template-columns: auto !important;
|
||||
border: none;
|
||||
}
|
||||
#main_toolbar {
|
||||
display: block;
|
||||
}
|
||||
#main_toolbar > * {
|
||||
display: block;
|
||||
}
|
||||
#main_toolbar > div.tools {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 26px;
|
||||
right: 0px;
|
||||
}
|
||||
#main_toolbar > div.mobile_side {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 86px;
|
||||
right: 0px;
|
||||
}
|
||||
#main_toolbar > div.tool_options {
|
||||
background-color: var(--color-back);
|
||||
}
|
||||
.resizer.vertical {
|
||||
display: none;
|
||||
}
|
||||
.sidebar {
|
||||
overflow-y: auto;
|
||||
}
|
||||
#left_bar, #right_bar {
|
||||
width: calc(100% - 40px);
|
||||
display: none;
|
||||
}
|
||||
/*Left*/
|
||||
#page_wrapper.show_left {
|
||||
grid-template-areas: "toolbar" "left_bar" "status_bar";
|
||||
}
|
||||
#page_wrapper.show_left #center {
|
||||
display: none;
|
||||
}
|
||||
#page_wrapper.show_left #left_bar {
|
||||
display: flex;
|
||||
}
|
||||
/*Right*/
|
||||
#page_wrapper.show_right {
|
||||
grid-template-areas: "toolbar" "right_bar" "status_bar";
|
||||
}
|
||||
#page_wrapper.show_right #center {
|
||||
display: none;
|
||||
}
|
||||
#page_wrapper.show_right #right_bar {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
/*Display*/
|
||||
|
||||
.tabs_small input[type="radio"]:checked+label {
|
||||
@ -317,7 +14,6 @@
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
flex-grow: 1;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
#color .tabs_small label {
|
||||
@ -347,6 +43,7 @@
|
||||
.bar.slider_input_combo {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.bar.slider_input_combo input.tool[type="range"] {
|
||||
float: none;
|
||||
@ -406,6 +103,9 @@
|
||||
text-align: center;
|
||||
width: 21px;
|
||||
}
|
||||
.outliner_node .outliner_object i.icon_off {
|
||||
opacity: 0.56;
|
||||
}
|
||||
.outliner_opener_placeholder {
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
@ -416,6 +116,9 @@
|
||||
padding: 2px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.outliner_object:active {
|
||||
background-color: var(--color-ui);
|
||||
}
|
||||
.outliner_object.selected {
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
@ -436,6 +139,19 @@
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
}
|
||||
#cubes_list ul {
|
||||
position: relative;
|
||||
}
|
||||
#cubes_list .outliner_line_guide {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
bottom: 4px;
|
||||
width: 4px;
|
||||
margin-left: 10px;
|
||||
border-left: 2px solid var(--color-text);
|
||||
opacity: 0.2;
|
||||
pointer-events: none;
|
||||
}
|
||||
.drag_hover[order]::before {
|
||||
content: '';
|
||||
width: calc(100% - 12px);
|
||||
@ -482,10 +198,10 @@
|
||||
font-size: 15px;
|
||||
float: right;
|
||||
}
|
||||
#cubes_list .outliner_object i.icon-open-state {
|
||||
i.icon-open-state {
|
||||
opacity: 0.7;
|
||||
}
|
||||
#cubes_list .outliner_object i.icon-open-state:hover {
|
||||
i.icon-open-state:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -735,14 +451,28 @@
|
||||
#timeline_playhead {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 3;
|
||||
|
||||
height: 26px;
|
||||
width: 18px;
|
||||
top: 0;
|
||||
margin-left: -8px;
|
||||
border: 2px solid var(--color-accent);
|
||||
border-top-width: 5px;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
z-index: 3;
|
||||
|
||||
border-right: 9px solid transparent;
|
||||
border-left: 9px solid transparent;
|
||||
border-top: 12px solid var(--color-accent);
|
||||
border-radius: 2px;
|
||||
}
|
||||
#timeline_playhead::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
background-color: var(--color-accent);
|
||||
pointer-events: none;
|
||||
margin-left: -1px;
|
||||
margin-top: -2px;
|
||||
height: 17px;
|
||||
}
|
||||
#timeline_playhead_line {
|
||||
content: "";
|
||||
@ -754,6 +484,21 @@
|
||||
background-color: var(--color-accent);
|
||||
pointer-events: none;
|
||||
}
|
||||
#timeline_endbracket {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
|
||||
height: 26px;
|
||||
width: 8px;
|
||||
top: 0;
|
||||
margin-left: -7px;
|
||||
|
||||
border: 1px solid var(--color-accent);
|
||||
border-left-width: 0;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
|
||||
#timeline_body .keyframe {
|
||||
position: absolute;
|
||||
margin-left: -6px;
|
||||
@ -797,26 +542,53 @@
|
||||
padding: 3px;
|
||||
padding-left: 8px;
|
||||
overflow: hidden;
|
||||
background-color: var(--color-back);
|
||||
z-index: 4;
|
||||
}
|
||||
#timeline_time_wrapper {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background-color: var(--color-button);
|
||||
overflow: hidden;
|
||||
background-color: var(--color-back);
|
||||
}
|
||||
#timeline_time {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
margin-left: 8px;
|
||||
border-bottom: 1px solid var(--color-selected);
|
||||
}
|
||||
.timeline_timecode {
|
||||
border-left: 1px solid var(--color-border);
|
||||
padding-left: 4px;
|
||||
padding-top: 2px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
.timeline_timecode > span {
|
||||
display: block;
|
||||
margin-top: -4px;
|
||||
font-size: 0.9em;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.timeline_timecode > .substeps {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
}
|
||||
.timeline_timecode > .substeps > div {
|
||||
border-left: 1px solid var(--color-text);
|
||||
height: 4px;
|
||||
flex-grow: 1;
|
||||
margin-top: 4px;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.timeline_timecode > .substeps > div:first-child {
|
||||
height: 100%;
|
||||
margin-top: 0;
|
||||
opacity: 0.48;
|
||||
}
|
||||
|
||||
|
||||
#timeline_body_inner {
|
||||
@ -840,6 +612,7 @@
|
||||
height: calc(100% + 1px);
|
||||
background-color: var(--color-ui);
|
||||
border-right: 1px solid var(--color-border);
|
||||
border-left: 2px solid transparent;
|
||||
box-shadow: 1px 8px 10px 0 #00000038;
|
||||
z-index: 5;
|
||||
}
|
||||
@ -849,6 +622,9 @@
|
||||
#timeline_body li > .animator_channel_bar .channel_head {
|
||||
padding-left: 16px;
|
||||
}
|
||||
.animator.selected .channel_head {
|
||||
border-left-color: var(--color-accent);
|
||||
}
|
||||
.channel_head .text_button {
|
||||
width: 26px;
|
||||
height: 24px;
|
||||
@ -862,12 +638,6 @@
|
||||
.animator_channel_bar .channel_head .text_button .channel_mute {
|
||||
font-size: 11pt;
|
||||
}
|
||||
.animator.selected .animator_head_bar {
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
.animator.selected .animator_head_bar .channel_head {
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
.channel_head span {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
@ -895,6 +665,9 @@
|
||||
.UVEditor {
|
||||
position: relative;
|
||||
}
|
||||
dialog .UVEditor {
|
||||
z-index: 20;
|
||||
}
|
||||
.UVEditor > .toolbar {
|
||||
margin-top: 3px;
|
||||
}
|
||||
@ -909,7 +682,11 @@
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
}
|
||||
.uv_headline.selected {
|
||||
#uv_dialog_all .UVEditor.selected {
|
||||
border-color: var(--color-accent);
|
||||
z-index: 21;
|
||||
}
|
||||
.UVEditor.selected .uv_headline {
|
||||
background-color: var(--color-button);
|
||||
}
|
||||
.uv_headline .tool {
|
||||
@ -1089,7 +866,7 @@
|
||||
color: var(--color-accent_text);
|
||||
}
|
||||
|
||||
/*Edit Session UI*/
|
||||
/*Chat*/
|
||||
#chat {
|
||||
z-index: 16;
|
||||
min-height: 180px;
|
||||
@ -1149,9 +926,6 @@
|
||||
}
|
||||
|
||||
/*Color*/
|
||||
.panel#color {
|
||||
|
||||
}
|
||||
#color_panel_head {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@ -1200,33 +974,28 @@
|
||||
width: 36px;
|
||||
}
|
||||
#palette_list {
|
||||
padding: 2px 1px;
|
||||
padding: 2px;
|
||||
min-height: 160px;
|
||||
max-height: 232px;
|
||||
}
|
||||
#palette_list .color {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 3px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
vertical-align: top;
|
||||
}
|
||||
#palette_list .color:hover {
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
#palette_list .color.selected {
|
||||
padding: 1px;
|
||||
}
|
||||
#palette_list .color .color_inner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
#palette_list .color.selected {
|
||||
padding: 3px;
|
||||
}
|
||||
#palette_list .color.selected .color_inner {
|
||||
border-radius: 4px;
|
||||
transition: border-radius 20ms ease;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
#palette_list .color.contrast {
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
#palette_list .color .color_inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.panel#color input.sp-input {
|
||||
width: calc(100% - 40px);
|
||||
|
@ -22,7 +22,7 @@
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--color-ui);
|
||||
}
|
||||
@ -138,7 +138,6 @@
|
||||
[class^="icon-"]:not(.fa), [class*=" icon-"]:not(.fa) {
|
||||
/* use !important to prevent issues with browser extensions that change fonts */
|
||||
font-family: 'icomoon' !important;
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
@ -147,7 +146,6 @@
|
||||
font-size: 1.4em;
|
||||
max-width: 24px;
|
||||
|
||||
Better Font Rendering ===========
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
@ -399,7 +397,7 @@
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--color-text)
|
||||
color: var(--color-text);
|
||||
font-size: 1em;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
@ -419,6 +417,7 @@
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
button.disabled {
|
||||
opacity: 0.5;
|
||||
@ -503,13 +502,16 @@
|
||||
right: 6px;
|
||||
top: 3px;
|
||||
}
|
||||
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button, {
|
||||
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appeareance: none;
|
||||
}
|
||||
input[type=range] {
|
||||
background-color: var(--color-back);
|
||||
height: 30px;
|
||||
}
|
||||
input[type=password] {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
|
@ -150,10 +150,6 @@ License: MIT
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.sp-container:not(.sp-alpha-enabled) .sp-top {
|
||||
/*margin-bottom: -20px;*/
|
||||
}
|
||||
|
||||
/* Don't allow text selection */
|
||||
.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
|
||||
-webkit-user-select:none;
|
||||
@ -444,12 +440,6 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
|
||||
|
||||
|
||||
/* Buttons: http://hellohappy.org/css3-buttons/ */
|
||||
.sp-container button {
|
||||
|
||||
}
|
||||
.sp-container button:hover {
|
||||
|
||||
}
|
||||
.sp-cancel {
|
||||
font-size: 11px;
|
||||
margin:0;
|
||||
|
561
css/window.css
Normal file
561
css/window.css
Normal file
@ -0,0 +1,561 @@
|
||||
|
||||
/*Layout*/
|
||||
#page_wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 332px auto 314px;
|
||||
grid-template-rows: 30px minmax(200px, 5000px) 26px;
|
||||
grid-template-areas:
|
||||
"left_bar toolbar toolbar"
|
||||
"left_bar center right_bar"
|
||||
"left_bar status_bar right_bar";
|
||||
height: calc(100% - 26px);
|
||||
width: 100%;
|
||||
border: 2px solid var(--color-frame);
|
||||
border-top: none;
|
||||
opacity: 1;
|
||||
transition: opacity 0.1s linear;
|
||||
}
|
||||
#page_wrapper.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
body {
|
||||
background-image: url('../assets/logo_cutout.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 128px;
|
||||
background-position: center;
|
||||
}
|
||||
#loading_error_message {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--color-dark);
|
||||
border: 2px solid var(--color-accent);
|
||||
text-align: center;
|
||||
padding-top: 160px;
|
||||
position: absolute;
|
||||
z-index: 250;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-color: var(--color-ui);;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#left_bar {
|
||||
grid-area: left_bar;
|
||||
}
|
||||
#right_bar {
|
||||
grid-area: right_bar;
|
||||
}
|
||||
|
||||
.panel.grow {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
min-height: 133px;
|
||||
}
|
||||
.panel:not(:last-child) {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
h3.panel_handle {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 6px 12px;
|
||||
background: var(--color-ui);
|
||||
margin: 0;
|
||||
}
|
||||
.panel p {
|
||||
margin-left: 12px;
|
||||
}
|
||||
body > h3.panel_handle {
|
||||
box-shadow: 0 0 16px black;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#center {
|
||||
grid-area: center;
|
||||
background-color: var(--color-dark);
|
||||
overflow: hidden;
|
||||
min-width: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
div#center > div {
|
||||
max-height: 100%;
|
||||
}
|
||||
div#preview {
|
||||
flex-grow: 1;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
#status_bar {
|
||||
grid-area: status_bar;
|
||||
}
|
||||
.single_canvas_wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
cursor: inherit;
|
||||
}
|
||||
.quad_canvas_wrapper {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
position: absolute;
|
||||
cursor: inherit;
|
||||
}
|
||||
.quad_canvas_wrapper.qcw_x {
|
||||
border-right: 2px solid var(--color-grid);
|
||||
}
|
||||
.quad_canvas_wrapper.qcw_y {
|
||||
border-bottom: 2px solid var(--color-grid);
|
||||
}
|
||||
.quad_canvas_wrapper:not(.qcw_x) {
|
||||
right: 0;
|
||||
}
|
||||
.quad_canvas_wrapper:not(.qcw_y) {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.resizer {
|
||||
position: absolute !important;
|
||||
z-index: 12;
|
||||
}
|
||||
.resizer.vertical { /* | */
|
||||
cursor: ew-resize;
|
||||
width: 6px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.resizer.horizontal { /* __ */
|
||||
cursor: ns-resize;
|
||||
height: 6px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.resizer.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
/*
|
||||
.resizer:hover, .resizer.ui-draggable-dragging {
|
||||
background-color: var(--color-accent);
|
||||
opacity: 0.2;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*Head Bars*/
|
||||
#main_toolbar {
|
||||
background-color: var(--color-ui);;
|
||||
grid-area: toolbar;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
}
|
||||
#main_toolbar > * {
|
||||
display: inline-block;
|
||||
}
|
||||
.toolbar_wrapper.tool_options {
|
||||
flex-grow: 1;
|
||||
}
|
||||
header {
|
||||
background-color: var(--color-frame);
|
||||
grid-area: titlebar;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
height: 26px;
|
||||
}
|
||||
header > * {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
header ::-webkit-scrollbar {
|
||||
height: 0;
|
||||
}
|
||||
div#title {
|
||||
width: auto;
|
||||
padding-right: 8px;
|
||||
padding-left: 6px;
|
||||
margin-left: 4px;
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
font-family: montserrat, arial, sans-serif;
|
||||
color: var(--color-light);
|
||||
vertical-align: top;
|
||||
min-width: 62px;
|
||||
margin-top: -0.6px;
|
||||
}
|
||||
div#title i {
|
||||
display: none;
|
||||
padding-top: 1px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
#title span {
|
||||
min-width: 114px;
|
||||
display: inline-block;
|
||||
}
|
||||
@media (max-width:950px) {
|
||||
#title span {
|
||||
display: none;
|
||||
}
|
||||
div#title i {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.app-drag-region {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
div#header_free_bar.app-drag-region {
|
||||
flex-grow: 1;
|
||||
}
|
||||
div#header_free_bar.app-drag-region.resize_space {
|
||||
margin-top: 4px;
|
||||
height: calc(100% - 4px);
|
||||
}
|
||||
#web_download_button {
|
||||
margin-left: auto;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
#web_download_button a {
|
||||
text-decoration: none !important;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0 12px;
|
||||
}
|
||||
#web_download_button:hover a {
|
||||
color: var(--color-accent_text);
|
||||
}
|
||||
#windows_window_menu {
|
||||
margin-left: auto;
|
||||
}
|
||||
#windows_window_menu li {
|
||||
display: inline-block;
|
||||
width: 42px;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#windows_window_menu li:hover {
|
||||
color: var(--color-light);
|
||||
background-color: var(--color-selected);
|
||||
}
|
||||
#windows_window_menu li.wwm_r:hover {
|
||||
background-color: var(--color-close);
|
||||
}
|
||||
#windows_window_menu li i:not(.material-icons) {
|
||||
font-size: 10pt;
|
||||
}
|
||||
#windows_window_menu i.material-icons {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
#mac_window_menu {
|
||||
width: 68px;
|
||||
}
|
||||
|
||||
/*Mobile*/
|
||||
@media (max-device-width: 480px) {
|
||||
|
||||
#page_wrapper {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(200px, 5000px) 26px;
|
||||
grid-template-areas:
|
||||
"toolbar"
|
||||
"center"
|
||||
"status_bar";
|
||||
grid-template-columns: auto !important;
|
||||
border: none;
|
||||
}
|
||||
#main_toolbar {
|
||||
display: block;
|
||||
}
|
||||
#main_toolbar > * {
|
||||
display: block;
|
||||
}
|
||||
#main_toolbar > div.tools {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 26px;
|
||||
right: 0px;
|
||||
}
|
||||
#main_toolbar > div.mobile_side {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 86px;
|
||||
right: 0px;
|
||||
}
|
||||
#main_toolbar > div.tool_options {
|
||||
background-color: var(--color-back);
|
||||
}
|
||||
.resizer.vertical {
|
||||
display: none;
|
||||
}
|
||||
.sidebar {
|
||||
overflow-y: auto;
|
||||
}
|
||||
#left_bar, #right_bar {
|
||||
width: calc(100% - 40px);
|
||||
display: none;
|
||||
}
|
||||
/*Left*/
|
||||
#page_wrapper.show_left {
|
||||
grid-template-areas: "toolbar" "left_bar" "status_bar";
|
||||
}
|
||||
#page_wrapper.show_left #center {
|
||||
display: none;
|
||||
}
|
||||
#page_wrapper.show_left #left_bar {
|
||||
display: flex;
|
||||
}
|
||||
/*Right*/
|
||||
#page_wrapper.show_right {
|
||||
grid-template-areas: "toolbar" "right_bar" "status_bar";
|
||||
}
|
||||
#page_wrapper.show_right #center {
|
||||
display: none;
|
||||
}
|
||||
#page_wrapper.show_right #right_bar {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
/*Menu Bar*/
|
||||
ul#menu_bar {
|
||||
height: 100%;
|
||||
}
|
||||
li.menu_bar_point {
|
||||
font-size: 17px;
|
||||
padding: 0 8px;
|
||||
padding-top: 2px;
|
||||
display: inline-block;
|
||||
height: 29px;
|
||||
font-weight: normal;
|
||||
}
|
||||
li.menu_bar_point.opened {
|
||||
color: var(--color-light);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
li.menu_bar_point:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
|
||||
#mode_selector {
|
||||
float: right;
|
||||
font-size: 1.1em;
|
||||
height: 30px;
|
||||
}
|
||||
#mode_selector li {
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
margin: 0 5px;
|
||||
overflow: hidden;
|
||||
padding-top: 2px;
|
||||
font-size: 18px;
|
||||
}
|
||||
#mode_selector li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#mode_selector li.selected {
|
||||
border-bottom: 3px solid var(--color-accent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Start Screen*/
|
||||
#start_screen {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#start_screen h3 {
|
||||
margin: 0;
|
||||
}
|
||||
#start_screen .bar.next_to_title {
|
||||
margin-top: -40px;
|
||||
margin-right: -12px;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
#start_screen .recent_project {
|
||||
margin: 2px 0;
|
||||
display: flex;
|
||||
}
|
||||
#start_screen .recent_project .icon_wrapper {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#start_screen .recent_project_name {
|
||||
font-size: 1.1em;
|
||||
overflow-x: hidden;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
margin: 0 4px;
|
||||
}
|
||||
#start_screen .recent_project_date {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
span.recent_project_date:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 26px;
|
||||
margin-left: -20px;
|
||||
background: linear-gradient(90deg, transparent, var(--color-ui));
|
||||
}
|
||||
|
||||
#start_screen .recent_project.thumbnail {
|
||||
width: 242px;
|
||||
height: 150px;
|
||||
|
||||
width: 168px;
|
||||
height: 128px;
|
||||
position: relative;
|
||||
float: left;
|
||||
background-color: var(--color-back);
|
||||
margin: 1px;
|
||||
background-size: 150px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#start_screen .recent_project.thumbnail:hover {
|
||||
background-color: var(--color-ui);
|
||||
}
|
||||
#start_screen .recent_project.thumbnail .recent_project_name {
|
||||
font-size: 1em;
|
||||
overflow-x: hidden;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
height: 24px;
|
||||
right: 6px;
|
||||
left: 6px;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#start_screen > content {
|
||||
display: block;
|
||||
margin-top: 40px;
|
||||
max-width: 1000px;
|
||||
height: auto;
|
||||
max-height: calc(100% - 80px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: var(--color-ui);
|
||||
overflow-y: scroll;
|
||||
image-rendering: auto;
|
||||
}
|
||||
#start_screen > content > section {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
#start_screen section left, #start_screen section right {
|
||||
display: block;
|
||||
padding: 24px;
|
||||
max-height: 600px;
|
||||
}
|
||||
#start_screen section right > ul {
|
||||
max-height: 465px;
|
||||
overflow-y: auto;
|
||||
padding-right: 5px;
|
||||
}
|
||||
#start_screen left {
|
||||
flex-grow: 0;
|
||||
background-size: cover;
|
||||
}
|
||||
#start_screen left i.graphic_icon {
|
||||
font-size: 40px;
|
||||
width: 12px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
#start_screen right {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#start_screen i.start_screen_close_button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
#start_screen i.start_screen_close_button:not(:hover) {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@media (max-device-width: 480px) {
|
||||
#start_screen {
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
#start_screen > content {
|
||||
margin-top: 0px;
|
||||
margin-top: 0px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
max-height: 100%;
|
||||
}
|
||||
#start_screen > content > section {
|
||||
display: block;
|
||||
}
|
||||
#start_screen content section right {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
#start_screen content section left {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
#start_screen content section left {
|
||||
width: 100% !important;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#start-files li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#start-files left {
|
||||
width: 38%;
|
||||
}
|
||||
#start-files right {
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
#start_screen left > ul {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
#start_screen right i {
|
||||
vertical-align: sub;
|
||||
}
|
||||
#start-files left li {
|
||||
padding: 4px 0;
|
||||
}
|
||||
#start-files left span.icon_wrapper {
|
||||
height: 22px;
|
||||
}
|
||||
#start-files left i {
|
||||
font-size: 20pt;
|
||||
height: 22px;
|
||||
margin: 2px 12px 0px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/*Status Bar*/
|
||||
#status_bar {
|
||||
position: relative;
|
||||
display: block;
|
||||
background: var(--color-back);
|
||||
}
|
||||
#status_bar > div {
|
||||
float: left;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
#status_bar > div#status_fps {
|
||||
float: right;
|
||||
}
|
||||
#status_bar > div#status_saved {
|
||||
padding-top: 2px;
|
||||
}
|
||||
#status_bar #status_progress {
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
background: var(--color-accent);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
BIN
icon_full.png
Normal file
BIN
icon_full.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
126
index.html
126
index.html
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Blockbench</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#181a1f">
|
||||
<meta name="robots" content="noindex">
|
||||
@ -15,6 +15,7 @@
|
||||
<link rel="stylesheet" href="css/prism.css">
|
||||
<link rel="stylesheet" href="css/setup.css">
|
||||
<link rel="stylesheet" href="css/general.css">
|
||||
<link rel="stylesheet" href="css/window.css">
|
||||
<link rel="stylesheet" href="css/panels.css">
|
||||
<link rel="stylesheet" href="css/dialogs.css">
|
||||
<style type="text/css" id="theme_css"></style>
|
||||
@ -23,10 +24,11 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '3.4.2';
|
||||
const appVersion = '3.5.0';
|
||||
</script>
|
||||
<div id="loading_error_message" style="display: none;">
|
||||
<div>An error occurred while loading Blockbench</div>
|
||||
<div id="loading_error_detail"></div>
|
||||
<button onclick="isApp ? Blockbench.reload() : window.location.reload(true)" class="large" style="margin-right: auto; margin-left: auto;">Reload</button>
|
||||
<button onclick="window.close()" class="large" style="margin-right: auto; margin-left: auto;">Quit</button>
|
||||
</div>
|
||||
@ -93,6 +95,7 @@
|
||||
<script src="js/animations.js"></script>
|
||||
<script src="js/plugin_loader.js"></script>
|
||||
|
||||
<script src="js/io/project.js"></script>
|
||||
<script src="js/io/io.js"></script>
|
||||
<script src="js/io/bbmodel.js"></script>
|
||||
<script src="js/io/java_block.js"></script>
|
||||
@ -128,7 +131,7 @@
|
||||
<div class="progress_bar" id="update_bar">
|
||||
<div class="progress_bar_inner"></div>
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar" hidden>
|
||||
<button type="button" class="cancel_btn confirm_btn uc_btn tl" onclick="hideDialog()">dialog.close</button>
|
||||
</div>
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
@ -158,10 +161,10 @@
|
||||
<i v-else class="material-icons plugin_expand_icon">expand_more</i>
|
||||
{{ plugin.title }}
|
||||
</div>
|
||||
<div class="button_bar" v-if="plugin.isInstallable() == true">
|
||||
<div class="button_bar" v-if="plugin.installed || plugin.isInstallable() == true">
|
||||
<button type="button" class="" v-on:click="plugin.uninstall()" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">dialog.plugins.uninstall</span></button>
|
||||
<button type="button" class="" v-on:click="plugin.download(true)" v-else><i class="material-icons">add</i><span class="tl">dialog.plugins.install</span></button>
|
||||
<button type="button" class="local_only" v-on:click="plugin.reload()" v-if="plugin.installed && plugin.fromFile && isApp"><i class="material-icons">refresh</i><span class="tl">dialog.plugins.reload</span></button>
|
||||
<button type="button" v-on:click="plugin.reload()" v-if="plugin.installed && plugin.isReloadable()"><i class="material-icons">refresh</i><span class="tl">dialog.plugins.reload</span></button>
|
||||
</div>
|
||||
<div class="button_bar tiny tl" v-else>{{ plugin.isInstallable() }}</div>
|
||||
|
||||
@ -174,8 +177,8 @@
|
||||
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && showAll === true" id="plugin_available_empty">dialog.plugins.none_available</div>
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
<div class="dialog_bar" hidden>
|
||||
<button type="button" class="cancel_btn confirm_btn uc_btn tl" onclick="hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</dialog>
|
||||
@ -238,7 +241,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
<button type="button" class="cancel_btn confirm_btn uc_btn tl" onclick="hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</dialog>
|
||||
@ -295,46 +298,6 @@
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</dialog>
|
||||
|
||||
<dialog class="dialog draggable paddinged" id="texture_edit">
|
||||
<div class="dialog_handle tl" id="te_title">data.texture</div>
|
||||
|
||||
<div id="texture_menu_thumbnail"></div>
|
||||
|
||||
<div class="bar">
|
||||
<div class="tool link_only" onclick="textures.selected.reopen()"><div class="tooltip tl">menu.texture.change</div><i class="material-icons">file_upload</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.refresh(true)"><div class="tooltip tl">menu.texture.refresh</div><i class="material-icons">refresh</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.openFolder()"><div class="tooltip tl">menu.texture.folder</div><i class="material-icons">folder</i></div>
|
||||
<div class="tool" onclick="textures.selected.remove()"><div class="tooltip tl">generic.delete</div><i class="material-icons">delete</i></div>
|
||||
</div>
|
||||
|
||||
<p class="multiline_text" id="te_path">path</p>
|
||||
|
||||
<div class="dialog_bar narrow bitmap_only"><label class="tl">generic.name</label> </div>
|
||||
<div class="dialog_bar bitmap_only">
|
||||
<input type="text" class="input_wide dark_bordered" id="te_name">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar narrow"><label class="tl">dialog.texture.variable</label> </div>
|
||||
<div class="dialog_bar">
|
||||
<input type="text" class="input_wide dark_bordered" id="te_variable">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar narrow"><label class="tl">dialog.texture.folder</label> </div>
|
||||
<div class="dialog_bar">
|
||||
<input type="text" class="input_wide dark_bordered" id="te_folder">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar narrow"><label class="tl">dialog.texture.namespace</label> </div>
|
||||
<div class="dialog_bar">
|
||||
<input type="text" class="input_wide dark_bordered" id="te_namespace">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="confirm_btn cancel_btn" onclick="saveTextureMenu()">Close</button>
|
||||
</div>
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</dialog>
|
||||
|
||||
<dialog class="dialog draggable paddinged" id="scaling">
|
||||
<div class="dialog_handle tl">dialog.scale.title</div>
|
||||
|
||||
@ -511,6 +474,15 @@
|
||||
<template v-if="setting.type === 'text'">
|
||||
<input type="text" class="dark_bordered" style="width: 96%" v-model="setting.value" v-on:input="saveSettings()">
|
||||
</template>
|
||||
|
||||
<template v-if="setting.type === 'password'">
|
||||
<input :type="setting.hidden ? 'password' : 'text'" class="dark_bordered" style="width: calc(96% - 28px);" v-model="setting.value" v-on:input="saveSettings()">
|
||||
<div class="password_toggle" @click="setting.hidden = !setting.hidden;">
|
||||
<i class="fas fa-eye-slash" v-if="setting.hidden"></i>
|
||||
<i class="fas fa-eye" v-else></i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="setting.type === 'select'">
|
||||
<div class="bar_select">
|
||||
<select v-model="setting.value">
|
||||
@ -625,7 +597,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar" hidden>
|
||||
<button type="button" class="confirm_btn cancel_btn tl" onclick="Settings.save()">dialog.close</button>
|
||||
</div>
|
||||
<div class="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
@ -673,21 +645,6 @@
|
||||
|
||||
<div id="plugin_dialog_wrapper"></div>
|
||||
|
||||
<dialog id="action_selector" v-if="open">
|
||||
<input type="text" v-model="search_input" autocomplete="off" autosave="off" autocorrect="off" spellcheck="off" autocapitalize="off">
|
||||
<i class="material-icons" id="action_search_bar_icon">search</i>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-for="(item, i) in actions" v-on:click="ActionControl.click(item, $event)" v-bind:class="{selected: i === index}" v-on:mouseenter="index = i">
|
||||
<div class="icon_wrapper normal" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<label>{{ item.keybind.label }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="small_text" v-if="actions[index]">{{ Pressing.alt ? actions[index].keybind.label : actions[index].description }}</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<header>
|
||||
<ul id="mac_window_menu" hidden></ul>
|
||||
<div id="title" class="app-drag-region">
|
||||
@ -704,7 +661,22 @@
|
||||
<button id="web_download_button" hidden><a class="tl" href="https://blockbench.net/downloads">web.download_app</a></button>
|
||||
</header>
|
||||
|
||||
<div id="page_wrapper">
|
||||
<div id="page_wrapper" class="hidden">
|
||||
|
||||
<dialog id="action_selector" v-if="open">
|
||||
<input type="text" v-model="search_input" autocomplete="off" autosave="off" autocorrect="off" spellcheck="off" autocapitalize="off">
|
||||
<i class="material-icons" id="action_search_bar_icon">search</i>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-for="(item, i) in actions" v-on:click="ActionControl.click(item, $event)" v-bind:class="{selected: i === index}" v-on:mouseenter="index = i">
|
||||
<div class="icon_wrapper normal" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<label>{{ item.keybind.label }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="small_text" v-if="actions[index]">{{ Pressing.alt ? actions[index].keybind.label : actions[index].description }}</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<div id="blackout" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"></div>
|
||||
|
||||
@ -973,7 +945,7 @@
|
||||
<li
|
||||
class="color" v-for="color in palette"
|
||||
:title="color" :key="color"
|
||||
:class="{selected: color == main_color}"
|
||||
:class="{selected: color == main_color, contrast: isDarkColor(color)}"
|
||||
@click="setColor(color)"
|
||||
@mouseenter="hover_color = color"
|
||||
@mouseleave="hover_color = ''"
|
||||
@ -1017,12 +989,18 @@
|
||||
<div id="timeline_corner" v-bind:style="{width: head_width+'px'}"></div>
|
||||
<div id="timeline_time_wrapper">
|
||||
<div id="timeline_time" v-bind:style="{width: (size*length)+'px', left: -scroll_left+'px'}">
|
||||
<div v-for="t in timecodes" class="timeline_timecode" v-bind:style="{left: (t.time * size) + 'px'}">
|
||||
{{ t.text }}
|
||||
<div v-for="t in timecodes" class="timeline_timecode" v-bind:style="{left: (t.time * size) + 'px', width: (t.width * size) + 'px'}">
|
||||
<span>{{ t.text }}</span>
|
||||
<div class="substeps">
|
||||
<div v-for="n in Math.ceil(t.substeps)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="timeline_playhead"
|
||||
v-bind:style="{left: (playhead * size) + 'px'}"
|
||||
></div>
|
||||
<div id="timeline_endbracket"
|
||||
v-bind:style="{left: (animation_length * size) + 'px'}"
|
||||
></div>
|
||||
<div
|
||||
v-for="marker in markers"
|
||||
class="timeline_marker"
|
||||
@ -1040,9 +1018,9 @@
|
||||
></div>
|
||||
<li v-for="animator in animators" class="animator" :class="{selected: animator.selected}" :uuid="animator.uuid" v-on:click="animator.select();">
|
||||
<div class="animator_head_bar">
|
||||
<div class="channel_head" v-bind:style="{left: scroll_left+'px', width: head_width+'px'}">
|
||||
<div class="channel_head" v-bind:style="{left: scroll_left+'px', width: head_width+'px'}" v-on:dblclick.stop="toggleAnimator(animator)">
|
||||
<div class="text_button" v-on:click.stop="toggleAnimator(animator)">
|
||||
<i class="icon-open-state fa" v-bind:class="{'fa-caret-right': !animator.expanded, 'fa-caret-down': animator.expanded}"></i>
|
||||
<i class="icon-open-state fa" v-bind:class="{'fa-angle-right': !animator.expanded, 'fa-angle-down': animator.expanded}"></i>
|
||||
</div>
|
||||
<span v-on:click.stop="animator.select();">{{animator.name}}</span>
|
||||
<div class="text_button" v-on:click.stop="removeAnimator(animator)">
|
||||
@ -1060,7 +1038,11 @@
|
||||
</keyframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="animator_channel_bar" v-bind:style="{width: (size*length + head_width)+'px'}" v-for="channel in animator.channels" v-if="animator.expanded && (!focus_channel || channel == focus_channel)">
|
||||
<div class="animator_channel_bar"
|
||||
v-bind:style="{width: (size*length + head_width)+'px'}"
|
||||
v-for="channel in animator.channels"
|
||||
v-if="animator.expanded && (!focus_channel || channel == focus_channel || focus_channel == 'used' && animator[channel].length)"
|
||||
>
|
||||
<div class="channel_head" v-bind:style="{left: scroll_left+'px', width: head_width+'px'}">
|
||||
<div class="text_button" v-on:click.stop="animator.toggleMuted(channel)">
|
||||
<template v-if="channel === 'sound'">
|
||||
@ -1109,7 +1091,7 @@
|
||||
<div class="bar next_to_title" id="uv_title_bar">
|
||||
<div class="tool" onclick="Blockbench.openLink('https://blockbench.net/quickstart/')">
|
||||
<div class="tooltip tl">menu.help.quickstart</div>
|
||||
<i class="fa_big fas fa-directions"></i>
|
||||
<i class="fas fa-question-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
|
257
js/animations.js
257
js/animations.js
@ -20,6 +20,9 @@ class Animation {
|
||||
Merge.boolean(this, data, 'override')
|
||||
Merge.string(this, data, 'anim_time_update')
|
||||
Merge.number(this, data, 'length')
|
||||
if (typeof data.length == 'number') {
|
||||
this.setLength(this.length)
|
||||
}
|
||||
if (data.bones && !data.animators) {
|
||||
data.animators = data.bones;
|
||||
}
|
||||
@ -30,9 +33,9 @@ class Animation {
|
||||
var ba = this.getBoneAnimator(group)
|
||||
var kfs = data.animators[key]
|
||||
if (kfs && ba) {
|
||||
ba.rotation.length = 0;
|
||||
ba.position.length = 0;
|
||||
ba.scale.length = 0;
|
||||
ba.rotation.empty();
|
||||
ba.position.empty();
|
||||
ba.scale.empty();
|
||||
kfs.forEach(kf_data => {
|
||||
ba.addKeyframe(kf_data, kf_data.uuid);
|
||||
})
|
||||
@ -87,6 +90,7 @@ class Animation {
|
||||
Timeline.animators.purge();
|
||||
Timeline.selected.empty();
|
||||
Timeline.vue._data.markers = this.markers;
|
||||
Timeline.vue._data.animation_length = this.length;
|
||||
this.selected = true;
|
||||
this.playing = true;
|
||||
Animator.selected = this;
|
||||
@ -103,6 +107,14 @@ class Animation {
|
||||
Animator.preview();
|
||||
return this;
|
||||
}
|
||||
setLength(len) {
|
||||
len = limitNumber(len, 0, 1e4)
|
||||
this.length = len;
|
||||
if (Animator.selected == this) {
|
||||
Timeline.vue._data.animation_length = this.length;
|
||||
BarItems.slider_animation_length.update()
|
||||
}
|
||||
}
|
||||
createUniqueName(arr) {
|
||||
var scope = this;
|
||||
var others = Animator.animations;
|
||||
@ -217,7 +229,7 @@ class Animation {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
this.length = len
|
||||
this.setLength(len)
|
||||
if (this == Animator.selected) {
|
||||
BarItems.slider_animation_length.update()
|
||||
}
|
||||
@ -294,6 +306,7 @@ class GeneralAnimator {
|
||||
})
|
||||
}
|
||||
select() {
|
||||
if (this.getGroup().locked) return;
|
||||
var scope = this;
|
||||
TickUpdates.keyframes = true;
|
||||
for (var key in Animator.selected.animators) {
|
||||
@ -339,7 +352,7 @@ class GeneralAnimator {
|
||||
if (value) {
|
||||
keyframe.extend(value);
|
||||
} else if (this.fillValues) {
|
||||
this.fillValues(keyframe, value);
|
||||
this.fillValues(keyframe, value, true);
|
||||
}
|
||||
keyframe.channel = channel;
|
||||
keyframe.time = time;
|
||||
@ -468,7 +481,7 @@ class BoneAnimator extends GeneralAnimator {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
fillValues(keyframe, values) {
|
||||
fillValues(keyframe, values, allow_expression) {
|
||||
|
||||
if (values instanceof Array) {
|
||||
keyframe.extend({
|
||||
@ -486,7 +499,7 @@ class BoneAnimator extends GeneralAnimator {
|
||||
z: values
|
||||
})
|
||||
} else if (values == null) {
|
||||
var ref = this.interpolate(Timeline.time, keyframe.channel, true)
|
||||
var ref = this.interpolate(keyframe.channel, allow_expression)
|
||||
if (ref) {
|
||||
let e = 1e2
|
||||
ref.forEach((r, i) => {
|
||||
@ -551,7 +564,8 @@ class BoneAnimator extends GeneralAnimator {
|
||||
bone.scale.z *= arr[2] || 0.00001;
|
||||
return this;
|
||||
}
|
||||
interpolate(time, channel, allow_expression) {
|
||||
interpolate(channel, allow_expression) {
|
||||
let time = Timeline.time;
|
||||
var i = 0;
|
||||
var before = false
|
||||
var after = false
|
||||
@ -607,13 +621,13 @@ class BoneAnimator extends GeneralAnimator {
|
||||
}
|
||||
return result
|
||||
}
|
||||
displayFrame(time) {
|
||||
displayFrame() {
|
||||
if (!this.doRender()) return;
|
||||
this.getGroup()
|
||||
|
||||
if (!this.muted.rotation) this.displayRotation(this.interpolate(time, 'rotation'))
|
||||
if (!this.muted.position) this.displayPosition(this.interpolate(time, 'position'))
|
||||
if (!this.muted.scale) this.displayScale(this.interpolate(time, 'scale'))
|
||||
if (!this.muted.rotation) this.displayRotation(this.interpolate('rotation'))
|
||||
if (!this.muted.position) this.displayPosition(this.interpolate('position'))
|
||||
if (!this.muted.scale) this.displayScale(this.interpolate('scale'))
|
||||
}
|
||||
}
|
||||
BoneAnimator.prototype.channels = ['rotation', 'position', 'scale']
|
||||
@ -643,6 +657,7 @@ class EffectAnimator extends GeneralAnimator {
|
||||
if (diff >= 0 && diff < (1/60) * (Timeline.playback_speed/100)) {
|
||||
if (kf.file && !kf.cooldown) {
|
||||
var media = new Audio(kf.file);
|
||||
window._media = media
|
||||
media.volume = Math.clamp(settings.volume.value/100, 0, 1);
|
||||
media.play();
|
||||
Timeline.playing_sounds.push(media);
|
||||
@ -810,9 +825,6 @@ class Keyframe {
|
||||
this.get('y'),
|
||||
this.get('z'),
|
||||
]
|
||||
if (this.channel === 'rotation' && this.isQuaternion) {
|
||||
arr.push(this.get('w'))
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
getFixed() {
|
||||
@ -860,7 +872,7 @@ class Keyframe {
|
||||
Timeline.selected.forEach(function(kf) {
|
||||
kf.selected = false
|
||||
})
|
||||
Timeline.selected.length = 0
|
||||
Timeline.selected.empty()
|
||||
}
|
||||
if (event && event.shiftKey && Timeline.selected.length) {
|
||||
var last = Timeline.selected[Timeline.selected.length-1]
|
||||
@ -1162,7 +1174,7 @@ const Animator = {
|
||||
join() {
|
||||
|
||||
Animator.open = true;
|
||||
selected.length = 0
|
||||
selected.empty()
|
||||
Canvas.updateAllBones()
|
||||
|
||||
//if (quad_previews.enabled) {
|
||||
@ -1182,7 +1194,7 @@ const Animator = {
|
||||
}
|
||||
TickUpdates.keyframes = true;
|
||||
if (outlines.children.length) {
|
||||
outlines.children.length = 0
|
||||
outlines.children.empty()
|
||||
Canvas.updateAllPositions()
|
||||
}
|
||||
if (!Animator.selected && Animator.animations.length) {
|
||||
@ -1222,7 +1234,7 @@ const Animator = {
|
||||
Group.all.forEach(group => {
|
||||
Animator.animations.forEach(animation => {
|
||||
if (animation.playing) {
|
||||
animation.getBoneAnimator(group).displayFrame(Timeline.time)
|
||||
animation.getBoneAnimator(group).displayFrame()
|
||||
}
|
||||
})
|
||||
group.mesh.updateMatrixWorld()
|
||||
@ -1391,7 +1403,7 @@ const Animator = {
|
||||
ani_tag.timeline[timecode] = kf.instructions.split('\n');
|
||||
})
|
||||
|
||||
} else if (a.animators[uuid].keyframes.length && a.animators[uuid].group) {
|
||||
} else if (a.animators[uuid].keyframes.length && a.animators[uuid].getGroup()) {
|
||||
|
||||
var group = a.animators[uuid].group;
|
||||
var bone_tag = ani_tag.bones[group.name] = {};
|
||||
@ -1413,6 +1425,12 @@ const Animator = {
|
||||
let timecodes = Object.keys(channels[channel])
|
||||
if (timecodes.length === 1) {
|
||||
bone_tag[channel] = channels[channel][timecodes[0]]
|
||||
if (channel == 'scale' &&
|
||||
channels[channel][timecodes[0]] instanceof Array &&
|
||||
channels[channel][timecodes[0]].allEqual(channels[channel][timecodes[0]][0])
|
||||
) {
|
||||
bone_tag[channel] = channels[channel][timecodes[0]][0];
|
||||
}
|
||||
} else {
|
||||
timecodes.sort().forEach((time) => {
|
||||
if (!bone_tag[channel]) {
|
||||
@ -1442,6 +1460,7 @@ const Timeline = {
|
||||
playback_speed: 100,
|
||||
time: 0,
|
||||
get second() {return Timeline.time},
|
||||
get animation_length() {return Animator.selected ? Animator.selected.length : 0;},
|
||||
playing: false,
|
||||
selector: {
|
||||
start: [0, 0],
|
||||
@ -1502,7 +1521,7 @@ const Timeline = {
|
||||
var min_time = (rect.ax-Timeline.vue._data.head_width-8)/Timeline.vue._data.size;
|
||||
var max_time = (rect.bx-Timeline.vue._data.head_width-8)/Timeline.vue._data.size;
|
||||
|
||||
Timeline.selected.length = 0;
|
||||
Timeline.selected.empty()
|
||||
for (var animator of Timeline.animators) {
|
||||
var node = $('#timeline_body_inner .animator[uuid=' + animator.uuid + ']').get(0)
|
||||
var offset = node && node.offsetTop;
|
||||
@ -1562,10 +1581,14 @@ const Timeline = {
|
||||
if (!editing) {
|
||||
Timeline.setTimecode(seconds)
|
||||
}
|
||||
Timeline.updateSize()
|
||||
//Scroll
|
||||
if (Timeline.getMaxLength() !== Timeline.vue._data.length) {
|
||||
Timeline.updateSize()
|
||||
}
|
||||
Timeline.revealTime(seconds)
|
||||
},
|
||||
revealTime(time) {
|
||||
var scroll = $('#timeline_body').scrollLeft()
|
||||
var playhead = Timeline.time * Timeline.vue._data.size + 8
|
||||
var playhead = time * Timeline.vue._data.size + 8
|
||||
if (playhead < scroll || playhead > scroll + $('#timeline_body').width() - Timeline.vue._data.head_width) {
|
||||
$('#timeline_body').scrollLeft(playhead-16)
|
||||
}
|
||||
@ -1595,14 +1618,24 @@ const Timeline = {
|
||||
$('#timeline_time').on('mousedown touchstart', e => {
|
||||
if (e.which !== 1 && !event.changedTouches) return;
|
||||
if (e.target.classList.contains('timeline_marker')) return;
|
||||
convertTouchEvent(e);
|
||||
Timeline.dragging_playhead = true;
|
||||
let time = (e.offsetX) / Timeline.vue._data.size
|
||||
Timeline.setTime(Timeline.snapTime(time))
|
||||
Animator.preview()
|
||||
|
||||
if (e.target.id == 'timeline_endbracket') {
|
||||
|
||||
Timeline.dragging_endbracket = true;
|
||||
Undo.initEdit({animations: [Animator.selected]});
|
||||
|
||||
} else {
|
||||
|
||||
convertTouchEvent(e);
|
||||
Timeline.dragging_playhead = true;
|
||||
let time = (e.offsetX) / Timeline.vue._data.size
|
||||
Timeline.setTime(Timeline.snapTime(time))
|
||||
Animator.preview()
|
||||
}
|
||||
})
|
||||
$(document).on('mousemove touchmove', e => {
|
||||
if (Timeline.dragging_playhead) {
|
||||
|
||||
convertTouchEvent(e);
|
||||
let offset = e.clientX - $('#timeline_time').offset().left;
|
||||
let time = Timeline.snapTime(offset / Timeline.vue._data.size)
|
||||
@ -1610,12 +1643,26 @@ const Timeline = {
|
||||
Timeline.setTime(time)
|
||||
Animator.preview()
|
||||
}
|
||||
} else if (Timeline.dragging_endbracket) {
|
||||
|
||||
convertTouchEvent(e);
|
||||
let offset = e.clientX - $('#timeline_time').offset().left;
|
||||
let time = Timeline.snapTime(offset / Timeline.vue._data.size)
|
||||
|
||||
Animator.selected.setLength(time)
|
||||
Timeline.revealTime(time)
|
||||
|
||||
}
|
||||
})
|
||||
.on('mouseup touchend', e => {
|
||||
if (Timeline.dragging_playhead) {
|
||||
delete Timeline.dragging_playhead
|
||||
Timeline.pause();
|
||||
|
||||
} else if (Timeline.dragging_endbracket) {
|
||||
|
||||
Undo.finishEdit('Change Animation Length')
|
||||
delete Timeline.dragging_endbracket
|
||||
}
|
||||
})
|
||||
//Keyframe inputs
|
||||
@ -1679,16 +1726,33 @@ const Timeline = {
|
||||
}
|
||||
})
|
||||
|
||||
$('#timeline_vue').on('mousewheel', function() {
|
||||
$('#timeline_vue').on('mousewheel scroll', function(e) {
|
||||
e.preventDefault()
|
||||
var body = $('#timeline_body').get(0)
|
||||
if (event.shiftKey) {
|
||||
body.scrollLeft += event.deltaY/4
|
||||
|
||||
} else if (event.ctrlOrCmd) {
|
||||
var offset = 1 - event.deltaY/600
|
||||
Timeline.vue._data.size = limitNumber(Timeline.vue._data.size * offset, 10, 1000)
|
||||
body.scrollLeft *= offset
|
||||
|
||||
let mouse_pos = event.clientX - $(this).offset().left;
|
||||
|
||||
var zoom = 1 - event.deltaY/600
|
||||
let original_size = Timeline.vue._data.size
|
||||
Timeline.vue._data.size = limitNumber(Timeline.vue._data.size * zoom, 10, 1000)
|
||||
//let val = ((body.scrollLeft + mouse_pos) * (Timeline.vue._data.size - original_size) ) / 128
|
||||
|
||||
let size_ratio = Timeline.vue._data.size / original_size
|
||||
let offset = mouse_pos - body.scrollLeft - 180
|
||||
let val = (size_ratio-1) * offset;
|
||||
// todo: optimize zooming in
|
||||
body.scrollLeft += val
|
||||
/*
|
||||
Timeline.vue._data.size = limitNumber(Timeline.vue._data.size * zoom, 10, 1000)
|
||||
body.scrollLeft *= zoom
|
||||
let l = (event.offsetX / body.clientWidth) * 500 * (event.deltaY<0?1:-0.2)
|
||||
body.scrollLeft += l
|
||||
*/
|
||||
|
||||
} else {
|
||||
body.scrollTop += event.deltaY/6.25
|
||||
}
|
||||
@ -1752,88 +1816,56 @@ const Timeline = {
|
||||
}
|
||||
Undo.addKeyframeCasualties(deleted);
|
||||
Undo.finishEdit('drag keyframes')
|
||||
}
|
||||
})
|
||||
$('#timeline_body .keyframe:not(.ui-draggable)').draggable({
|
||||
axis: 'x',
|
||||
distance: 4,
|
||||
helper: () => $('<div></div>'),
|
||||
start: function(event, ui) {
|
||||
|
||||
var id = $(event.target).attr('id');
|
||||
var clicked = Timeline.keyframes.findInArray('uuid', id)
|
||||
|
||||
if (!$(event.target).hasClass('selected') && !event.shiftKey && Timeline.selected.length != 0) {
|
||||
clicked.select()
|
||||
} else if (clicked && !clicked.selected) {
|
||||
clicked.select({shiftKey: true})
|
||||
}
|
||||
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
Timeline.dragging_keyframes = true;
|
||||
|
||||
var i = 0;
|
||||
for (var kf of Timeline.selected) {
|
||||
kf.time_before = kf.time
|
||||
}
|
||||
},
|
||||
drag: function(event, ui) {
|
||||
var difference = (ui.position.left - ui.originalPosition.left - 8) / Timeline.vue._data.size;
|
||||
var id = $(ui.helper).attr('id')
|
||||
var snap_value = false
|
||||
var nearest
|
||||
|
||||
for (var kf of Timeline.selected) {
|
||||
var t = limitNumber(kf.time_before + difference, 0, 256)
|
||||
if (kf.uuid === id) {
|
||||
ui.position.left = t * Timeline.vue._data.size + 8
|
||||
}
|
||||
kf.time = Timeline.snapTime(t);
|
||||
}
|
||||
BarItems.slider_keyframe_time.update()
|
||||
Animator.preview()
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
var deleted = []
|
||||
for (var kf of Timeline.selected) {
|
||||
delete kf.time_before;
|
||||
kf.replaceOthers(deleted);
|
||||
}
|
||||
Undo.addKeyframeCasualties(deleted);
|
||||
Undo.finishEdit('drag keyframes')
|
||||
setTimeout(() => {
|
||||
Timeline.dragging_keyframes = false;
|
||||
}, 20)
|
||||
}
|
||||
})
|
||||
},
|
||||
updateSize() {
|
||||
let size = Timeline.vue._data.size
|
||||
getMaxLength() {
|
||||
var max_length = ($('#timeline_body').width()-8) / Timeline.vue._data.size;
|
||||
Timeline.keyframes.forEach((kf) => {
|
||||
max_length = Math.max(max_length, kf.time)
|
||||
})
|
||||
max_length = Math.max(max_length, Timeline.time) + 50/Timeline.vue._data.size
|
||||
Timeline.vue._data.length = max_length
|
||||
Timeline.vue._data.timecodes.length = 0
|
||||
return max_length;
|
||||
},
|
||||
updateSize() {
|
||||
let size = Timeline.vue._data.size
|
||||
Timeline.vue._data.length = Timeline.getMaxLength()
|
||||
Timeline.vue._data.timecodes.empty()
|
||||
|
||||
var step = 1
|
||||
if (size < 1) {step = 1}
|
||||
else if (size < 20) {step = 4}
|
||||
else if (size < 40) {step = 2}
|
||||
else if (size < 90) {step = 1}
|
||||
else if (size < 180) {step = 0.5}
|
||||
else if (size < 400) {step = 0.2}
|
||||
else if (size < 800) {step = 0.1}
|
||||
else if (size < 100) {step = 1}
|
||||
else if (size < 256) {step = 0.5}
|
||||
else if (size < 520) {step = 0.25}
|
||||
else if (size < 660) {step = 0.2}
|
||||
else if (size < 860) {step = 0.1}
|
||||
else {step = 0.05}
|
||||
|
||||
|
||||
if (step < 1) {
|
||||
var FPS = Timeline.getStep();
|
||||
step = Math.round(step/FPS) * FPS
|
||||
step = 1/Math.round(1/step)
|
||||
//step = 1/Math.round(1/step)
|
||||
}
|
||||
|
||||
let substeps = step / Timeline.getStep()
|
||||
while (substeps > 8) {
|
||||
substeps /= 2;
|
||||
}
|
||||
//substeps = Math.round(substeps)
|
||||
|
||||
|
||||
var i = 0;
|
||||
while (i < Timeline.vue._data.length) {
|
||||
Timeline.vue._data.timecodes.push({
|
||||
time: i,
|
||||
width: step,
|
||||
substeps: substeps,
|
||||
text: Math.round(i*100)/100
|
||||
})
|
||||
i += step;
|
||||
@ -1907,6 +1939,7 @@ const Timeline = {
|
||||
'_',
|
||||
'select_all',
|
||||
'bring_up_all_animations',
|
||||
'fold_all_animations',
|
||||
'clear_timeline',
|
||||
])
|
||||
}
|
||||
@ -1954,8 +1987,9 @@ onVueSetup(function() {
|
||||
data: {
|
||||
size: 150,
|
||||
length: 10,
|
||||
animation_length: 0,
|
||||
scroll_left: 0,
|
||||
head_width: 170,
|
||||
head_width: 180,
|
||||
timecodes: [],
|
||||
animators: Timeline.animators,
|
||||
markers: [],
|
||||
@ -2006,6 +2040,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
}
|
||||
Blockbench.import({
|
||||
resource_id: 'animation',
|
||||
extensions: ['json'],
|
||||
type: 'JSON Animation',
|
||||
startpath: path
|
||||
@ -2035,6 +2070,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
}
|
||||
Blockbench.export({
|
||||
resource_id: 'animation',
|
||||
type: 'JSON Animation',
|
||||
extensions: ['json'],
|
||||
name: (Project.geometry_name||'model')+'.animation',
|
||||
@ -2075,7 +2111,13 @@ BARS.defineActions(function() {
|
||||
return Animator.selected.length
|
||||
},
|
||||
change: function(modify) {
|
||||
Animator.selected.length = limitNumber(modify(Animator.selected.length), 0, 1e4)
|
||||
Animator.selected.setLength(limitNumber(modify(Animator.selected.length), 0, 1e4))
|
||||
},
|
||||
onBefore: function() {
|
||||
Undo.initEdit({animations: [Animator.selected]});
|
||||
},
|
||||
onAfter: function() {
|
||||
Undo.finishEdit('Change Animation Length')
|
||||
}
|
||||
})
|
||||
new NumSlider('slider_animation_speed', {
|
||||
@ -2169,12 +2211,28 @@ BARS.defineActions(function() {
|
||||
Animator.preview()
|
||||
}
|
||||
})
|
||||
new Action('resolve_keyframe_expressions', {
|
||||
icon: 'functions',
|
||||
category: 'animation',
|
||||
condition: () => Animator.open && Timeline.selected.length,
|
||||
click: function () {
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
Timeline.selected.forEach((kf) => {
|
||||
if (kf.animator.fillValues) {
|
||||
kf.animator.fillValues(kf, null, false);
|
||||
}
|
||||
})
|
||||
Undo.finishEdit('reset keyframes')
|
||||
updateKeyframeSelection()
|
||||
}
|
||||
})
|
||||
new Action('change_keyframe_file', {
|
||||
icon: 'fa-file-audio',
|
||||
category: 'animation',
|
||||
condition: () => (Animator.open && Timeline.selected.length && Timeline.selected[0].channel == 'sound' && isApp),
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'animation_audio',
|
||||
extensions: ['ogg'],
|
||||
type: 'Audio File',
|
||||
startpath: Timeline.selected[0].file
|
||||
@ -2365,6 +2423,7 @@ BARS.defineActions(function() {
|
||||
category: 'animation',
|
||||
condition: {modes: ['animate']},
|
||||
click: function () {
|
||||
if (!Animator.selected) return;
|
||||
for (var uuid in Animator.selected.animators) {
|
||||
var ba = Animator.selected.animators[uuid]
|
||||
if (ba && ba.keyframes.length) {
|
||||
@ -2374,6 +2433,17 @@ BARS.defineActions(function() {
|
||||
|
||||
}
|
||||
})
|
||||
new Action('fold_all_animations', {
|
||||
icon: 'format_indent_decrease',
|
||||
category: 'animation',
|
||||
condition: {modes: ['animate']},
|
||||
click: function () {
|
||||
for (var animator of Timeline.animators) {
|
||||
animator.expanded = false;
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
new Action('clear_timeline', {
|
||||
icon: 'clear_all',
|
||||
category: 'animation',
|
||||
@ -2398,6 +2468,7 @@ BARS.defineActions(function() {
|
||||
new BarSelect('timeline_focus', {
|
||||
options: {
|
||||
all: true,
|
||||
used: true,
|
||||
rotation: tl('timeline.rotation'),
|
||||
position: tl('timeline.position'),
|
||||
scale: tl('timeline.scale'),
|
||||
|
52
js/api.js
52
js/api.js
@ -299,6 +299,7 @@ const Blockbench = {
|
||||
//startpath
|
||||
//title
|
||||
//errorbox
|
||||
//resource_id
|
||||
|
||||
if (isApp) {
|
||||
var properties = []
|
||||
@ -309,6 +310,9 @@ const Blockbench = {
|
||||
options.type = 'Images'
|
||||
options.extensions = ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'tif', 'gif']
|
||||
}
|
||||
if (!options.startpath && options.resource_id) {
|
||||
options.startpath = StateMemory.dialog_paths[options.resource_id]
|
||||
}
|
||||
|
||||
ElecDialogs.showOpenDialog(
|
||||
currentwindow,
|
||||
@ -323,6 +327,11 @@ const Blockbench = {
|
||||
defaultPath: options.startpath
|
||||
},
|
||||
function (fileNames) {
|
||||
if (!fileNames) return;
|
||||
if (options.resource_id) {
|
||||
StateMemory.dialog_paths[options.resource_id] = PathModule.dirname(fileNames[0])
|
||||
StateMemory.save('dialog_paths')
|
||||
}
|
||||
Blockbench.read(fileNames, options, cb)
|
||||
})
|
||||
} else {
|
||||
@ -478,6 +487,7 @@ const Blockbench = {
|
||||
savetype
|
||||
project_file
|
||||
custom_writer
|
||||
resource_id
|
||||
*/
|
||||
if (Blockbench.isWeb) {
|
||||
var file_name = options.name + (options.extensions ? '.'+options.extensions[0] : '')
|
||||
@ -504,6 +514,12 @@ const Blockbench = {
|
||||
cb(file_name)
|
||||
}
|
||||
} else {
|
||||
if (!options.startpath && options.resource_id) {
|
||||
options.startpath = StateMemory.dialog_paths[options.resource_id]
|
||||
if (options.name) {
|
||||
options.startpath += osfs + options.name + (options.extensions ? '.'+options.extensions[0] : '');
|
||||
}
|
||||
}
|
||||
ElecDialogs.showSaveDialog(currentwindow, {
|
||||
dontAddToRecent: true,
|
||||
filters: [ {
|
||||
@ -515,6 +531,10 @@ const Blockbench = {
|
||||
: options.name
|
||||
}, function (file_path) {
|
||||
if (!file_path) return;
|
||||
if (options.resource_id) {
|
||||
StateMemory.dialog_paths[options.resource_id] = PathModule.dirname(file_path)
|
||||
StateMemory.save('dialog_paths')
|
||||
}
|
||||
var extension = pathToExtension(file_path);
|
||||
if (!extension && options.extensions && options.extensions[0]) {
|
||||
file_path += '.'+options.extensions[0]
|
||||
@ -635,6 +655,38 @@ if (isApp) {
|
||||
if (Blockbench.platform.includes('win32') === true) osfs = '\\';
|
||||
}
|
||||
|
||||
|
||||
|
||||
const StateMemory = {
|
||||
init(key, type) {
|
||||
let saved = localStorage.getItem(`StateMemory.${key}`)
|
||||
if (typeof saved == 'string') {
|
||||
try {
|
||||
saved = JSON.parse(saved)
|
||||
} catch (err) {
|
||||
localStorage.clearItem(`StateMemory.${key}`)
|
||||
}
|
||||
}
|
||||
if ( saved !== null && (typeof saved == type || (type == 'array' && saved instanceof Array)) ) {
|
||||
StateMemory[key] = saved;
|
||||
} else {
|
||||
StateMemory[key] = (() => {switch (type) {
|
||||
case 'string': return ''; break;
|
||||
case 'number': return 0; break;
|
||||
case 'boolean': return false; break;
|
||||
case 'object': return {}; break;
|
||||
case 'array': return []; break;
|
||||
}})();
|
||||
}
|
||||
},
|
||||
save(key) {
|
||||
let serialized = JSON.stringify(StateMemory[key])
|
||||
localStorage.setItem(`StateMemory.${key}`, serialized)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
document.ondragover = function(event) {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
@ -29,39 +29,7 @@ var Prop = {
|
||||
connections : 0,
|
||||
facing : 'north'
|
||||
}
|
||||
const Project = {
|
||||
name : '',
|
||||
parent : '',
|
||||
geometry_name : '',
|
||||
description : '',
|
||||
_box_uv : false,
|
||||
get box_uv() {return Project._box_uv},
|
||||
set box_uv(v) {
|
||||
if (Project._box_uv != v) {
|
||||
Project._box_uv = v;
|
||||
switchBoxUV(v);
|
||||
}
|
||||
},
|
||||
get texture_width() {return Project._texture_width},
|
||||
get texture_height() {return Project._texture_height},
|
||||
set texture_width(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
Project._texture_width = n;
|
||||
},
|
||||
set texture_height(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
Project._texture_height = n;
|
||||
},
|
||||
_texture_width : 16,
|
||||
_texture_height : 16,
|
||||
ambientocclusion: true,
|
||||
front_gui_light: false,
|
||||
get optional_box_uv() {
|
||||
return Format.optional_box_uv;
|
||||
}
|
||||
}
|
||||
|
||||
const mouse_pos = {x:0,y:0}
|
||||
const sort_collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
|
||||
|
||||
@ -175,12 +143,13 @@ function updateProjectResolution() {
|
||||
//Selections
|
||||
function updateSelection() {
|
||||
elements.forEach(obj => {
|
||||
if (selected.includes(obj) && !obj.selected) {
|
||||
if (selected.includes(obj) && !obj.selected && !obj.locked) {
|
||||
obj.selectLow()
|
||||
} else if (!selected.includes(obj) && obj.selected) {
|
||||
} else if ((!selected.includes(obj) || obj.locked) && obj.selected) {
|
||||
obj.unselect()
|
||||
}
|
||||
})
|
||||
if (Group.selected && Group.selected.locked) Group.selected.unselect()
|
||||
|
||||
Cube.all.forEach(cube => {
|
||||
if (cube.visibility) {
|
||||
@ -221,7 +190,6 @@ function updateSelection() {
|
||||
|
||||
BarItems.cube_counter.update();
|
||||
updateNslideValues();
|
||||
Blockbench.globalMovement = isMovementGlobal();
|
||||
updateCubeHighlights();
|
||||
Canvas.updateOrigin();
|
||||
Transformer.updateSelection();
|
||||
@ -298,7 +266,7 @@ function createSelection() {
|
||||
setInterval(function() {
|
||||
if (Outliner.root.length || textures.length) {
|
||||
try {
|
||||
var model = Codecs.project.compile({compressed: true});
|
||||
var model = Codecs.project.compile({compressed: false});
|
||||
localStorage.setItem('backup_model', model)
|
||||
} catch (err) {
|
||||
console.log('Unable to create backup. ', err)
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
CustomTheme.setup()
|
||||
|
||||
StateMemory.init('dialog_paths', 'object')
|
||||
|
||||
initCanvas()
|
||||
animate()
|
||||
|
||||
@ -117,4 +119,6 @@ Modes.options.start.select()
|
||||
|
||||
loadInstalledPlugins();
|
||||
|
||||
document.getElementById('page_wrapper').classList.remove('hidden')
|
||||
|
||||
Blockbench.setup_successful = true;
|
||||
|
@ -7,6 +7,7 @@ const zlib = require('zlib');
|
||||
const exec = require('child_process').exec;
|
||||
const originalFs = require('original-fs');
|
||||
const https = require('https');
|
||||
const PathModule = require('path')
|
||||
|
||||
const currentwindow = electron.getCurrentWindow();
|
||||
const ElecDialogs = {};
|
||||
@ -49,7 +50,9 @@ function initializeDesktopApp() {
|
||||
shell.openExternal(event.target.href);
|
||||
return true;
|
||||
});
|
||||
if (compareVersions('5.0.0', process.versions.electron)) {
|
||||
if (currentwindow.webContents.zoomLevel !== undefined) {
|
||||
Prop.zoom = 100 + currentwindow.webContents.zoomLevel*12
|
||||
} else if (compareVersions('5.0.0', process.versions.electron)) {
|
||||
Prop.zoom = 100 + currentwindow.webContents._getZoomLevel()*12
|
||||
} else {
|
||||
Prop.zoom = 100 + currentwindow.webContents.getZoomLevel()*12
|
||||
@ -114,6 +117,7 @@ function addRecentProject(data) {
|
||||
}
|
||||
i--;
|
||||
}
|
||||
if (data.name.length > 48) data.name = data.name.substr(0, 20) + '...' + data.name.substr(-20);
|
||||
let project = {
|
||||
name: data.name,
|
||||
path: data.path,
|
||||
@ -214,7 +218,7 @@ function installUpdate() {
|
||||
|
||||
var file = originalFs.createWriteStream(asar_path);
|
||||
|
||||
var request = https.get("https://blockbench.net/api/app.asar", function(response) {
|
||||
https.get("https://blockbench.net/api/app.asar", function(response) {
|
||||
response.pipe(file);
|
||||
|
||||
total_bytes = parseInt(response.headers['content-length']);
|
||||
@ -252,12 +256,12 @@ function changeImageEditor(texture, from_settings) {
|
||||
var path;
|
||||
if (Blockbench.platform == 'darwin') {
|
||||
switch (id) {
|
||||
case 'ps': path = '/Applications/Adobe Photoshop CC 2019/Adobe Photoshop CC 2019.app'; break;
|
||||
case 'ps': path = '/Applications/Adobe Photoshop CC 2020/Adobe Photoshop CC 2020.app'; break;
|
||||
case 'gimp':path = '/Applications/Gimp-2.10.app'; break;
|
||||
}
|
||||
} else {
|
||||
switch (id) {
|
||||
case 'ps': path = 'C:\\Program Files\\Adobe\\Adobe Photoshop CC 2019\\Photoshop.exe'; break;
|
||||
case 'ps': path = 'C:\\Program Files\\Adobe\\Adobe Photoshop CC 2020\\Photoshop.exe'; break;
|
||||
case 'gimp':path = 'C:\\Program Files\\GIMP 2\\bin\\gimp-2.10.exe'; break;
|
||||
case 'pdn': path = 'C:\\Program Files\\paint.net\\PaintDotNet.exe'; break;
|
||||
}
|
||||
|
@ -1778,6 +1778,7 @@ window.changeDisplaySkin = function() {
|
||||
}, function(result) {
|
||||
if (result === 0) {
|
||||
Blockbench.import({
|
||||
resource_id: 'minecraft_skin',
|
||||
extensions: ['png'],
|
||||
type: 'PNG Player Skin',
|
||||
readtype: 'image'
|
||||
@ -1937,6 +1938,51 @@ BARS.defineActions(function() {
|
||||
condition: () => display_mode,
|
||||
click: function () {showDialog('create_preset')}
|
||||
})
|
||||
new Action('apply_display_preset', {
|
||||
icon: 'fa-list',
|
||||
category: 'display',
|
||||
condition: () => display_mode,
|
||||
click: function (e) {
|
||||
new Menu(this.children()).open(e.target)
|
||||
},
|
||||
children: function() {
|
||||
var presets = []
|
||||
display_presets.forEach(function(p) {
|
||||
var icon = 'label'
|
||||
if (p.fixed) {
|
||||
switch(p.id) {
|
||||
case 'item': icon = 'filter_vintage'; break;
|
||||
case 'block': icon = 'fa-cube'; break;
|
||||
case 'handheld': icon = 'build'; break;
|
||||
case 'rod': icon = 'remove'; break;
|
||||
}
|
||||
}
|
||||
presets.push({
|
||||
icon: icon,
|
||||
name: p.id ? tl('display.preset.'+p.id) : p.name,
|
||||
children: [
|
||||
{name: 'action.apply_display_preset.here', icon: 'done', click() {
|
||||
DisplayMode.applyPreset(p)
|
||||
}},
|
||||
{name: 'action.apply_display_preset.everywhere', icon: 'done_all', click() {
|
||||
DisplayMode.applyPreset(p, true)
|
||||
}},
|
||||
{
|
||||
icon: 'delete',
|
||||
name: 'generic.delete',
|
||||
condition: !p.fixed,
|
||||
click: function() {
|
||||
display_presets.splice(display_presets.indexOf(p), 1);
|
||||
localStorage.setItem('display_presets', JSON.stringify(display_presets))
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
return presets;
|
||||
}
|
||||
})
|
||||
|
||||
new BarSelect('gui_light', {
|
||||
options: {
|
||||
side: true,
|
||||
|
@ -172,6 +172,7 @@ class Action extends BarItem {
|
||||
this.linked_setting = data.linked_setting
|
||||
}
|
||||
if (data.condition) this.condition = data.condition
|
||||
this.children = data.children;
|
||||
|
||||
//Node
|
||||
this.click = data.click
|
||||
@ -751,7 +752,7 @@ class BarSelect extends Widget {
|
||||
}
|
||||
let menu = new Menu(items);
|
||||
menu.node.style['min-width'] = this.node.clientWidth+'px';
|
||||
menu.open(this.node, this);
|
||||
menu.open(event.target, this);
|
||||
}
|
||||
trigger(event) {
|
||||
if (!event) event = 0;
|
||||
@ -1518,8 +1519,13 @@ const BARS = {
|
||||
'export_palette',
|
||||
'generate_palette',
|
||||
'sort_palette',
|
||||
'load_palette',
|
||||
]
|
||||
})
|
||||
//update 3.5
|
||||
if (!Toolbars.palette.children.includes(BarItems.load_palette)) {
|
||||
Toolbars.palette.add(BarItems.load_palette)
|
||||
}
|
||||
Toolbars.color_picker = new Toolbar({
|
||||
id: 'color_picker',
|
||||
children: [
|
||||
@ -1538,14 +1544,11 @@ const BARS = {
|
||||
'copy',
|
||||
'paste',
|
||||
'add_display_preset',
|
||||
'apply_display_preset',
|
||||
'gui_light'
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
//update 3.3.1
|
||||
if (!Toolbars.display.children.includes(BarItems.gui_light)) {
|
||||
Toolbars.display.add(BarItems.gui_light)
|
||||
}
|
||||
//UV
|
||||
Toolbars.main_uv = new Toolbar({
|
||||
id: 'main_uv',
|
||||
@ -1682,6 +1685,7 @@ const BARS = {
|
||||
|
||||
BarItems.reset_keybindings.toElement('#keybinds_title_bar')
|
||||
BarItems.load_plugin.toElement('#plugins_header_bar')
|
||||
BarItems.load_plugin_from_url.toElement('#plugins_header_bar')
|
||||
BarItems.uv_dialog.toElement('#uv_title_bar')
|
||||
BarItems.uv_dialog_full.toElement('#uv_title_bar')
|
||||
BarItems.toggle_chat.toElement('#chat_title_bar')
|
||||
|
@ -72,7 +72,7 @@ function Dialog(settings) {
|
||||
}
|
||||
if (scope.form) {
|
||||
for (var form_id in scope.form) {
|
||||
var data = scope.form[form_id]
|
||||
let data = scope.form[form_id]
|
||||
if (data === '_') {
|
||||
jq_dialog.append('<hr />')
|
||||
|
||||
@ -94,10 +94,25 @@ function Dialog(settings) {
|
||||
}
|
||||
bar.append(list)
|
||||
}
|
||||
if (data.type == 'password') {
|
||||
bar.append(`<div class="password_toggle" @click="setting.hidden = !setting.hidden;">
|
||||
<i class="fas fa-eye-slash"></i>
|
||||
</div>`)
|
||||
let input = bar.find('input').attr('type', 'password')
|
||||
let hidden = true;
|
||||
let this_bar = bar;
|
||||
this_bar.find('.password_toggle').click(e => {
|
||||
hidden = !hidden;
|
||||
input.attr('type', hidden ? 'password' : 'text');
|
||||
this_bar.find('.password_toggle i')[0].className = hidden ? 'fas fa-eye-slash' : 'fas fa-eye';
|
||||
})
|
||||
}
|
||||
break;
|
||||
case 'textarea':
|
||||
bar.append(`<textarea class="focusable_input" style="height: ${data.height||150}px;" id="${form_id}"></textarea>`)
|
||||
break;
|
||||
|
||||
|
||||
case 'select':
|
||||
var el = $(`<div class="bar_select half"><select class="focusable_input" id="${form_id}"></select></div>`)
|
||||
var sel = el.find('select')
|
||||
@ -107,6 +122,8 @@ function Dialog(settings) {
|
||||
}
|
||||
bar.append(el)
|
||||
break;
|
||||
|
||||
|
||||
case 'radio':
|
||||
var el = $(`<div class="half form_part_radio" id="${form_id}"></div>`)
|
||||
for (var key in data.options) {
|
||||
@ -118,14 +135,31 @@ function Dialog(settings) {
|
||||
}
|
||||
bar.append(el)
|
||||
break;
|
||||
case 'text':
|
||||
|
||||
|
||||
case 'info':
|
||||
data.text = marked(tl(data.text))
|
||||
bar.append(`<p>${data.text}</p>`)
|
||||
bar.addClass('small_text')
|
||||
break;
|
||||
|
||||
|
||||
case 'number':
|
||||
bar.append(`<input class="dark_bordered half focusable_input" type="number" id="${form_id}" value="${data.value||0}" min="${data.min}" max="${data.max}" step="${data.step||1}">`)
|
||||
bar.append(`<input class="dark_bordered half focusable_input" type="number" id="${form_id}"
|
||||
value="${data.value||0}" min="${data.min}" max="${data.max}" step="${data.step||1}">`)
|
||||
break;
|
||||
|
||||
|
||||
case 'vector':
|
||||
let group = $(`<div class="dialog_vector_group half"></div>`)
|
||||
bar.append(group)
|
||||
for (var i = 0; i < (data.dimensions || 3); i++) {
|
||||
group.append(`<input class="dark_bordered focusable_input" type="number" id="${form_id}_${i}"
|
||||
value="${data.value ? data.value[i]: 0}" step="${data.step||1}" min="${data.min}" max="${data.max}">`)
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'color':
|
||||
if (!data.colorpicker) {
|
||||
data.colorpicker = new ColorPicker({
|
||||
@ -137,9 +171,13 @@ function Dialog(settings) {
|
||||
}
|
||||
bar.append(data.colorpicker.getNode())
|
||||
break;
|
||||
|
||||
|
||||
case 'checkbox':
|
||||
bar.append(`<input type="checkbox" class="focusable_input" id="${form_id}"${data.value ? ' checked' : ''}>`)
|
||||
break;
|
||||
|
||||
|
||||
case 'file':
|
||||
case 'folder':
|
||||
case 'save':
|
||||
@ -170,6 +208,7 @@ function Dialog(settings) {
|
||||
switch (data.type) {
|
||||
case 'file':
|
||||
Blockbench.import({
|
||||
resource_id: data.resource_id,
|
||||
extensions: data.extensions,
|
||||
type: data.filetype,
|
||||
startpath: data.value
|
||||
@ -185,6 +224,7 @@ function Dialog(settings) {
|
||||
break;
|
||||
case 'save':
|
||||
Blockbench.export({
|
||||
resource_id: data.resource_id,
|
||||
extensions: data.extensions,
|
||||
type: data.filetype,
|
||||
startpath: data.value,
|
||||
@ -194,7 +234,6 @@ function Dialog(settings) {
|
||||
}
|
||||
})
|
||||
|
||||
case 'folder':
|
||||
}
|
||||
if (data.readonly) {
|
||||
bar.find('input').attr('readonly', 'readonly').removeClass('focusable_input')
|
||||
@ -223,7 +262,7 @@ function Dialog(settings) {
|
||||
|
||||
} else if (this.singleButton) {
|
||||
|
||||
jq_dialog.append('<div class="dialog_bar">' +
|
||||
jq_dialog.append('<div class="dialog_bar" hidden>' +
|
||||
'<button type="button" class="cancel_btn confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>'+tl('dialog.close')+'</button>' +
|
||||
'</div>')
|
||||
|
||||
@ -247,7 +286,7 @@ function Dialog(settings) {
|
||||
default:
|
||||
result[form_id] = jq_dialog.find('input#'+form_id).val()
|
||||
break;
|
||||
case 'text':
|
||||
case 'info':
|
||||
break;
|
||||
case 'textarea':
|
||||
result[form_id] = jq_dialog.find('textarea#'+form_id).val()
|
||||
@ -261,6 +300,13 @@ function Dialog(settings) {
|
||||
case 'number':
|
||||
result[form_id] = Math.clamp(parseFloat(jq_dialog.find('input#'+form_id).val())||0, data.min, data.max)
|
||||
break;
|
||||
case 'vector':
|
||||
result[form_id] = [];
|
||||
for (var i = 0; i < (data.dimensions || 3); i++) {
|
||||
let num = Math.clamp(parseFloat(jq_dialog.find(`input#${form_id}_${i}`).val())||0, data.min, data.max)
|
||||
result[form_id].push(num)
|
||||
}
|
||||
break;
|
||||
case 'color':
|
||||
result[form_id] = data.colorpicker.get();
|
||||
break;
|
||||
|
@ -116,9 +116,10 @@ class ResizeLine {
|
||||
var jq = $('<div class="resizer '+(data.horizontal ? 'horizontal' : 'vertical')+'"></div>')
|
||||
this.node = jq.get(0)
|
||||
jq.draggable({
|
||||
axis: this.horizontal ? 'y' : 'y',
|
||||
axis: this.horizontal ? 'y' : 'x',
|
||||
containment: '#page_wrapper',
|
||||
revert: true,
|
||||
revertDuration: 0,
|
||||
start: function(e, u) {
|
||||
scope.before = data.get()
|
||||
},
|
||||
@ -126,7 +127,7 @@ class ResizeLine {
|
||||
if (scope.horizontal) {
|
||||
data.set(scope.before, u.position.top - u.originalPosition.top)
|
||||
} else {
|
||||
data.set(scope.before, (e.clientX - u.position.left))
|
||||
data.set(scope.before, (u.position.left - u.originalPosition.left))
|
||||
}
|
||||
updateInterface()
|
||||
},
|
||||
@ -189,13 +190,14 @@ var Interface = {
|
||||
},
|
||||
get: function() {return Interface.data.left_bar_width},
|
||||
set: function(o, diff) {
|
||||
Interface.data.left_bar_width = limitNumber(o + diff, 128, $(window).width()- 240 - Interface.data.right_bar_width)
|
||||
let calculated = limitNumber(o + diff, 128, $(window).width()- 120 - Interface.data.right_bar_width)
|
||||
Interface.data.left_bar_width = Math.snapToValues(calculated, [Interface.default_data.left_bar_width], 16);
|
||||
},
|
||||
position: function(line) {
|
||||
line.setPosition({
|
||||
top: 32,
|
||||
top: 26,
|
||||
bottom: 0,
|
||||
left: Interface.data.left_bar_width-3
|
||||
left: Interface.data.left_bar_width+2
|
||||
})
|
||||
}
|
||||
}),
|
||||
@ -210,13 +212,14 @@ var Interface = {
|
||||
},
|
||||
get: function() {return Interface.data.right_bar_width},
|
||||
set: function(o, diff) {
|
||||
Interface.data.right_bar_width = limitNumber(o - diff, 128, $(window).width()- 240 - Interface.data.left_bar_width)
|
||||
let calculated = limitNumber(o - diff, 128, $(window).width()- 120 - Interface.data.left_bar_width);
|
||||
Interface.data.right_bar_width = Math.snapToValues(calculated, [Interface.default_data.right_bar_width], 12);
|
||||
},
|
||||
position: function(line) {
|
||||
line.setPosition({
|
||||
top: 32,
|
||||
top: 56,
|
||||
bottom: 0,
|
||||
right: Interface.data.right_bar_width-3
|
||||
right: Interface.data.right_bar_width-2
|
||||
})
|
||||
}
|
||||
}),
|
||||
@ -307,7 +310,6 @@ function setupInterface() {
|
||||
$('.edit_session_active').hide()
|
||||
|
||||
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
|
||||
$('#UVEditor_main_uv').toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
|
||||
|
||||
$('.sidebar').droppable({
|
||||
accept: 'h3',
|
||||
@ -846,7 +848,7 @@ var documentReady = new Promise((resolve, reject) => {
|
||||
|
||||
|
||||
//Electron
|
||||
if (isApp && !compareVersions(process.versions.electron, '4.0.0')) {
|
||||
if (isApp && !compareVersions(process.versions.electron, '6.0.0')) {
|
||||
addStartScreenSection({
|
||||
graphic: {type: 'icon', icon: 'fas.fa-atom'},
|
||||
text: [
|
||||
@ -869,8 +871,21 @@ var documentReady = new Promise((resolve, reject) => {
|
||||
last: true
|
||||
})
|
||||
}
|
||||
//Twitter
|
||||
if (Blockbench.startup_count < 20 && Blockbench.startup_count % 5 === 4) {
|
||||
addStartScreenSection({
|
||||
color: '#1da1f2',
|
||||
text_color: '#ffffff',
|
||||
graphic: {type: 'icon', icon: 'fab.fa-twitter'},
|
||||
text: [
|
||||
{type: 'h1', text: 'Blockbench on Twitter'},
|
||||
{text: 'Follow Blockbench on Twitter for the latest news as well as cool models from the community! [twitter.com/blockbench](https://twitter.com/blockbench/)'}
|
||||
],
|
||||
last: true
|
||||
})
|
||||
}
|
||||
//Donation reminder
|
||||
if (Blockbench.startup_count % 12 === 11) {
|
||||
if (Blockbench.startup_count % 20 === 19) {
|
||||
addStartScreenSection({
|
||||
graphic: {type: 'icon', icon: 'fas.fa-heart'},
|
||||
text: [
|
||||
|
@ -81,7 +81,7 @@ class Menu {
|
||||
} else if (index >= MenuBar.keys.length) {
|
||||
index = 0;
|
||||
}
|
||||
MenuBar.menues[MenuBar.keys[index]].open()
|
||||
MenuBar.menus[MenuBar.keys[index]].open()
|
||||
}
|
||||
} else {
|
||||
obj.find('> li:first-child').addClass('focused')
|
||||
@ -113,6 +113,30 @@ class Menu {
|
||||
|
||||
ctxmenu.children().detach()
|
||||
|
||||
function createChildList(object, node) {
|
||||
|
||||
if (typeof object.children == 'function') {
|
||||
var list = object.children(context)
|
||||
} else {
|
||||
var list = object.children
|
||||
}
|
||||
if (list.length) {
|
||||
node.addClass('parent')
|
||||
.find('ul.contextMenu.sub').detach()
|
||||
var childlist = $('<ul class="contextMenu sub"></ul>')
|
||||
node.append(childlist)
|
||||
list.forEach(function(s2, i) {
|
||||
getEntry(s2, childlist)
|
||||
})
|
||||
var last = childlist.children().last()
|
||||
if (last.length && last.hasClass('menu_separator')) {
|
||||
last.remove()
|
||||
}
|
||||
return childlist.children().length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getEntry(s, parent) {
|
||||
|
||||
var entry;
|
||||
@ -129,15 +153,20 @@ class Menu {
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
entry = s.menu_node
|
||||
entry = $(s.menu_node)
|
||||
if (BARS.condition(s.condition)) {
|
||||
|
||||
if (!entry.hasMenuEvents) {
|
||||
entry.hasMenuEvents = true
|
||||
entry.addEventListener('click', (e) => {s.trigger(e)})
|
||||
$(entry).on('mouseenter mousedown', function(e) {
|
||||
scope.hover(this, e)
|
||||
})
|
||||
entry.off('click')
|
||||
entry.off('mouseenter mousedown')
|
||||
entry.on('mouseenter mousedown', function(e) {
|
||||
scope.hover(this, e)
|
||||
})
|
||||
//Submenu
|
||||
if (typeof s.children == 'function' || typeof s.children == 'object') {
|
||||
createChildList(s, entry)
|
||||
} else {
|
||||
entry.on('click', (e) => {s.trigger(e)})
|
||||
//entry[0].addEventListener('click', )
|
||||
}
|
||||
parent.append(entry)
|
||||
}
|
||||
@ -161,24 +190,7 @@ class Menu {
|
||||
}
|
||||
//Submenu
|
||||
if (typeof s.children == 'function' || typeof s.children == 'object') {
|
||||
if (typeof s.children == 'function') {
|
||||
var list = s.children(context)
|
||||
} else {
|
||||
var list = s.children
|
||||
}
|
||||
if (list.length) {
|
||||
entry.addClass('parent')
|
||||
var childlist = $('<ul class="contextMenu sub"></ul>')
|
||||
entry.append(childlist)
|
||||
list.forEach(function(s2, i) {
|
||||
getEntry(s2, childlist)
|
||||
})
|
||||
var last = childlist.children().last()
|
||||
child_count = childlist.children().length;
|
||||
if (last.length && last.hasClass('menu_separator')) {
|
||||
last.remove()
|
||||
}
|
||||
}
|
||||
child_count = createChildList(s, entry)
|
||||
}
|
||||
if (child_count !== 0 || typeof s.click === 'function') {
|
||||
parent.append(entry)
|
||||
@ -204,6 +216,11 @@ class Menu {
|
||||
if (position && position.clientX !== undefined) {
|
||||
var offset_left = position.clientX
|
||||
var offset_top = position.clientY+1
|
||||
|
||||
} else if (position == document.body) {
|
||||
var offset_left = (document.body.clientWidth-el_width)/2
|
||||
var offset_top = (document.body.clientHeight-el_height)/2
|
||||
|
||||
} else {
|
||||
if (!position && scope.type === 'bar_menu') {
|
||||
position = scope.label
|
||||
@ -338,7 +355,7 @@ class BarMenu extends Menu {
|
||||
constructor(id, structure, condition) {
|
||||
super()
|
||||
var scope = this;
|
||||
MenuBar.menues[id] = this
|
||||
MenuBar.menus[id] = this
|
||||
this.type = 'bar_menu'
|
||||
this.id = id
|
||||
this.children = [];
|
||||
@ -367,9 +384,10 @@ class BarMenu extends Menu {
|
||||
}
|
||||
}
|
||||
const MenuBar = {
|
||||
menues: {},
|
||||
menus: {},
|
||||
open: undefined,
|
||||
setup() {
|
||||
MenuBar.menues = MenuBar.menus;
|
||||
new BarMenu('file', [
|
||||
'project_window',
|
||||
'_',
|
||||
@ -470,6 +488,7 @@ const MenuBar = {
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'add_locator',
|
||||
'unlock_everything',
|
||||
'duplicate',
|
||||
'delete',
|
||||
'_',
|
||||
@ -500,6 +519,7 @@ const MenuBar = {
|
||||
]},
|
||||
{name: 'menu.transform.properties', id: 'properties', icon: 'navigate_next', children: [
|
||||
'toggle_visibility',
|
||||
'toggle_locked',
|
||||
'toggle_export',
|
||||
'toggle_autouv',
|
||||
'toggle_shade',
|
||||
@ -514,66 +534,7 @@ const MenuBar = {
|
||||
'paste',
|
||||
'_',
|
||||
'add_display_preset',
|
||||
{name: 'menu.display.preset', icon: 'fa-list', children: function() {
|
||||
var presets = []
|
||||
display_presets.forEach(function(p) {
|
||||
var icon = 'label'
|
||||
if (p.fixed) {
|
||||
switch(p.id) {
|
||||
case 'item': icon = 'filter_vintage'; break;
|
||||
case 'block': icon = 'fa-cube'; break;
|
||||
case 'handheld': icon = 'build'; break;
|
||||
case 'rod': icon = 'remove'; break;
|
||||
}
|
||||
}
|
||||
presets.push({
|
||||
icon: icon,
|
||||
name: p.id ? tl('display.preset.'+p.id) : p.name,
|
||||
click: function() {
|
||||
DisplayMode.applyPreset(p)
|
||||
}
|
||||
})
|
||||
})
|
||||
return presets;
|
||||
}},
|
||||
{name: 'menu.display.preset_all', icon: 'fa-list', children: function() {
|
||||
var presets = []
|
||||
display_presets.forEach(function(p) {
|
||||
var icon = 'label'
|
||||
if (p.fixed) {
|
||||
switch(p.id) {
|
||||
case 'item': icon = 'filter_vintage'; break;
|
||||
case 'block': icon = 'fa-cube'; break;
|
||||
case 'handheld': icon = 'build'; break;
|
||||
case 'rod': icon = 'remove'; break;
|
||||
}
|
||||
}
|
||||
presets.push({
|
||||
icon: icon,
|
||||
name: p.id ? tl('display.preset.'+p.id) : p.name,
|
||||
click: function() {
|
||||
DisplayMode.applyPreset(p, true)
|
||||
}
|
||||
})
|
||||
})
|
||||
return presets;
|
||||
}},
|
||||
{name: 'menu.display.remove_preset', icon: 'fa-list', children: function() {
|
||||
var presets = []
|
||||
display_presets.forEach(function(p) {
|
||||
if (!p.fixed) {
|
||||
presets.push({
|
||||
icon: 'label',
|
||||
name: p.name,
|
||||
click: function() {
|
||||
display_presets.splice(display_presets.indexOf(p), 1);
|
||||
localStorage.setItem('display_presets', JSON.stringify(display_presets))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return presets;
|
||||
}}
|
||||
'apply_display_preset'
|
||||
], () => Modes.display)
|
||||
|
||||
new BarMenu('filter', [
|
||||
@ -650,7 +611,9 @@ const MenuBar = {
|
||||
{name: 'menu.help.developer.reset_storage', icon: 'fas.fa-hdd', click: () => {
|
||||
if (confirm(tl('menu.help.developer.reset_storage.confirm'))) {
|
||||
localStorage.clear()
|
||||
Blockbench.addFlag('no_localstorage_saving')
|
||||
console.log('Cleared Local Storage')
|
||||
window.location.reload(true)
|
||||
}
|
||||
}},
|
||||
{name: 'menu.help.developer.cache_reload', icon: 'cached', condition: !isApp, click: () => {
|
||||
@ -672,10 +635,10 @@ const MenuBar = {
|
||||
var bar = $('#menu_bar')
|
||||
bar.children().detach()
|
||||
this.keys = []
|
||||
for (var menu in MenuBar.menues) {
|
||||
if (MenuBar.menues.hasOwnProperty(menu)) {
|
||||
if (MenuBar.menues[menu].conditionMet()) {
|
||||
bar.append(MenuBar.menues[menu].label)
|
||||
for (var menu in MenuBar.menus) {
|
||||
if (MenuBar.menus.hasOwnProperty(menu)) {
|
||||
if (MenuBar.menus[menu].conditionMet()) {
|
||||
bar.append(MenuBar.menus[menu].label)
|
||||
this.keys.push(menu)
|
||||
}
|
||||
}
|
||||
@ -686,7 +649,7 @@ const MenuBar = {
|
||||
addAction(action, path) {
|
||||
if (path) {
|
||||
path = path.split('.')
|
||||
var menu = MenuBar.menues[path.splice(0, 1)[0]]
|
||||
var menu = MenuBar.menus[path.splice(0, 1)[0]]
|
||||
if (menu) {
|
||||
menu.addAction(action, path.join('.'))
|
||||
}
|
||||
@ -695,7 +658,7 @@ const MenuBar = {
|
||||
removeAction(path) {
|
||||
if (path) {
|
||||
path = path.split('.')
|
||||
var menu = MenuBar.menues[path.splice(0, 1)[0]]
|
||||
var menu = MenuBar.menus[path.splice(0, 1)[0]]
|
||||
if (menu) {
|
||||
menu.removeAction(path.join('.'))
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ class Setting {
|
||||
case 'toggle': this.value = true; break;
|
||||
case 'number': this.value = 0; break;
|
||||
case 'text': this.value = ''; break;
|
||||
case 'password': this.value = ''; break;
|
||||
case 'select': this.value; break;
|
||||
case 'click': this.value = false; break;
|
||||
}
|
||||
@ -38,6 +39,9 @@ class Setting {
|
||||
if (this.type == 'select') {
|
||||
this.options = data.options;
|
||||
}
|
||||
if (this.type == 'password') {
|
||||
this.hidden = true;
|
||||
}
|
||||
if (typeof data.onChange == 'function') {
|
||||
this.onChange = data.onChange
|
||||
}
|
||||
@ -88,7 +92,7 @@ const Settings = {
|
||||
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
|
||||
}});
|
||||
new Setting('uv_checkerboard', {category: 'interface', value: false, onChange() {
|
||||
$('#UVEditor_main_uv').toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
|
||||
$('.UVEditor').toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
|
||||
}});
|
||||
|
||||
//Preview
|
||||
@ -111,12 +115,13 @@ const Settings = {
|
||||
new Setting('deactivate_size_limit',{category: 'edit', value: false});
|
||||
|
||||
//Grid
|
||||
new Setting('base_grid', {category: 'grid', value: true,});
|
||||
new Setting('large_grid', {category: 'grid', value: false});
|
||||
new Setting('full_grid', {category: 'grid', value: false});
|
||||
new Setting('large_box', {category: 'grid', value: false});
|
||||
new Setting('display_grid', {category: 'grid', value: false});
|
||||
new Setting('painting_grid',{category: 'grid', value: true, onChange() {
|
||||
new Setting('base_grid', {category: 'grid', value: true,});
|
||||
new Setting('large_grid', {category: 'grid', value: false});
|
||||
new Setting('full_grid', {category: 'grid', value: false});
|
||||
new Setting('large_box', {category: 'grid', value: false});
|
||||
new Setting('large_grid_size', {category: 'grid', value: 3, type: 'number'});
|
||||
new Setting('display_grid', {category: 'grid', value: false});
|
||||
new Setting('painting_grid', {category: 'grid', value: true, onChange() {
|
||||
Cube.all.forEach(cube => {
|
||||
Canvas.buildGridBox(cube)
|
||||
})
|
||||
@ -130,7 +135,8 @@ const Settings = {
|
||||
new Setting('animation_snap',{category: 'snapping', value: 25, type: 'number'});
|
||||
|
||||
//Paint
|
||||
new Setting('paint_side_restrict', {category: 'paint', value: true});
|
||||
new Setting('paint_side_restrict', {category: 'paint', value: true});
|
||||
//new Setting('layered_textures', {category: 'paint', value: false});
|
||||
new Setting('brush_opacity_modifier', {category: 'paint', value: 'pressure', type: 'select', options: {
|
||||
'pressure': tl('settings.brush_modifier.pressure'),
|
||||
'tilt': tl('settings.brush_modifier.tilt'),
|
||||
@ -149,18 +155,13 @@ const Settings = {
|
||||
new Setting('default_path', {category: 'defaults', value: false, type: 'click', condition: isApp, icon: 'burst_mode', click: function() { openDefaultTexturePath() }});
|
||||
|
||||
//Dialogs
|
||||
new Setting('dialog_unsaved_textures', {category: 'dialogs', value: true});
|
||||
new Setting('dialog_larger_cubes', {category: 'dialogs', value: true});
|
||||
new Setting('dialog_rotation_limit', {category: 'dialogs', value: true});
|
||||
|
||||
//Export
|
||||
new Setting('minifiedout', {category: 'export', value: false});
|
||||
new Setting('export_groups', {category: 'export', value: true});
|
||||
new Setting('class_export_version', {category: 'export', value: '1.12', type: 'select', options: {
|
||||
'1.12': '1.12',
|
||||
'1.14': '1.14',
|
||||
}});
|
||||
new Setting('sketchfab_token', {category: 'export', value: '', type: 'text'});
|
||||
new Setting('sketchfab_token', {category: 'export', value: '', type: 'password'});
|
||||
new Setting('credit', {category: 'export', value: 'Made with Blockbench', type: 'text'});
|
||||
},
|
||||
addCategory(id, data) {
|
||||
@ -181,18 +182,20 @@ const Settings = {
|
||||
setSettingsTab('setting')
|
||||
},
|
||||
saveLocalStorages() {
|
||||
localStorage.setItem('canvas_scenes', JSON.stringify(canvas_scenes))
|
||||
var settings_copy = {}
|
||||
for (var key in settings) {
|
||||
settings_copy[key] = {value: settings[key].value}
|
||||
}
|
||||
localStorage.setItem('settings', JSON.stringify(settings_copy) )
|
||||
|
||||
localStorage.setItem('canvas_scenes', JSON.stringify(canvas_scenes))
|
||||
localStorage.setItem('colors', JSON.stringify({
|
||||
palette: ColorPanel.vue._data.palette,
|
||||
history: ColorPanel.vue._data.history,
|
||||
}))
|
||||
},
|
||||
save() {
|
||||
Settings.saveLocalStorages()
|
||||
function hasSettingChanged(id) {
|
||||
return (settings[id].value !== Settings.old[id])
|
||||
}
|
||||
@ -205,7 +208,7 @@ const Settings = {
|
||||
action.toggleLinkedSetting(false)
|
||||
}
|
||||
}
|
||||
if (hasSettingChanged('base_grid') || hasSettingChanged('large_grid') || hasSettingChanged('full_grid')
|
||||
if (hasSettingChanged('base_grid') || hasSettingChanged('large_grid') || hasSettingChanged('full_grid') || hasSettingChanged('large_grid_size')
|
||||
||hasSettingChanged('large_box') || hasSettingChanged('display_grid') || hasSettingChanged('edit_size')) {
|
||||
buildGrid()
|
||||
}
|
||||
@ -264,9 +267,14 @@ const Settings = {
|
||||
},
|
||||
old: {}
|
||||
}
|
||||
$(window).on('unload', Settings.saveLocalStorages)
|
||||
Settings.setup()
|
||||
|
||||
window.onunload = function() {
|
||||
if (!Blockbench.hasFlag('no_localstorage_saving')) {
|
||||
Settings.saveLocalStorages()
|
||||
}
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
Settings.structure.search_results = {
|
||||
name: tl('dialog.settings.search_results'),
|
||||
|
@ -15,6 +15,7 @@ const CustomTheme = {
|
||||
button: '#3a3f4b',
|
||||
bright_ui: '#f4f3ff',
|
||||
accent: '#3e90ff',
|
||||
frame: '#181a1f',
|
||||
text: '#cacad4',
|
||||
light: '#f4f3ff',
|
||||
accent_text: '#000006',
|
||||
@ -61,7 +62,7 @@ const CustomTheme = {
|
||||
var hex = CustomTheme.data.colors[key];
|
||||
document.body.style.setProperty('--color-'+key, hex);
|
||||
}
|
||||
$('meta[name=theme-color]').attr('content', CustomTheme.data.colors.border);
|
||||
$('meta[name=theme-color]').attr('content', CustomTheme.data.colors.frame);
|
||||
|
||||
var c_outline = parseInt('0x'+CustomTheme.data.colors.accent.replace('#', ''))
|
||||
if (c_outline !== gizmo_colors.outline.getHex()) {
|
||||
@ -197,6 +198,7 @@ BARS.defineActions(function() {
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'theme',
|
||||
extensions: ['bbstyle', 'bbtheme'],
|
||||
type: 'Blockbench Theme'
|
||||
}, function(files) {
|
||||
@ -209,6 +211,7 @@ BARS.defineActions(function() {
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
Blockbench.export({
|
||||
resource_id: 'theme',
|
||||
type: 'Blockbench Theme',
|
||||
extensions: ['bbtheme'],
|
||||
content: autoStringify(CustomTheme.data)
|
||||
|
@ -38,6 +38,12 @@ var codec = new Codec('project', {
|
||||
model.ambientocclusion = Project.ambientocclusion
|
||||
model.front_gui_light = Project.front_gui_light;
|
||||
}
|
||||
if (Format.id == 'bedrock' || Format.id == 'bedrock_legacy') {
|
||||
model.visible_box = Project.visible_box
|
||||
}
|
||||
if (Format.id == 'modded_entity') {
|
||||
model.modded_entity_version = Project.modded_entity_version
|
||||
}
|
||||
model.resolution = {
|
||||
width: Project.texture_width || 16,
|
||||
height: Project.texture_height || 16,
|
||||
@ -156,6 +162,12 @@ var codec = new Codec('project', {
|
||||
if (model.front_gui_light !== undefined) {
|
||||
Project.front_gui_light = !!model.front_gui_light;
|
||||
}
|
||||
if (model.visible_box) {
|
||||
Project.visible_box.splice(0, Infinity, ...model.visible_box)
|
||||
}
|
||||
if (model.modded_entity_version) {
|
||||
Project.modded_entity_version = model.modded_entity_version
|
||||
}
|
||||
if (model.resolution !== undefined) {
|
||||
Project.texture_width = model.resolution.width;
|
||||
Project.texture_height = model.resolution.height;
|
||||
@ -179,12 +191,12 @@ var codec = new Codec('project', {
|
||||
|
||||
var copy = NonGroup.fromSave(element, true)
|
||||
for (var face in copy.faces) {
|
||||
if (!Format.single_texture) {
|
||||
if (!Format.single_texture && element.faces) {
|
||||
var texture = element.faces[face].texture !== null && textures[element.faces[face].texture]
|
||||
if (texture) {
|
||||
copy.faces[face].texture = texture.uuid
|
||||
}
|
||||
} else if (textures[0] && copy.faces[face].texture !== null) {
|
||||
} else if (textures[0] && copy.faces && copy.faces[face].texture !== null) {
|
||||
copy.faces[face].texture = textures[0].uuid
|
||||
}
|
||||
}
|
||||
|
@ -207,6 +207,46 @@ window.BedrockEntityManager = {
|
||||
}
|
||||
}
|
||||
|
||||
function calculateVisibleBox() {
|
||||
var visible_box = new THREE.Box3()
|
||||
Cube.all.forEach(cube => {
|
||||
if (cube.export && cube.mesh) {
|
||||
visible_box.expandByObject(cube.mesh);
|
||||
}
|
||||
})
|
||||
|
||||
var offset = new THREE.Vector3(8,8,8);
|
||||
visible_box.max.add(offset);
|
||||
visible_box.min.add(offset);
|
||||
|
||||
// Width
|
||||
var radius = Math.max(
|
||||
visible_box.max.x,
|
||||
visible_box.max.z,
|
||||
-visible_box.min.x,
|
||||
-visible_box.min.z
|
||||
)
|
||||
if (Math.abs(radius) === Infinity) {
|
||||
radius = 0
|
||||
}
|
||||
let width = Math.ceil((radius*2) / 16)
|
||||
width = Math.max(width, Project.visible_box[0]);
|
||||
Project.visible_box[0] = width;
|
||||
|
||||
// Height
|
||||
let height = Math.ceil(Math.abs(visible_box.max.y - visible_box.min.y) / 16)
|
||||
if (height === Infinity) height = 0;
|
||||
height = Math.max(height, Project.visible_box[1]);
|
||||
|
||||
// Y
|
||||
let y = height/2 + Math.floor(visible_box.min.y / 16)
|
||||
if (y === Infinity) y = 0;
|
||||
y = Math.min(y, Project.visible_box[2]);
|
||||
|
||||
Project.visible_box.replace([width, height, y])
|
||||
return Project.visible_box;
|
||||
}
|
||||
|
||||
(function() {
|
||||
|
||||
function parseGeometry(data) {
|
||||
@ -221,16 +261,25 @@ function parseGeometry(data) {
|
||||
}
|
||||
}
|
||||
codec.dispatchEvent('parse', {model: data.object});
|
||||
let {description} = data.object;
|
||||
|
||||
Project.geometry_name = (data.object.description.identifier && data.object.description.identifier.replace(/^geometry\./, '')) || '';
|
||||
Project.geometry_name = (description.identifier && description.identifier.replace(/^geometry\./, '')) || '';
|
||||
Project.texture_width = 16;
|
||||
Project.texture_height = 16;
|
||||
|
||||
if (data.object.description.texture_width !== undefined) {
|
||||
Project.texture_width = data.object.description.texture_width;
|
||||
if (typeof description.visible_bounds_width == 'number' && typeof description.visible_bounds_height == 'number') {
|
||||
Project.visible_box[0] = Math.max(Project.visible_box[0], description.visible_bounds_width);
|
||||
Project.visible_box[1] = Math.max(Project.visible_box[1], description.visible_bounds_height);
|
||||
if (description.visible_bounds_offset && typeof description.visible_bounds_offset[1] == 'number') {
|
||||
Project.visible_box[2] = Math.min(Project.visible_box[2], description.visible_bounds_offset[1]);
|
||||
}
|
||||
}
|
||||
if (data.object.description.texture_height !== undefined) {
|
||||
Project.texture_height = data.object.description.texture_height;
|
||||
|
||||
if (description.texture_width !== undefined) {
|
||||
Project.texture_width = description.texture_width;
|
||||
}
|
||||
if (description.texture_height !== undefined) {
|
||||
Project.texture_height = description.texture_height;
|
||||
}
|
||||
|
||||
var bones = {}
|
||||
@ -367,6 +416,7 @@ function parseGeometry(data) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
var codec = new Codec('bedrock', {
|
||||
name: 'Bedrock Model',
|
||||
extension: 'json',
|
||||
@ -385,7 +435,6 @@ var codec = new Codec('bedrock', {
|
||||
texture_height: Project.texture_height || 16,
|
||||
}
|
||||
var bones = []
|
||||
var visible_box = new THREE.Box3()
|
||||
|
||||
var groups = getAllGroups();
|
||||
var loose_cubes = [];
|
||||
@ -485,11 +534,6 @@ var codec = new Codec('bedrock', {
|
||||
}
|
||||
}
|
||||
}
|
||||
//Visible Bounds
|
||||
var mesh = obj.mesh
|
||||
if (mesh) {
|
||||
visible_box.expandByObject(mesh)
|
||||
}
|
||||
cubes.push(template)
|
||||
|
||||
} else if (obj instanceof Locator) {
|
||||
@ -510,26 +554,11 @@ var codec = new Codec('bedrock', {
|
||||
})
|
||||
|
||||
if (bones.length && options.visible_box !== false) {
|
||||
var offset = new THREE.Vector3(8,8,8)
|
||||
visible_box.max.add(offset)
|
||||
visible_box.min.add(offset)
|
||||
//Width
|
||||
var radius = Math.max(
|
||||
visible_box.max.x,
|
||||
visible_box.max.z,
|
||||
-visible_box.min.x,
|
||||
-visible_box.min.z
|
||||
) * 0.9
|
||||
if (Math.abs(radius) === Infinity) {
|
||||
radius = 0
|
||||
}
|
||||
entitymodel.description.visible_bounds_width = Math.ceil((radius*2) / 16)
|
||||
//Height
|
||||
entitymodel.description.visible_bounds_height = Math.ceil(((visible_box.max.y - visible_box.min.y) * 0.9) / 16)
|
||||
if (Math.abs(entitymodel.description.visible_bounds_height) === Infinity) {
|
||||
entitymodel.description.visible_bounds_height = 0;
|
||||
}
|
||||
entitymodel.description.visible_bounds_offset = [0, entitymodel.description.visible_bounds_height/2 , 0]
|
||||
|
||||
let visible_box = calculateVisibleBox();
|
||||
entitymodel.description.visible_bounds_width = visible_box[0];
|
||||
entitymodel.description.visible_bounds_height = visible_box[1];
|
||||
entitymodel.description.visible_bounds_offset = [0, visible_box[2] , 0]
|
||||
}
|
||||
if (bones.length) {
|
||||
entitymodel.bones = bones
|
||||
@ -777,6 +806,7 @@ var format = new ModelFormat({
|
||||
|
||||
}
|
||||
})
|
||||
//Object.defineProperty(format, 'single_texture', {get: _ => !settings.layered_textures.value})
|
||||
codec.format = format;
|
||||
|
||||
BARS.defineActions(function() {
|
||||
|
@ -16,6 +16,14 @@ function parseGeometry(data) {
|
||||
Project.texture_width = data.object.texturewidth || 64;
|
||||
Project.texture_height = data.object.textureheight || 64;
|
||||
|
||||
if (typeof data.object.visible_bounds_width == 'number' && typeof data.object.visible_bounds_height == 'number') {
|
||||
Project.visible_box[0] = Math.max(Project.visible_box[0], data.object.visible_bounds_width);
|
||||
Project.visible_box[1] = Math.max(Project.visible_box[1], data.object.visible_bounds_height);
|
||||
if (data.object.visible_bounds_offset && typeof data.object.visible_bounds_offset[1] == 'number') {
|
||||
Project.visible_box[2] = Math.min(Project.visible_box[2], data.object.visible_bounds_offset[1]);
|
||||
}
|
||||
}
|
||||
|
||||
var bones = {}
|
||||
|
||||
if (data.object.bones) {
|
||||
@ -203,26 +211,11 @@ var codec = new Codec('bedrock_old', {
|
||||
})
|
||||
|
||||
if (bones.length && options.visible_box !== false) {
|
||||
var offset = new THREE.Vector3(8,8,8)
|
||||
visible_box.max.add(offset)
|
||||
visible_box.min.add(offset)
|
||||
//Width
|
||||
var radius = Math.max(
|
||||
visible_box.max.x,
|
||||
visible_box.max.z,
|
||||
-visible_box.min.x,
|
||||
-visible_box.min.z
|
||||
) * 0.9
|
||||
if (Math.abs(radius) === Infinity) {
|
||||
radius = 0
|
||||
}
|
||||
entitymodel.visible_bounds_width = Math.ceil((radius*2) / 16)
|
||||
//Height
|
||||
entitymodel.visible_bounds_height = Math.ceil(((visible_box.max.y - visible_box.min.y) * 0.9) / 16)
|
||||
if (Math.abs(entitymodel.visible_bounds_height) === Infinity) {
|
||||
entitymodel.visible_bounds_height = 0;
|
||||
}
|
||||
entitymodel.visible_bounds_offset = [0, entitymodel.visible_bounds_height/2 , 0]
|
||||
|
||||
let visible_box = calculateVisibleBox();
|
||||
entitymodel.visible_bounds_width = visible_box[0];
|
||||
entitymodel.visible_bounds_height = visible_box[1];
|
||||
entitymodel.visible_bounds_offset = [0, visible_box[2] , 0]
|
||||
}
|
||||
if (bones.length) {
|
||||
entitymodel.bones = bones
|
||||
@ -258,18 +251,12 @@ var codec = new Codec('bedrock_old', {
|
||||
pe_list._data.search_text = ''
|
||||
}
|
||||
|
||||
function rotateOriginCoord(pivot, y, z) {
|
||||
return [
|
||||
pivot[1] - pivot[2] + z,
|
||||
pivot[2] - y + pivot[1]
|
||||
]
|
||||
}
|
||||
function create_thumbnail(model_entry, isize) {
|
||||
var included_bones = []
|
||||
model_entry.object.bones.forEach(function(b) {
|
||||
included_bones.push(b.name)
|
||||
})
|
||||
var thumbnail = new Jimp(48, 48, 0x00000000, function(err, image) {
|
||||
new Jimp(48, 48, 0x00000000, function(err, image) {
|
||||
model_entry.object.bones.forEach(function(b) {
|
||||
//var rotate_bone = false;
|
||||
//if (b.name === 'body' &&
|
||||
@ -400,6 +387,7 @@ var codec = new Codec('bedrock_old', {
|
||||
export() {
|
||||
var scope = this;
|
||||
Blockbench.export({
|
||||
resource_id: 'model',
|
||||
type: this.name,
|
||||
extensions: [this.extension],
|
||||
name: this.fileName(),
|
||||
@ -492,6 +480,7 @@ var format = new ModelFormat({
|
||||
|
||||
}
|
||||
})
|
||||
//Object.defineProperty(format, 'single_texture', {get: _ => !settings.layered_textures.value})
|
||||
codec.format = format;
|
||||
|
||||
BARS.defineActions(function() {
|
||||
|
152
js/io/gltf.js
152
js/io/gltf.js
@ -1,6 +1,99 @@
|
||||
(function() {
|
||||
|
||||
function buildAnimationTracks() {
|
||||
let tracks = [];
|
||||
Animator.animations.forEach(animation => {
|
||||
|
||||
let tracks = [];
|
||||
for (var uuid in animation.animators) {
|
||||
let animator = animation.animators[uuid];
|
||||
|
||||
if (animator instanceof BoneAnimator && animator.getGroup()) {
|
||||
for (var channel of animator.channels) {
|
||||
if (animator[channel] && animator[channel].length) {
|
||||
let times = [];
|
||||
let values = [];
|
||||
let keyframes = animator[channel].slice();
|
||||
|
||||
// Sampling calculated (molang) values
|
||||
let contains_script
|
||||
for (var kf of keyframes) {
|
||||
if (isNaN(kf.x) || isNaN(kf.y) || isNaN(kf.z)) {
|
||||
contains_script = true; break;
|
||||
}
|
||||
}
|
||||
if (contains_script) {
|
||||
var last_values;
|
||||
for (var time = 0; time < animation.length; time += 1/24) {
|
||||
Timeline.time = time;
|
||||
let values = animator.interpolate(channel, false)
|
||||
if (!values.equals(last_values) && !keyframes.find(kf => Math.epsilon(kf.time, time, 1/24))) {
|
||||
let new_keyframe = new Keyframe({
|
||||
time, channel,
|
||||
x: values[0], y: values[1], z: values[2],
|
||||
})
|
||||
new_keyframe.animator = animator;
|
||||
keyframes.push(new_keyframe)
|
||||
}
|
||||
last_values = values;
|
||||
}
|
||||
}
|
||||
|
||||
keyframes.sort((a, b) => a.time - b.time)
|
||||
|
||||
// Sampling rotation steps that exceed 180 degrees
|
||||
if (channel === 'rotation' && !contains_script) {
|
||||
let original_keyframes = keyframes.slice();
|
||||
original_keyframes.forEach((kf, i) => {
|
||||
let next = original_keyframes[i+1]
|
||||
if (!next) return;
|
||||
|
||||
let k1 = kf.getArray();
|
||||
let k2 = next.getArray();
|
||||
let max_diff = Math.max(Math.abs(k1[0] - k2[0]), Math.abs(k1[1] - k2[1]), Math.abs(k1[2] - k2[2]));
|
||||
let steps = Math.floor(max_diff / 180 + 1);
|
||||
|
||||
for (var step = 1; step < steps; step++) {
|
||||
|
||||
Timeline.time = kf.time + (next.time - kf.time) * (step/steps);
|
||||
let values = animator.interpolate(channel, false)
|
||||
let new_keyframe = new Keyframe({
|
||||
time: Timeline.time, channel,
|
||||
x: values[0], y: values[1], z: values[2],
|
||||
})
|
||||
new_keyframe.animator = animator;
|
||||
keyframes.splice(keyframes.indexOf(kf) + step, 0, new_keyframe);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
keyframes.forEach(kf => {
|
||||
times.push(kf.time);
|
||||
Timeline.time = kf.time;
|
||||
kf.getFixed().toArray(values, values.length);
|
||||
})
|
||||
let trackType = THREE.VectorKeyframeTrack;
|
||||
if (channel === 'rotation') {
|
||||
trackType = THREE.QuaternionKeyframeTrack;
|
||||
channel = 'quaternion';
|
||||
}
|
||||
let track = new trackType(animator.group.mesh.uuid+'.'+channel, times, values, THREE.InterpolateLinear);
|
||||
tracks.push(track);
|
||||
}
|
||||
}
|
||||
} else if (animator instanceof BoneAnimator) {
|
||||
console.log(`Skip export of track ${uuid.substr(0, 7)}... - No connected bone`)
|
||||
}
|
||||
}
|
||||
if (tracks.length) {
|
||||
let clip = new THREE.AnimationClip(animation.name, animation.length, tracks)
|
||||
tracks.push(clip);
|
||||
} else {
|
||||
console.log(`Skip export of animation ${animation.name} - No tracks generated`)
|
||||
}
|
||||
})
|
||||
return tracks;
|
||||
}
|
||||
|
||||
var codec = new Codec('gltf', {
|
||||
name: 'GLTF Model',
|
||||
@ -21,45 +114,9 @@ var codec = new Codec('gltf', {
|
||||
Animator.showDefaultPose();
|
||||
}
|
||||
if (options.animations !== false) {
|
||||
Animator.animations.forEach(animation => {
|
||||
|
||||
let tracks = [];
|
||||
for (var uuid in animation.animators) {
|
||||
let animator = animation.animators[uuid];
|
||||
|
||||
if (animator instanceof BoneAnimator && animator.getGroup()) {
|
||||
for (var channel of animator.channels) {
|
||||
if (animator[channel] && animator[channel].length) {
|
||||
let times = [];
|
||||
let values = [];
|
||||
let keyframes = animator[channel].slice();
|
||||
keyframes.sort((a, b) => a.time - b.time)
|
||||
keyframes.forEach(kf => {
|
||||
times.push(kf.time);
|
||||
Timeline.time = kf.time;
|
||||
kf.getFixed().toArray(values, values.length);
|
||||
})
|
||||
let trackType = THREE.VectorKeyframeTrack;
|
||||
if (channel === 'rotation') {
|
||||
trackType = THREE.QuaternionKeyframeTrack;
|
||||
channel = 'quaternion';
|
||||
}
|
||||
let track = new trackType(animator.group.mesh.uuid+'.'+channel, times, values, THREE.InterpolateLinear);
|
||||
tracks.push(track);
|
||||
}
|
||||
}
|
||||
} else if (animator instanceof BoneAnimator) {
|
||||
console.log(`Skip export of track ${uuid.substr(0, 7)}... - No connected bone`)
|
||||
}
|
||||
}
|
||||
if (tracks.length) {
|
||||
let clip = new THREE.AnimationClip(animation.name, animation.length, tracks)
|
||||
animations.push(clip);
|
||||
} else {
|
||||
console.log(`Skip export of animation ${animation.name} - No tracks generated`)
|
||||
}
|
||||
})
|
||||
animations = buildAnimationTracks();
|
||||
}
|
||||
|
||||
exporter.parse(gl_scene, (json) => {
|
||||
|
||||
scope.dispatchEvent('compile', {model: json, options});
|
||||
@ -82,14 +139,17 @@ var codec = new Codec('gltf', {
|
||||
export() {
|
||||
var scope = codec;
|
||||
scope.compile(0, content => {
|
||||
Blockbench.export({
|
||||
type: scope.name,
|
||||
extensions: [scope.extension],
|
||||
name: scope.fileName(),
|
||||
startpath: scope.startPath(),
|
||||
content,
|
||||
custom_writer: isApp ? (a, b) => scope.write(a, b) : null,
|
||||
}, path => scope.afterDownload(path))
|
||||
setTimeout(_ => {
|
||||
Blockbench.export({
|
||||
resource_id: 'gltf',
|
||||
type: scope.name,
|
||||
extensions: [scope.extension],
|
||||
name: scope.fileName(),
|
||||
startpath: scope.startPath(),
|
||||
content,
|
||||
custom_writer: isApp ? (a, b) => scope.write(a, b) : null,
|
||||
}, path => scope.afterDownload(path))
|
||||
}, 20)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
219
js/io/io.js
219
js/io/io.js
@ -27,6 +27,7 @@ class ModelFormat {
|
||||
this.box_uv = false;
|
||||
this.optional_box_uv = false;
|
||||
this.single_texture = false;
|
||||
this.animated_textures = false;
|
||||
this.bone_rig = false;
|
||||
this.centered_grid = false;
|
||||
this.rotate_cubes = false;
|
||||
@ -47,6 +48,7 @@ class ModelFormat {
|
||||
Merge.boolean(this, data, 'box_uv');
|
||||
Merge.boolean(this, data, 'optional_box_uv');
|
||||
Merge.boolean(this, data, 'single_texture');
|
||||
Merge.boolean(this, data, 'animated_textures');
|
||||
Merge.boolean(this, data, 'bone_rig');
|
||||
Merge.boolean(this, data, 'centered_grid');
|
||||
Merge.boolean(this, data, 'rotate_cubes');
|
||||
@ -81,6 +83,9 @@ class ModelFormat {
|
||||
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
|
||||
}
|
||||
})
|
||||
uv_dialog.all_editors.forEach(editor => {
|
||||
editor.img.style.objectFit = Format.animated_textures ? 'cover' : 'fill';
|
||||
})
|
||||
updateSelection()
|
||||
Modes.vue.$forceUpdate()
|
||||
Canvas.updateRenderSides()
|
||||
@ -257,6 +262,7 @@ class Codec {
|
||||
export() {
|
||||
var scope = this;
|
||||
Blockbench.export({
|
||||
resource_id: 'model',
|
||||
type: scope.name,
|
||||
extensions: [scope.extension],
|
||||
name: scope.fileName(),
|
||||
@ -324,60 +330,6 @@ class Codec {
|
||||
}
|
||||
}
|
||||
|
||||
//New
|
||||
function resetProject() {
|
||||
Blockbench.dispatchEvent('reset_project');
|
||||
if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
|
||||
Format = 0;
|
||||
elements.length = 0;
|
||||
Outliner.root.purge();
|
||||
Canvas.materials.length = 0;
|
||||
textures.length = 0;
|
||||
selected.length = 0;
|
||||
|
||||
Screencam.stopTimelapse();
|
||||
|
||||
Group.all.empty();
|
||||
Group.selected = undefined;
|
||||
Cube.all.empty();
|
||||
Cube.selected.empty();
|
||||
Locator.all.empty();
|
||||
Locator.selected.empty();
|
||||
|
||||
Blockbench.display_settings = display = {};
|
||||
Project.name = Project.parent = Project.geometry_name = Project.description = '';
|
||||
Project.texture_width = Project.texture_height = 16;
|
||||
Project.ambientocclusion = true;
|
||||
Project.front_gui_light = false;
|
||||
ModelMeta.save_path = ModelMeta.export_path = ModelMeta.animation_path = ModelMeta.name = '';
|
||||
ModelMeta.saved = true;
|
||||
Prop.project_saved = true;
|
||||
Prop.added_models = 0;
|
||||
Canvas.updateAll();
|
||||
Outliner.vue.$forceUpdate();
|
||||
texturelist.$forceUpdate();
|
||||
Undo.history.length = 0;
|
||||
Undo.index = 0;
|
||||
Undo.current_save = null;
|
||||
Painter.current = {};
|
||||
Animator.animations.purge();
|
||||
Timeline.animators.purge();
|
||||
Animator.selected = undefined;
|
||||
$('#var_placeholder_area').val('');
|
||||
}
|
||||
function newProject(format, force) {
|
||||
if (force || showSaveDialog()) {
|
||||
resetProject();
|
||||
Modes.options.edit.select();
|
||||
if (format instanceof ModelFormat) {
|
||||
format.select();
|
||||
}
|
||||
Blockbench.dispatchEvent('new_project');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Import
|
||||
function setupDragHandlers() {
|
||||
@ -399,7 +351,7 @@ function setupDragHandlers() {
|
||||
'plugin',
|
||||
{extensions: ['bbplugin', 'js']},
|
||||
function(files) {
|
||||
loadPluginFromFile(files[0])
|
||||
new Plugin().loadFromFile(files[0], true)
|
||||
}
|
||||
)
|
||||
Blockbench.addDragHandler(
|
||||
@ -661,8 +613,8 @@ function uploadSketchfabModel() {
|
||||
title: 'dialog.sketchfab_uploader.title',
|
||||
width: 540,
|
||||
form: {
|
||||
token: {label: 'dialog.sketchfab_uploader.token', value: settings.sketchfab_token.value},
|
||||
about_token: {type: 'text', text: tl('dialog.sketchfab_uploader.about_token', ['[sketchfab.com/settings/password](https://sketchfab.com/settings/password)'])},
|
||||
token: {label: 'dialog.sketchfab_uploader.token', value: settings.sketchfab_token.value, type: 'password'},
|
||||
about_token: {type: 'info', text: tl('dialog.sketchfab_uploader.about_token', ['[sketchfab.com/settings/password](https://sketchfab.com/settings/password)'])},
|
||||
name: {label: 'dialog.sketchfab_uploader.name'},
|
||||
description: {label: 'dialog.sketchfab_uploader.description', type: 'textarea'},
|
||||
tags: {label: 'dialog.sketchfab_uploader.tags', placeholder: 'Tag1 Tag2'},
|
||||
@ -696,24 +648,6 @@ function uploadSketchfabModel() {
|
||||
|
||||
settings.sketchfab_token.value = formResult.token
|
||||
|
||||
|
||||
/*
|
||||
|
||||
var archive = new JSZip();
|
||||
var model_data = Codecs.obj.compile({all_files: true})
|
||||
archive.file('model.obj', model_data.obj)
|
||||
archive.file('model.mtl', model_data.mtl)
|
||||
for (var key in model_data.images) {
|
||||
var tex = model_data.images[key];
|
||||
if (tex) {
|
||||
archive.file(pathToName(tex.name) + '.png', tex.getBase64(), {base64: true});
|
||||
}
|
||||
}
|
||||
archive.generateAsync({type: 'blob'}).then(blob => {
|
||||
var file = new File([blob], 'model.zip', {type: 'application/x-zip-compressed'})
|
||||
*/
|
||||
|
||||
|
||||
Codecs.gltf.compile({animations: formResult.animations}, (content) => {
|
||||
|
||||
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
|
||||
@ -870,142 +804,12 @@ BARS.defineActions(function() {
|
||||
icon: 'icon-format_free',
|
||||
rotate_cubes: true,
|
||||
bone_rig: true,
|
||||
centered_grid: false,
|
||||
centered_grid: true,
|
||||
optional_box_uv: true,
|
||||
uv_rotation: true,
|
||||
animation_mode: true,
|
||||
})
|
||||
//Project
|
||||
new Action('project_window', {
|
||||
icon: 'featured_play_list',
|
||||
category: 'file',
|
||||
condition: () => Format,
|
||||
click: function () {
|
||||
|
||||
var dialog = new Dialog({
|
||||
id: 'project',
|
||||
title: 'dialog.project.title',
|
||||
width: 540,
|
||||
form: {
|
||||
format: {type: 'text', label: 'data.format', text: Format.name||'unknown'},
|
||||
name: {label: 'dialog.project.name', value: Project.name},
|
||||
parent: {label: 'dialog.project.parent', value: Project.parent, condition: !Format.bone_rig, list: ['paro', 'foo', 'bar']},
|
||||
geometry_name: {label: 'dialog.project.geoname', value: Project.geometry_name, condition: Format.bone_rig},
|
||||
ambientocclusion: {label: 'dialog.project.ao', type: 'checkbox', value: Project.ambientocclusion, condition: Format.id == 'java_block'},
|
||||
box_uv: {label: 'dialog.project.box_uv', type: 'checkbox', value: Project.box_uv, condition: Format.optional_box_uv},
|
||||
texture_width: {
|
||||
label: 'dialog.project.width',
|
||||
type: 'number',
|
||||
value: Project.texture_width,
|
||||
min: 1
|
||||
},
|
||||
texture_height: {
|
||||
label: 'dialog.project.height',
|
||||
type: 'number',
|
||||
value: Project.texture_height,
|
||||
min: 1
|
||||
},
|
||||
},
|
||||
onConfirm: function(formResult) {
|
||||
var save;
|
||||
if (Project.box_uv != formResult.box_uv ||
|
||||
Project.texture_width != formResult.texture_width ||
|
||||
Project.texture_height != formResult.texture_height
|
||||
) {
|
||||
if (!Project.box_uv && !formResult.box_uv
|
||||
&& (Project.texture_width != formResult.texture_width
|
||||
|| Project.texture_height != formResult.texture_height)
|
||||
) {
|
||||
save = Undo.initEdit({uv_only: true, elements: Cube.all, uv_mode: true})
|
||||
Cube.all.forEach(cube => {
|
||||
for (var key in cube.faces) {
|
||||
var uv = cube.faces[key].uv;
|
||||
uv[0] *= formResult.texture_width / Project.texture_width;
|
||||
uv[2] *= formResult.texture_width / Project.texture_width;
|
||||
uv[1] *= formResult.texture_height / Project.texture_height;
|
||||
uv[3] *= formResult.texture_height / Project.texture_height;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
save = Undo.initEdit({uv_mode: true})
|
||||
}
|
||||
Project.texture_width = formResult.texture_width;
|
||||
Project.texture_height = formResult.texture_height;
|
||||
|
||||
if (Format.optional_box_uv) Project.box_uv = formResult.box_uv;
|
||||
Canvas.updateAllUVs()
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
Project.name = formResult.name;
|
||||
Project.parent = formResult.parent;
|
||||
Project.geometry_name = formResult.geometry_name;
|
||||
Project.ambientocclusion = formResult.ambientocclusion;
|
||||
|
||||
if (save) {
|
||||
Undo.finishEdit('change global UV')
|
||||
}
|
||||
|
||||
BARS.updateConditions()
|
||||
if (EditSession.active) {
|
||||
EditSession.sendAll('change_project_meta', JSON.stringify(Project));
|
||||
}
|
||||
dialog.hide()
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
}
|
||||
})
|
||||
new Action('close_project', {
|
||||
icon: 'cancel_presentation',
|
||||
category: 'file',
|
||||
condition: () => (!EditSession.active || EditSession.hosting) && Format,
|
||||
click: function () {
|
||||
if (showSaveDialog()) {
|
||||
resetProject()
|
||||
Modes.options.start.select()
|
||||
Modes.vue.$forceUpdate()
|
||||
Blockbench.dispatchEvent('close_project');
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action('convert_project', {
|
||||
icon: 'fas.fa-file-import',
|
||||
category: 'file',
|
||||
condition: () => (!EditSession.active || EditSession.hosting),
|
||||
click: function () {
|
||||
|
||||
var options = {};
|
||||
for (var key in Formats) {
|
||||
if (key !== Format.id && key !== 'skin') {
|
||||
options[key] = Formats[key].name;
|
||||
}
|
||||
}
|
||||
|
||||
var dialog = new Dialog({
|
||||
id: 'convert_project',
|
||||
title: 'dialog.convert_project.title',
|
||||
width: 540,
|
||||
form: {
|
||||
text: {type: 'text', text: 'dialog.convert_project.text'},
|
||||
format: {
|
||||
label: 'data.format',
|
||||
type: 'select',
|
||||
default: Format.id,
|
||||
options,
|
||||
},
|
||||
},
|
||||
onConfirm: function(formResult) {
|
||||
var format = Formats[formResult.format]
|
||||
if (format && format != Format) {
|
||||
format.convertTo()
|
||||
}
|
||||
dialog.hide()
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
}
|
||||
})
|
||||
//Import
|
||||
new Action('open_model', {
|
||||
icon: 'assessment',
|
||||
@ -1023,6 +827,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
}
|
||||
Blockbench.import({
|
||||
resource_id: 'model',
|
||||
extensions: ['json', 'jem', 'jpm', 'java', 'bbmodel'],
|
||||
type: 'Model',
|
||||
startpath
|
||||
@ -1037,6 +842,7 @@ BARS.defineActions(function() {
|
||||
condition: _ => (Format.id == 'java_block'),
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'model',
|
||||
extensions: ['json'],
|
||||
type: 'JSON Model',
|
||||
multiple: true,
|
||||
@ -1054,6 +860,7 @@ BARS.defineActions(function() {
|
||||
condition: _ => !Project.box_uv,
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'texture',
|
||||
extensions: ['png'],
|
||||
type: 'PNG Texture',
|
||||
readtype: 'image'
|
||||
|
@ -9,7 +9,7 @@ var codec = new Codec('java_block', {
|
||||
var clear_elements = []
|
||||
var textures_used = []
|
||||
var element_index_lut = []
|
||||
var largerCubesNr = 0;
|
||||
var overflow_cubes = [];
|
||||
|
||||
function computeCube(s) {
|
||||
if (s.export == false) return;
|
||||
@ -100,7 +100,7 @@ var codec = new Codec('java_block', {
|
||||
element.faces = e_faces
|
||||
|
||||
function inVd(n) {
|
||||
return n > 32 || n < -16
|
||||
return n < -16 || n > 32;
|
||||
}
|
||||
if (inVd(element.from[0]) ||
|
||||
inVd(element.from[1]) ||
|
||||
@ -109,7 +109,7 @@ var codec = new Codec('java_block', {
|
||||
inVd(element.to[1]) ||
|
||||
inVd(element.to[2])
|
||||
) {
|
||||
largerCubesNr++;
|
||||
overflow_cubes.push(s);
|
||||
}
|
||||
if (Object.keys(element.faces).length) {
|
||||
clear_elements.push(element)
|
||||
@ -155,17 +155,17 @@ var codec = new Codec('java_block', {
|
||||
}
|
||||
})
|
||||
|
||||
//if (options.prevent_dialog !== true && hasUnsavedTextures && settings.dialog_unsaved_textures.value) {
|
||||
// Blockbench.showMessageBox({
|
||||
// translateKey: 'unsaved_textures',
|
||||
// icon: 'broken_image',
|
||||
// })
|
||||
//}
|
||||
if (options.prevent_dialog !== true && largerCubesNr > 0 && settings.dialog_larger_cubes.value) {
|
||||
if (options.prevent_dialog !== true && overflow_cubes.length > 0 && settings.dialog_larger_cubes.value) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'model_clipping',
|
||||
icon: 'settings_overscan',
|
||||
message: tl('message.model_clipping.message', [largerCubesNr])
|
||||
message: tl('message.model_clipping.message', [overflow_cubes.length]),
|
||||
buttons: ['dialog.scale.select_overflow', 'dialog.ok']
|
||||
}, (result) => {
|
||||
if (result == 0) {
|
||||
selected.splice(0, Infinity, ...overflow_cubes)
|
||||
updateSelection();
|
||||
}
|
||||
})
|
||||
}
|
||||
if (options.prevent_dialog !== true && clear_elements.length && ['item/generated', 'item/handheld'].includes(Project.parent)) {
|
||||
@ -246,7 +246,6 @@ var codec = new Codec('java_block', {
|
||||
|
||||
this.dispatchEvent('parse', {model});
|
||||
|
||||
var previous_length = add ? elements.length : 0
|
||||
var previous_texture_length = add ? textures.length : 0
|
||||
var new_cubes = [];
|
||||
var new_textures = [];
|
||||
@ -445,6 +444,7 @@ var format = new ModelFormat({
|
||||
rotation_limit: true,
|
||||
optional_box_uv: true,
|
||||
uv_rotation: true,
|
||||
animated_textures: true,
|
||||
display_mode: true,
|
||||
codec
|
||||
})
|
||||
|
@ -1,150 +1,313 @@
|
||||
(function() {
|
||||
|
||||
function F(num) {
|
||||
var s = trimFloatNumber(num) + '';
|
||||
if (!s.includes('.')) {
|
||||
s += '.0';
|
||||
}
|
||||
return s+'F';
|
||||
}
|
||||
function I(num) {
|
||||
return Math.floor(num)
|
||||
}
|
||||
const Templates = {
|
||||
'1.12': {
|
||||
name: '1.12',
|
||||
flip_y: true,
|
||||
integer_size: true,
|
||||
file:
|
||||
`// Made with Blockbench %(bb_version)
|
||||
// Exported for Minecraft version 1.12
|
||||
// Paste this class into your mod and generate all required imports
|
||||
|
||||
|
||||
public class %(identifier) extends ModelBase {
|
||||
%(fields)
|
||||
|
||||
public %(identifier)() {
|
||||
textureWidth = %(texture_width);
|
||||
textureHeight = %(texture_height);
|
||||
|
||||
%(content)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
|
||||
%(renderers)
|
||||
}
|
||||
|
||||
public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) {
|
||||
modelRenderer.rotateAngleX = x;
|
||||
modelRenderer.rotateAngleY = y;
|
||||
modelRenderer.rotateAngleZ = z;
|
||||
}
|
||||
}`,
|
||||
field: `private final ModelRenderer %(bone);`,
|
||||
bone:
|
||||
`%(bone) = new ModelRenderer(this);
|
||||
%(bone).setRotationPoint(%(x), %(y), %(z));
|
||||
?(has_parent)%(parent).addChild(%(bone));
|
||||
?(has_rotation)setRotationAngle(%(bone), %(rx), %(ry), %(rz));
|
||||
%(cubes)`,
|
||||
renderer: `%(bone).render(f5);`,
|
||||
cube: `%(bone).cubeList.add(new ModelBox(%(bone), %(uv_x), %(uv_y), %(x), %(y), %(z), %(dx), %(dy), %(dz), %(inflate), %(mirror)));`,
|
||||
},
|
||||
|
||||
'1.14': {
|
||||
name: '1.14',
|
||||
flip_y: true,
|
||||
integer_size: true,
|
||||
file:
|
||||
`// Made with Blockbench %(bb_version)
|
||||
// Exported for Minecraft version 1.14
|
||||
// Paste this class into your mod and generate all required imports
|
||||
|
||||
|
||||
public class %(identifier) extends EntityModel {
|
||||
%(fields)
|
||||
|
||||
public %(identifier)() {
|
||||
textureWidth = %(texture_width);
|
||||
textureHeight = %(texture_height);
|
||||
|
||||
%(content)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
|
||||
%(renderers)
|
||||
}
|
||||
|
||||
public void setRotationAngle(RendererModel modelRenderer, float x, float y, float z) {
|
||||
modelRenderer.rotateAngleX = x;
|
||||
modelRenderer.rotateAngleY = y;
|
||||
modelRenderer.rotateAngleZ = z;
|
||||
}
|
||||
}`,
|
||||
field: `private final RendererModel %(bone);`,
|
||||
bone:
|
||||
`%(bone) = new RendererModel(this);
|
||||
%(bone).setRotationPoint(%(x), %(y), %(z));
|
||||
?(has_parent)%(parent).addChild(%(bone));
|
||||
?(has_rotation)setRotationAngle(%(bone), %(rx), %(ry), %(rz));
|
||||
%(cubes)`,
|
||||
renderer: `%(bone).render(f5);`,
|
||||
cube: `%(bone).cubeList.add(new ModelBox(%(bone), %(uv_x), %(uv_y), %(x), %(y), %(z), %(dx), %(dy), %(dz), %(inflate), %(mirror)));`,
|
||||
},
|
||||
|
||||
'1.15': {
|
||||
name: '1.15',
|
||||
flip_y: true,
|
||||
integer_size: false,
|
||||
radians: true,
|
||||
file:
|
||||
`// Made with Blockbench %(bb_version)
|
||||
// Exported for Minecraft version 1.15
|
||||
// Paste this class into your mod and generate all required imports
|
||||
|
||||
|
||||
public class %(identifier) extends EntityModel<Entity> {
|
||||
%(fields)
|
||||
|
||||
public %(identifier)() {
|
||||
textureWidth = %(texture_width);
|
||||
textureHeight = %(texture_height);
|
||||
|
||||
%(content)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotationAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch){
|
||||
//previously the render function, render code was moved to a method below
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrixStack, IVertexBuilder buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha){
|
||||
%(renderers)
|
||||
}
|
||||
|
||||
public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) {
|
||||
modelRenderer.rotateAngleX = x;
|
||||
modelRenderer.rotateAngleY = y;
|
||||
modelRenderer.rotateAngleZ = z;
|
||||
}
|
||||
}`,
|
||||
field: `private final ModelRenderer %(bone);`,
|
||||
bone:
|
||||
`%(bone) = new ModelRenderer(this);
|
||||
%(bone).setRotationPoint(%(x), %(y), %(z));
|
||||
?(has_parent)%(parent).addChild(%(bone));
|
||||
?(has_rotation)setRotationAngle(%(bone), %(rx), %(ry), %(rz));
|
||||
%(cubes)`,
|
||||
renderer: `%(bone).render(matrixStack, buffer, packedLight, packedOverlay);`,
|
||||
cube: `%(bone).setTextureOffset(%(uv_x), %(uv_y)).addBox(%(x), %(y), %(z), %(dx), %(dy), %(dz), %(inflate), %(mirror));`,
|
||||
},
|
||||
|
||||
get(key, version = Project.modded_entity_version) {
|
||||
let temp = Templates[version][key];
|
||||
if (typeof temp === 'string') temp = temp.replace(/\t\t\t/g, '');
|
||||
return temp;
|
||||
},
|
||||
keepLine(line) {
|
||||
return line.replace(/\?\(\w+\)/, '');
|
||||
},
|
||||
getVariableRegex(name) {
|
||||
return new RegExp(`%\\(${name}\\)`, 'g');
|
||||
}
|
||||
}
|
||||
|
||||
function getIdentifier() {
|
||||
return Project.geometry_name.replace(/[\s-]+/g, '_') || 'custom_model';
|
||||
}
|
||||
|
||||
var codec = new Codec('modded_entity', {
|
||||
name: 'Java Class',
|
||||
extension: 'java',
|
||||
remember: true,
|
||||
compile(options) {
|
||||
function F(num) {
|
||||
var s = trimFloatNumber(num) + '';
|
||||
if (!s.includes('.')) {
|
||||
s += '.0';
|
||||
}
|
||||
return s+'F';
|
||||
}
|
||||
|
||||
var bone_nr = 1
|
||||
var model_id = Project.geometry_name.replace(/[\s-]+/g, '_') || 'custom_model';
|
||||
var all_groups = getAllGroups();
|
||||
var renderers = {};
|
||||
let R = Templates.getVariableRegex;
|
||||
let identifier = getIdentifier();
|
||||
|
||||
var ver = settings.class_export_version.value == '1.14' ? 1 : 0;
|
||||
var rendererName = ver == 1 ? 'RendererModel' : 'ModelRenderer'
|
||||
|
||||
var loose_cubes = []
|
||||
Outliner.root.forEach(obj => {
|
||||
if (obj.type === 'cube') {
|
||||
loose_cubes.push(obj)
|
||||
}
|
||||
let all_groups = getAllGroups();
|
||||
let loose_cubes = [];
|
||||
Cube.all.forEach(cube => {
|
||||
if (cube.parent == 'root') loose_cubes.push(cube)
|
||||
})
|
||||
if (loose_cubes.length) {
|
||||
var group = {
|
||||
all_groups.push({
|
||||
name: 'bb_main',
|
||||
rotation: [0, 0, 0],
|
||||
origin: [0, 0, 0],
|
||||
parent: 'root',
|
||||
children: loose_cubes
|
||||
}
|
||||
all_groups.splice(0, 0, group)
|
||||
}
|
||||
|
||||
all_groups.forEach((g) => {
|
||||
//model += `\nthis.bone${bone_nr} = new ModelRenderer`
|
||||
var id = g.name
|
||||
bone_nr++;
|
||||
if (g.export === false) return;
|
||||
|
||||
var bone = {
|
||||
id: id,
|
||||
rootBone: g.parent instanceof Group == false,
|
||||
lines: [
|
||||
`${id} = new ${rendererName}(this);`,//Texture Offset
|
||||
]
|
||||
}
|
||||
var origin = [-g.origin[0], -g.origin[1], g.origin[2]]
|
||||
//Rotation
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.lines.push(
|
||||
`setRotationAngle(${id}, ${
|
||||
F(Math.degToRad(-g.rotation[0])) }, ${
|
||||
F(Math.degToRad(-g.rotation[1])) }, ${
|
||||
F(Math.degToRad(g.rotation[2])) });`
|
||||
)
|
||||
}
|
||||
//Parent
|
||||
if (!bone.rootBone && all_groups.indexOf(g.parent) >= 0) {
|
||||
bone.lines.push(
|
||||
`${ g.parent.name }.addChild(${id});`
|
||||
)
|
||||
origin[0] += g.parent.origin[0]
|
||||
origin[1] += g.parent.origin[1]
|
||||
origin[2] -= g.parent.origin[2]
|
||||
} else {
|
||||
origin[1] += 24
|
||||
}
|
||||
//origin
|
||||
bone.lines.splice(1, 0,
|
||||
`${id}.setRotationPoint(${F(origin[0])}, ${F(origin[1])}, ${F(origin[2])});`
|
||||
)
|
||||
|
||||
//Boxes
|
||||
g.children.forEach((obj) => {
|
||||
if (obj.export === false || obj.type !== 'cube') return;
|
||||
var values = [
|
||||
''+id,
|
||||
Math.floor(obj.uv_offset[0]),
|
||||
Math.floor(obj.uv_offset[1]),
|
||||
F(g.origin[0] - obj.to[0]),
|
||||
F(-obj.from[1] - obj.size(1, true) + g.origin[1]),
|
||||
F(obj.from[2] - g.origin[2]),
|
||||
obj.size(0, true),
|
||||
obj.size(1, true),
|
||||
obj.size(2, true),
|
||||
F(obj.inflate),
|
||||
obj.mirror_uv
|
||||
]
|
||||
bone.lines.push(
|
||||
`${id}.cubeList.add(new ModelBox(${ values.join(', ') }));`
|
||||
)
|
||||
})
|
||||
|
||||
renderers[id] = bone;
|
||||
|
||||
})
|
||||
|
||||
|
||||
var model = (settings.credit.value
|
||||
? '// '+settings.credit.value+'\n'
|
||||
: '')+
|
||||
'// Paste this code into your mod.\n' +
|
||||
'// Make sure to generate all required imports\n'
|
||||
if (ver == 1) {
|
||||
model += '\npublic class '+model_id+' extends EntityModel {';
|
||||
} else {
|
||||
model += '\npublic class '+model_id+' extends ModelBase {';
|
||||
}
|
||||
|
||||
for (var r_id in renderers) {
|
||||
model += `\n private final ${rendererName} ${r_id};`;
|
||||
}
|
||||
let model = Templates.get('file');
|
||||
|
||||
model += '\n'+
|
||||
'\n public '+model_id+'() {'+
|
||||
'\n textureWidth = '+ (Project.texture_width || 32) +';'+
|
||||
'\n textureHeight = '+ (Project.texture_height|| 32) +';\n';
|
||||
model = model.replace(R('bb_version'), Blockbench.version);
|
||||
model = model.replace(R('identifier'), identifier);
|
||||
model = model.replace(R('texture_width'), Project.texture_width);
|
||||
model = model.replace(R('texture_height'), Project.texture_height);
|
||||
|
||||
for (var r_id in renderers) {
|
||||
model += `\n ${renderers[r_id].lines.join('\n ')}\n`;
|
||||
}
|
||||
|
||||
model +=
|
||||
' }\n'+
|
||||
'\n @Override'+
|
||||
'\n public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {'
|
||||
|
||||
for (var r_id in renderers) {
|
||||
if (renderers[r_id].rootBone) {
|
||||
model += `\n ${r_id}.render(f5);`;
|
||||
model = model.replace(R('fields'), () => {
|
||||
let group_snippets = [];
|
||||
for (var group of all_groups) {
|
||||
if (group instanceof Group === false || !group.export) continue;
|
||||
let snippet = Templates.get('field')
|
||||
.replace(R('bone'), group.name)
|
||||
group_snippets.push(snippet);
|
||||
}
|
||||
}
|
||||
model +=
|
||||
'\n }'+
|
||||
`\n public void setRotationAngle(${rendererName} modelRenderer, float x, float y, float z) {`+
|
||||
'\n modelRenderer.rotateAngleX = x;'+
|
||||
'\n modelRenderer.rotateAngleY = y;'+
|
||||
'\n modelRenderer.rotateAngleZ = z;'+
|
||||
'\n }'+
|
||||
'\n}';
|
||||
return group_snippets.join('\n\t')
|
||||
});
|
||||
|
||||
model = model.replace(R('content'), () => {
|
||||
|
||||
let group_snippets = [];
|
||||
for (var group of all_groups) {
|
||||
|
||||
if (group instanceof Group === false || !group.export) continue;
|
||||
let snippet = Templates.get('bone')
|
||||
|
||||
.replace(R('bone'), group.name)
|
||||
|
||||
.replace(/\n\?\(has_rotation\).+/, group.rotation.allEqual(0) ? '' : Templates.keepLine)
|
||||
|
||||
if (Templates.get('radians')) {
|
||||
snippet = snippet
|
||||
.replace(R('rx'), F(Math.degToRad(-group.rotation[0])))
|
||||
.replace(R('ry'), F(Math.degToRad(-group.rotation[1])))
|
||||
.replace(R('rz'), F(Math.degToRad(group.rotation[2])))
|
||||
} else {
|
||||
snippet = snippet
|
||||
.replace(R('rx'), F(-group.rotation[0]))
|
||||
.replace(R('ry'), F(-group.rotation[1]))
|
||||
.replace(R('rz'), F(group.rotation[2]))
|
||||
}
|
||||
|
||||
|
||||
var origin = group.origin.slice();
|
||||
if (group.parent instanceof Group) {
|
||||
origin.V3_subtract(group.parent.origin)
|
||||
}
|
||||
origin[0] *= -1;
|
||||
if (Templates.get('flip_y')) {
|
||||
origin[1] *= -1;
|
||||
if (group.parent instanceof Group === false) {
|
||||
origin[1] += 24
|
||||
}
|
||||
}
|
||||
|
||||
snippet = snippet
|
||||
.replace(R('x'), F(origin[0]))
|
||||
.replace(R('y'), F(origin[1]))
|
||||
.replace(R('z'), F(origin[2]))
|
||||
|
||||
.replace(/\n\?\(has_parent\).+/, group.parent instanceof Group ? Templates.keepLine : '')
|
||||
.replace(R('parent'), group.parent.name)
|
||||
|
||||
.replace(R('cubes'), () => {
|
||||
|
||||
let cube_snippets = [];
|
||||
for (var cube of group.children) {
|
||||
if (cube instanceof Cube === false || !cube.export) continue;
|
||||
|
||||
let c_snippet = Templates.get('cube')
|
||||
.replace(R('bone'), group.name)
|
||||
|
||||
.replace(R('uv_x'), I(cube.uv_offset[0]))
|
||||
.replace(R('uv_y'), I(cube.uv_offset[1]))
|
||||
|
||||
.replace(R('inflate'), F(cube.inflate))
|
||||
.replace(R('mirror'), cube.mirror_uv)
|
||||
|
||||
if (Templates.get('flip_y')) {
|
||||
c_snippet = c_snippet
|
||||
.replace(R('x'), F(group.origin[0] - cube.to[0]) )
|
||||
.replace(R('y'), F(-cube.from[1] - cube.size(1) + group.origin[1]) )
|
||||
.replace(R('z'), F(cube.from[2] - group.origin[2]) )
|
||||
|
||||
} else {
|
||||
c_snippet = c_snippet
|
||||
.replace(R('x'), F(group.origin[0] - cube.to[0]) )
|
||||
.replace(R('y'), F(cube.from[1] - group.origin[1]) )
|
||||
.replace(R('z'), F(cube.from[2] - group.origin[2]) )
|
||||
}
|
||||
if (Templates.get('integer_size')) {
|
||||
c_snippet = c_snippet
|
||||
.replace(R('dx'), I(cube.size(0, true)) )
|
||||
.replace(R('dy'), I(cube.size(1, true)) )
|
||||
.replace(R('dz'), I(cube.size(2, true)) )
|
||||
|
||||
} else {
|
||||
c_snippet = c_snippet
|
||||
.replace(R('dx'), F(cube.size(0)) )
|
||||
.replace(R('dy'), F(cube.size(1)) )
|
||||
.replace(R('dz'), F(cube.size(2)) )
|
||||
}
|
||||
|
||||
cube_snippets.push(c_snippet);
|
||||
}
|
||||
return cube_snippets.join('\n');
|
||||
})
|
||||
.replace(/\n/g, '\n\t\t')
|
||||
|
||||
group_snippets.push(snippet);
|
||||
}
|
||||
return group_snippets.join('\n\n\t\t')
|
||||
});
|
||||
|
||||
model = model.replace(R('renderers'), () => {
|
||||
let group_snippets = [];
|
||||
for (var group of all_groups) {
|
||||
if (group instanceof Group === false || !group.export) continue;
|
||||
let snippet = Templates.get('renderer')
|
||||
.replace(R('bone'), group.name)
|
||||
group_snippets.push(snippet);
|
||||
}
|
||||
return group_snippets.join('\n\t\t')
|
||||
});
|
||||
|
||||
this.dispatchEvent('compile', {model, options});
|
||||
return model;
|
||||
@ -160,11 +323,6 @@ var codec = new Codec('modded_entity', {
|
||||
}
|
||||
})
|
||||
|
||||
var getArgs = function(input) {
|
||||
var i = input.search('(')
|
||||
var args = input.substr(i+1).replace(/\)$/, '');
|
||||
return args.split(/, ?/);
|
||||
}
|
||||
function parseScheme(scheme, input) {
|
||||
scheme = scheme.replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/\./g, '\\.');
|
||||
var parts = scheme.split('$');
|
||||
@ -269,6 +427,18 @@ var codec = new Codec('modded_entity', {
|
||||
last_uv = [match[1], match[2]];
|
||||
} else
|
||||
|
||||
if (
|
||||
parseScheme('$v = new ModelRenderer(this)', line)
|
||||
) {
|
||||
// Blockbench for 1.15
|
||||
if (!bones[match[0]]) {
|
||||
bones[match[0]] = new Group({
|
||||
name: match[0],
|
||||
origin: [0, 0, 0]
|
||||
}).init();
|
||||
}
|
||||
} else
|
||||
|
||||
if (parseScheme('$v.setRotationPoint($f, $f, $f)', line)) {
|
||||
var bone = bones[match[0]]
|
||||
if (bone) {
|
||||
@ -288,6 +458,7 @@ var codec = new Codec('modded_entity', {
|
||||
child.addTo(parent);
|
||||
child.origin.V3_add(parent.origin)
|
||||
child.origin[1] -= 24;
|
||||
|
||||
child.children.forEach(cube => {
|
||||
if (cube instanceof Cube) {
|
||||
cube.from[0] += parent.origin[0]; cube.to[0] += parent.origin[0];
|
||||
@ -347,6 +518,30 @@ var codec = new Codec('modded_entity', {
|
||||
cube.addTo(bones[match[0]]).init();
|
||||
} else
|
||||
|
||||
if (parseScheme('$v.setTextureOffset($i, $i).addBox($f, $f, $f, $f, $f, $f, $f, $b)', line)
|
||||
) {
|
||||
var group = bones[match[0]];
|
||||
var cube = new Cube({
|
||||
name: match[0],
|
||||
uv_offset: [match[1], match[2]],
|
||||
from: [
|
||||
group.origin[0] - match[3] - match[6],
|
||||
group.origin[1] - match[4] - match[7],
|
||||
group.origin[2] + match[5]
|
||||
],
|
||||
inflate: match[9],
|
||||
mirror_uv: match[10]
|
||||
})
|
||||
cube.extend({
|
||||
to: [
|
||||
cube.from[0] + match[6],
|
||||
cube.from[1] + match[7],
|
||||
cube.from[2] + match[8],
|
||||
]
|
||||
});
|
||||
cube.addTo(bones[match[0]]).init();
|
||||
} else
|
||||
|
||||
|
||||
//Rotation
|
||||
if (parseScheme('setRotationAngle($v, $f, $f, $f)', line)) {
|
||||
@ -423,8 +618,12 @@ var codec = new Codec('modded_entity', {
|
||||
}
|
||||
})
|
||||
Canvas.updateAll();
|
||||
},
|
||||
fileName() {
|
||||
return getIdentifier();
|
||||
}
|
||||
})
|
||||
codec.templates = Templates;
|
||||
|
||||
var format = new ModelFormat({
|
||||
id: 'modded_entity',
|
||||
@ -432,12 +631,13 @@ var format = new ModelFormat({
|
||||
codec,
|
||||
box_uv: true,
|
||||
single_texture: true,
|
||||
integer_size: true,
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
})
|
||||
Object.defineProperty(format, 'integer_size', {get: _ => Templates.get('integer_size')})
|
||||
codec.format = format;
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'export_class_entity',
|
||||
|
@ -210,6 +210,7 @@ var codec = new Codec('obj', {
|
||||
var scope = this;
|
||||
if (isApp) {
|
||||
Blockbench.export({
|
||||
resource_id: 'obj',
|
||||
type: this.name,
|
||||
extensions: [this.extension],
|
||||
name: this.fileName(),
|
||||
|
@ -259,6 +259,7 @@ var format = new ModelFormat({
|
||||
centered_grid: true,
|
||||
codec
|
||||
})
|
||||
Object.defineProperty(format, 'integer_size', {get: _ => Format.box_uv})
|
||||
codec.format = format;
|
||||
|
||||
|
||||
|
@ -241,6 +241,7 @@ BARS.defineActions(function() {
|
||||
condition: () => (Format.id == 'optifine_entity' || Format.id == 'optifine_part'),
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'model',
|
||||
extensions: ['jpm'],
|
||||
type: 'JPM Entity Part Model',
|
||||
multiple: true,
|
||||
|
238
js/io/project.js
Normal file
238
js/io/project.js
Normal file
@ -0,0 +1,238 @@
|
||||
const Project = {
|
||||
name : '',
|
||||
parent : '',
|
||||
geometry_name : '',
|
||||
description : '',
|
||||
_box_uv : false,
|
||||
get box_uv() {return Project._box_uv},
|
||||
set box_uv(v) {
|
||||
if (Project._box_uv != v) {
|
||||
Project._box_uv = v;
|
||||
switchBoxUV(v);
|
||||
}
|
||||
},
|
||||
get texture_width() {return Project._texture_width},
|
||||
get texture_height() {return Project._texture_height},
|
||||
set texture_width(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
Project._texture_width = n;
|
||||
},
|
||||
set texture_height(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
Project._texture_height = n;
|
||||
},
|
||||
_texture_width : 16,
|
||||
_texture_height : 16,
|
||||
ambientocclusion: true,
|
||||
front_gui_light: false,
|
||||
visible_box: [1, 1, 0], /*width, height, y*/
|
||||
modded_entity_version: '1.15',
|
||||
get optional_box_uv() {
|
||||
return Format.optional_box_uv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//New
|
||||
function resetProject() {
|
||||
Blockbench.dispatchEvent('reset_project');
|
||||
if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
|
||||
Format = 0;
|
||||
elements.length = 0;
|
||||
Outliner.root.purge();
|
||||
Canvas.materials.length = 0;
|
||||
textures.length = 0;
|
||||
selected.length = 0;
|
||||
|
||||
Screencam.stopTimelapse();
|
||||
|
||||
Group.all.empty();
|
||||
Group.selected = undefined;
|
||||
Cube.all.empty();
|
||||
Cube.selected.empty();
|
||||
Locator.all.empty();
|
||||
Locator.selected.empty();
|
||||
|
||||
Blockbench.display_settings = display = {};
|
||||
Project.name = Project.parent = Project.geometry_name = Project.description = '';
|
||||
Project.texture_width = Project.texture_height = 16;
|
||||
Project.ambientocclusion = true;
|
||||
Project.front_gui_light = false;
|
||||
Project.modded_entity_version = '1.15';
|
||||
Project.visible_box.splice(0, Infinity, ...[1, 1, 0])
|
||||
ModelMeta.save_path = ModelMeta.export_path = ModelMeta.animation_path = ModelMeta.name = '';
|
||||
ModelMeta.saved = true;
|
||||
Prop.project_saved = true;
|
||||
Prop.added_models = 0;
|
||||
Canvas.updateAll();
|
||||
Outliner.vue.$forceUpdate();
|
||||
texturelist.$forceUpdate();
|
||||
Undo.history.length = 0;
|
||||
Undo.index = 0;
|
||||
Undo.current_save = null;
|
||||
Painter.current = {};
|
||||
Animator.animations.purge();
|
||||
Timeline.animators.purge();
|
||||
Animator.selected = undefined;
|
||||
$('#var_placeholder_area').val('');
|
||||
}
|
||||
function newProject(format, force) {
|
||||
if (force || showSaveDialog()) {
|
||||
resetProject();
|
||||
Modes.options.edit.select();
|
||||
if (format instanceof ModelFormat) {
|
||||
format.select();
|
||||
}
|
||||
Blockbench.dispatchEvent('new_project');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
|
||||
new Action('project_window', {
|
||||
icon: 'featured_play_list',
|
||||
category: 'file',
|
||||
condition: () => Format,
|
||||
click: function () {
|
||||
|
||||
let modded_entity_options = {}
|
||||
for (var key in Codecs.modded_entity.templates) {
|
||||
if (Codecs.modded_entity.templates[key] instanceof Function == false) {
|
||||
modded_entity_options[key] = Codecs.modded_entity.templates[key].name;
|
||||
}
|
||||
}
|
||||
var dialog = new Dialog({
|
||||
id: 'project',
|
||||
title: 'dialog.project.title',
|
||||
width: 540,
|
||||
form: {
|
||||
format: {type: 'info', label: 'data.format', text: Format.name||'unknown'},
|
||||
name: {label: 'dialog.project.name', value: Project.name},
|
||||
|
||||
parent: {label: 'dialog.project.parent', value: Project.parent, condition: !Format.bone_rig, list: ['paro', 'foo', 'bar']},
|
||||
geometry_name: {label: 'dialog.project.geoname', value: Project.geometry_name, condition: Format.bone_rig},
|
||||
modded_entity_version: {label: 'dialog.project.modded_entity_version', type: 'select', default: Project.modded_entity_version, options: modded_entity_options, condition: Format.id == 'modded_entity'},
|
||||
ambientocclusion: {label: 'dialog.project.ao', type: 'checkbox', value: Project.ambientocclusion, condition: Format.id == 'java_block'},
|
||||
|
||||
box_uv: {label: 'dialog.project.box_uv', type: 'checkbox', value: Project.box_uv, condition: Format.optional_box_uv},
|
||||
texture_width: {
|
||||
label: 'dialog.project.width',
|
||||
type: 'number',
|
||||
value: Project.texture_width,
|
||||
min: 1
|
||||
},
|
||||
texture_height: {
|
||||
label: 'dialog.project.height',
|
||||
type: 'number',
|
||||
value: Project.texture_height,
|
||||
min: 1
|
||||
},
|
||||
},
|
||||
onConfirm: function(formResult) {
|
||||
var save;
|
||||
if (Project.box_uv != formResult.box_uv ||
|
||||
Project.texture_width != formResult.texture_width ||
|
||||
Project.texture_height != formResult.texture_height
|
||||
) {
|
||||
if (!Project.box_uv && !formResult.box_uv
|
||||
&& (Project.texture_width != formResult.texture_width
|
||||
|| Project.texture_height != formResult.texture_height)
|
||||
) {
|
||||
save = Undo.initEdit({uv_only: true, elements: Cube.all, uv_mode: true})
|
||||
Cube.all.forEach(cube => {
|
||||
for (var key in cube.faces) {
|
||||
var uv = cube.faces[key].uv;
|
||||
uv[0] *= formResult.texture_width / Project.texture_width;
|
||||
uv[2] *= formResult.texture_width / Project.texture_width;
|
||||
uv[1] *= formResult.texture_height / Project.texture_height;
|
||||
uv[3] *= formResult.texture_height / Project.texture_height;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
save = Undo.initEdit({uv_mode: true})
|
||||
}
|
||||
Project.texture_width = formResult.texture_width;
|
||||
Project.texture_height = formResult.texture_height;
|
||||
|
||||
if (Format.optional_box_uv) Project.box_uv = formResult.box_uv;
|
||||
Canvas.updateAllUVs()
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
Project.name = formResult.name;
|
||||
Project.parent = formResult.parent;
|
||||
Project.geometry_name = formResult.geometry_name;
|
||||
Project.ambientocclusion = formResult.ambientocclusion;
|
||||
if (formResult.modded_entity_version) Project.modded_entity_version = formResult.modded_entity_version;
|
||||
|
||||
if (save) {
|
||||
Undo.finishEdit('change global UV')
|
||||
}
|
||||
|
||||
BARS.updateConditions()
|
||||
if (EditSession.active) {
|
||||
EditSession.sendAll('change_project_meta', JSON.stringify(Project));
|
||||
}
|
||||
dialog.hide()
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
}
|
||||
})
|
||||
new Action('close_project', {
|
||||
icon: 'cancel_presentation',
|
||||
category: 'file',
|
||||
condition: () => (!EditSession.active || EditSession.hosting) && Format,
|
||||
click: function () {
|
||||
if (showSaveDialog()) {
|
||||
resetProject()
|
||||
Modes.options.start.select()
|
||||
Modes.vue.$forceUpdate()
|
||||
Blockbench.dispatchEvent('close_project');
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action('convert_project', {
|
||||
icon: 'fas.fa-file-import',
|
||||
category: 'file',
|
||||
condition: () => (!EditSession.active || EditSession.hosting),
|
||||
click: function () {
|
||||
|
||||
var options = {};
|
||||
for (var key in Formats) {
|
||||
if (key !== Format.id && key !== 'skin') {
|
||||
options[key] = Formats[key].name;
|
||||
}
|
||||
}
|
||||
|
||||
var dialog = new Dialog({
|
||||
id: 'convert_project',
|
||||
title: 'dialog.convert_project.title',
|
||||
width: 540,
|
||||
form: {
|
||||
text: {type: 'info', text: 'dialog.convert_project.text'},
|
||||
format: {
|
||||
label: 'data.format',
|
||||
type: 'select',
|
||||
default: Format.id,
|
||||
options,
|
||||
},
|
||||
},
|
||||
onConfirm: function(formResult) {
|
||||
var format = Formats[formResult.format]
|
||||
if (format && format != Format) {
|
||||
format.convertTo()
|
||||
}
|
||||
dialog.hide()
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
}
|
||||
})
|
||||
})
|
266
js/io/skin.js
266
js/io/skin.js
@ -74,7 +74,7 @@ const codec = new Codec('skin_model', {
|
||||
this.dispatchEvent('compile', {model: entitymodel, options});
|
||||
return entitymodel
|
||||
},
|
||||
parse(data, resolution, texture_path) {
|
||||
parse(data, resolution, texture_path, pose = true) {
|
||||
this.dispatchEvent('parse', {model: data});
|
||||
Project.geometry_name = data.name;
|
||||
Project.texture_width = data.texturewidth || 64;
|
||||
@ -91,7 +91,7 @@ const codec = new Codec('skin_model', {
|
||||
var group = new Group({
|
||||
name: b.name,
|
||||
origin: b.pivot,
|
||||
rotation: b.rotation
|
||||
rotation: (pose && b.pose) ? b.pose : b.rotation
|
||||
}).init()
|
||||
group.isOpen = true;
|
||||
bones[b.name] = group
|
||||
@ -176,7 +176,7 @@ const codec = new Codec('skin_model', {
|
||||
EditSession.initNewModel()
|
||||
},
|
||||
})
|
||||
|
||||
codec.compile = null;
|
||||
|
||||
|
||||
const format = new ModelFormat({
|
||||
@ -211,7 +211,7 @@ function generateTemplate(width = 64, height = 64, name = 'name', eyes) {
|
||||
canvas.height = height;
|
||||
|
||||
Cube.all.forEach(cube => {
|
||||
TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas);
|
||||
TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas, null, !!cube.inflate);
|
||||
})
|
||||
if (eyes) {
|
||||
var res_multiple = canvas.width/Project.texture_width;
|
||||
@ -256,7 +256,8 @@ const skin_dialog = new Dialog({
|
||||
cod: 'Cod',
|
||||
cow: 'Cow',
|
||||
creeper: 'Creeper',
|
||||
dolphin: 'Dolphin',
|
||||
dolphin_bedrock: 'Dolphin (Bedrock)',
|
||||
dolphin_java: 'Dolphin (Java)',
|
||||
enderdragon: 'Ender Dragon',
|
||||
enderman: 'Enderman',
|
||||
endermite: 'Endermite',
|
||||
@ -293,6 +294,7 @@ const skin_dialog = new Dialog({
|
||||
snowgolem: 'Snowgolem',
|
||||
spider: 'Spider',
|
||||
squid: 'Squid',
|
||||
strider: 'Strider',
|
||||
tropicalfish_a: 'Tropicalfish A',
|
||||
tropicalfish_b: 'Tropicalfish B',
|
||||
turtle: 'Turtle',
|
||||
@ -319,13 +321,14 @@ const skin_dialog = new Dialog({
|
||||
type: 'file',
|
||||
extensions: ['png'],
|
||||
filetype: 'PNG',
|
||||
}
|
||||
},
|
||||
pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true}
|
||||
},
|
||||
draggable: true,
|
||||
onConfirm(result) {
|
||||
if (newProject(format)) {
|
||||
var model = JSON.parse(skin_presets[result.model]);
|
||||
codec.parse(model, result.resolution/16, result.texture);
|
||||
codec.parse(model, result.resolution/16, result.texture, result.pose);
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
@ -374,7 +377,7 @@ skin_presets.steve = `{
|
||||
"name": "Head",
|
||||
"color": 1,
|
||||
"pivot": [0, 24, 0],
|
||||
"rotation": [-6, 5, 0],
|
||||
"pose": [-6, 5, 0],
|
||||
"cubes": [
|
||||
{"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
|
||||
{"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
|
||||
@ -393,7 +396,7 @@ skin_presets.steve = `{
|
||||
"name": "Right Arm",
|
||||
"color": 5,
|
||||
"pivot": [-5, 22, 0],
|
||||
"rotation": [-10, 0, 0],
|
||||
"pose": [-10, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "Right Arm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]},
|
||||
{"name": "Right Arm Layer", "visibility": false, "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 32], "inflate": 0.25}
|
||||
@ -403,7 +406,7 @@ skin_presets.steve = `{
|
||||
"name": "Left Arm",
|
||||
"color": 0,
|
||||
"pivot": [5, 22, 0],
|
||||
"rotation": [12, 0, 0],
|
||||
"pose": [12, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "Left Arm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]},
|
||||
{"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [48, 48], "inflate": 0.25}
|
||||
@ -413,7 +416,7 @@ skin_presets.steve = `{
|
||||
"name": "Right Leg",
|
||||
"color": 6,
|
||||
"pivot": [-1.9, 12, 0],
|
||||
"rotation": [11, 0, 2],
|
||||
"pose": [11, 0, 2],
|
||||
"cubes": [
|
||||
{"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]},
|
||||
{"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25}
|
||||
@ -423,7 +426,7 @@ skin_presets.steve = `{
|
||||
"name": "Left Leg",
|
||||
"color": 7,
|
||||
"pivot": [1.9, 12, 0],
|
||||
"rotation": [-10, 0, -2],
|
||||
"pose": [-10, 0, -2],
|
||||
"cubes": [
|
||||
{"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]},
|
||||
{"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25}
|
||||
@ -444,7 +447,7 @@ skin_presets.alex = `{
|
||||
"name": "Head",
|
||||
"color": 1,
|
||||
"pivot": [0, 24, 0],
|
||||
"rotation": [-6, 5, 0],
|
||||
"pose": [-6, 5, 0],
|
||||
"cubes": [
|
||||
{"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
|
||||
{"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
|
||||
@ -463,7 +466,7 @@ skin_presets.alex = `{
|
||||
"name": "Right Arm",
|
||||
"color": 5,
|
||||
"pivot": [-5, 22, 0],
|
||||
"rotation": [-10, 0, 0],
|
||||
"pose": [-10, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "Right Arm", "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 16]},
|
||||
{"name": "Right Arm Layer", "visibility": false, "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 32], "inflate": 0.25}
|
||||
@ -473,7 +476,7 @@ skin_presets.alex = `{
|
||||
"name": "Left Arm",
|
||||
"color": 0,
|
||||
"pivot": [5, 22, 0],
|
||||
"rotation": [12, 0, 0],
|
||||
"pose": [12, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "Left Arm", "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [32, 48]},
|
||||
{"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [48, 48], "inflate": 0.25}
|
||||
@ -483,7 +486,7 @@ skin_presets.alex = `{
|
||||
"name": "Right Leg",
|
||||
"color": 6,
|
||||
"pivot": [-1.9, 12, 0],
|
||||
"rotation": [11, 0, 2],
|
||||
"pose": [11, 0, 2],
|
||||
"cubes": [
|
||||
{"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]},
|
||||
{"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25}
|
||||
@ -493,7 +496,7 @@ skin_presets.alex = `{
|
||||
"name": "Left Leg",
|
||||
"color": 7,
|
||||
"pivot": [1.9, 12, 0],
|
||||
"rotation": [-10, 0, -2],
|
||||
"pose": [-10, 0, -2],
|
||||
"cubes": [
|
||||
{"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]},
|
||||
{"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25}
|
||||
@ -615,7 +618,7 @@ skin_presets.bat = `{
|
||||
"name": "rightWing",
|
||||
"parent": "body",
|
||||
"pivot": [0, 24, 0],
|
||||
"rotation": [0, -10, 0],
|
||||
"pose": [0, -10, 0],
|
||||
"cubes": [
|
||||
{"name": "rightWing", "origin": [-12, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]}
|
||||
]
|
||||
@ -624,7 +627,7 @@ skin_presets.bat = `{
|
||||
"name": "rightWingTip",
|
||||
"parent": "rightWing",
|
||||
"pivot": [-12, 23, 1.5],
|
||||
"rotation": [0, -15, 0],
|
||||
"pose": [0, -15, 0],
|
||||
"cubes": [
|
||||
{"name": "rightWingTip", "origin": [-20, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]}
|
||||
]
|
||||
@ -633,7 +636,7 @@ skin_presets.bat = `{
|
||||
"name": "leftWing",
|
||||
"parent": "body",
|
||||
"pivot": [0, 24, 0],
|
||||
"rotation": [0, 10, 0],
|
||||
"pose": [0, 10, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "leftWing", "origin": [2, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]}
|
||||
@ -643,7 +646,7 @@ skin_presets.bat = `{
|
||||
"name": "leftWingTip",
|
||||
"parent": "leftWing",
|
||||
"pivot": [12, 23, 1.5],
|
||||
"rotation": [0, 15, 0],
|
||||
"pose": [0, 15, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "leftWingTip", "origin": [12, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]}
|
||||
@ -1284,7 +1287,7 @@ skin_presets.creeper = `{
|
||||
}
|
||||
]
|
||||
}`;
|
||||
skin_presets.dolphin = `{
|
||||
skin_presets.dolphin_bedrock = `{
|
||||
"name": "dolphin",
|
||||
"texturewidth": 64,
|
||||
"textureheight": 64,
|
||||
@ -1316,6 +1319,7 @@ skin_presets.dolphin = `{
|
||||
"name": "tail",
|
||||
"parent": "body",
|
||||
"pivot": [0, 2.5, 11],
|
||||
"pose": [-5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-2, 0, 10], "size": [4, 5, 11], "uv": [0, 33]}
|
||||
]
|
||||
@ -1324,6 +1328,7 @@ skin_presets.dolphin = `{
|
||||
"name": "tail_fin",
|
||||
"parent": "tail",
|
||||
"pivot": [0, 2.5, 20],
|
||||
"pose": [-8, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail_fin", "origin": [-5, 2, 19], "size": [10, 1, 6], "uv": [0, 49]}
|
||||
]
|
||||
@ -1357,6 +1362,81 @@ skin_presets.dolphin = `{
|
||||
}
|
||||
]
|
||||
}`;
|
||||
skin_presets.dolphin_java = `{
|
||||
"name": "dolphin",
|
||||
"texturewidth": 64,
|
||||
"textureheight": 64,
|
||||
"bones": [
|
||||
{
|
||||
"name": "body",
|
||||
"pivot": [0, 0, -3],
|
||||
"cubes": [
|
||||
{"name": "body", "origin": [-4, 0, -3], "size": [8, 7, 13], "uv": [22, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "head",
|
||||
"parent": "body",
|
||||
"pivot": [0, 0, -3],
|
||||
"cubes": [
|
||||
{"name": "head", "origin": [-4, 0, -9], "size": [8, 7, 6], "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "nose",
|
||||
"parent": "head",
|
||||
"pivot": [0, 0, -13],
|
||||
"cubes": [
|
||||
{"name": "nose", "origin": [-1, 0, -13], "size": [2, 2, 4], "uv": [0, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tail",
|
||||
"parent": "body",
|
||||
"pivot": [0, 2.5, 11],
|
||||
"pose": [-5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-2, 0, 10], "size": [4, 5, 11], "uv": [0, 19]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tail_fin",
|
||||
"parent": "tail",
|
||||
"pivot": [0, 2.5, 20],
|
||||
"pose": [-8, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail_fin", "origin": [-5, 2, 19], "size": [10, 1, 6], "uv": [19, 20]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "back_fin",
|
||||
"parent": "body",
|
||||
"pivot": [0, 7, 2],
|
||||
"rotation": [60, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "back_fin", "origin": [-0.5, 3.75, 1.5], "size": [1, 4, 5], "uv": [51, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "left_fin",
|
||||
"parent": "body",
|
||||
"pivot": [3, 2, 2],
|
||||
"rotation": [55, 0, 107],
|
||||
"cubes": [
|
||||
{"name": "left_fin", "origin": [3, 2, 0.5], "size": [1, 4, 7], "uv": [48, 20]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "right_fin",
|
||||
"parent": "body",
|
||||
"pivot": [-3, 2, 2],
|
||||
"rotation": [55, 0, -107],
|
||||
"cubes": [
|
||||
{"name": "left_fin", "origin": [-4, 2, 0.5], "size": [1, 4, 7], "uv": [48, 20], "mirror": true}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`;
|
||||
skin_presets.enderdragon = `{
|
||||
"name": "enderdragon",
|
||||
"texturewidth": 256,
|
||||
@ -1365,7 +1445,7 @@ skin_presets.enderdragon = `{
|
||||
{
|
||||
"name": "neck",
|
||||
"pivot": [0, 7, -8],
|
||||
"rotation": [-5, 0, 0],
|
||||
"pose": [-5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "neck", "origin": [-5, 2, -18], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "neck", "origin": [-1, 12, -16], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1375,7 +1455,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "neck2",
|
||||
"parent": "neck",
|
||||
"pivot": [0, 7, -18],
|
||||
"rotation": [5, 0, 0],
|
||||
"pose": [5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "neck", "origin": [-5, 2, -28], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "neck", "origin": [-1, 12, -26], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1385,7 +1465,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "neck3",
|
||||
"parent": "neck2",
|
||||
"pivot": [0, 7, -28],
|
||||
"rotation": [5, 0, 0],
|
||||
"pose": [5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "neck", "origin": [-5, 2, -38], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "neck", "origin": [-1, 12, -36], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1395,7 +1475,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "neck4",
|
||||
"parent": "neck3",
|
||||
"pivot": [0, 7, -38],
|
||||
"rotation": [5, 0, 0],
|
||||
"pose": [5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "neck", "origin": [-5, 2, -48], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "neck", "origin": [-1, 12, -46], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1405,7 +1485,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "neck5",
|
||||
"parent": "neck4",
|
||||
"pivot": [0, 7, -48],
|
||||
"rotation": [5, 0, 0],
|
||||
"pose": [5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "neck", "origin": [-5, 2, -58], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "neck", "origin": [-1, 12, -56], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1415,7 +1495,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "head",
|
||||
"parent": "neck5",
|
||||
"pivot": [0, 7, -58],
|
||||
"rotation": [5, 0, 0],
|
||||
"pose": [5, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "head", "origin": [-6, 3, -88], "size": [12, 5, 16], "uv": [176, 44]},
|
||||
{"name": "head", "origin": [-8, -1, -74], "size": [16, 16, 16], "uv": [112, 30]},
|
||||
@ -1429,7 +1509,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "jaw",
|
||||
"parent": "head",
|
||||
"pivot": [0, 3, -71],
|
||||
"rotation": [15, 0, 0],
|
||||
"pose": [15, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "jaw", "origin": [-6, -1, -88], "size": [12, 4, 16], "uv": [176, 65]}
|
||||
]
|
||||
@ -1447,41 +1527,41 @@ skin_presets.enderdragon = `{
|
||||
{
|
||||
"name": "wing",
|
||||
"pivot": [-12, 19, 2],
|
||||
"rotation": [0, 10, 10],
|
||||
"pose": [0, 10, 10],
|
||||
"cubes": [
|
||||
{"name": "wing", "origin": [-68, 15, -2], "size": [56, 8, 8], "uv": [112, 88]},
|
||||
{"name": "wing", "origin": [-68, 19, 4], "size": [56, 0, 56], "uv": [-56, 88]}
|
||||
{"name": "wing", "origin": [-68, 19, 4], "size": [56, 0, 56], "uv": [-56, 88], "inflate": 0.01}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "wingtip",
|
||||
"parent": "wing",
|
||||
"pivot": [-68, 19, 0],
|
||||
"rotation": [0, 0, -20],
|
||||
"pose": [0, 0, -20],
|
||||
"cubes": [
|
||||
{"name": "wingtip", "origin": [-124, 17, 0], "size": [56, 4, 4], "uv": [112, 136]},
|
||||
{"name": "wingtip", "origin": [-124, 19, 4], "size": [56, 0, 56], "uv": [-56, 144]}
|
||||
{"name": "wingtip", "origin": [-124, 19, 4], "size": [56, 0, 56], "uv": [-56, 144], "inflate": 0.01}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "wing1",
|
||||
"pivot": [12, 19, 2],
|
||||
"rotation": [0, -10, -10],
|
||||
"pose": [0, -10, -10],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "wing1", "origin": [12, 15, -2], "size": [56, 8, 8], "uv": [112, 88]},
|
||||
{"name": "wing1", "origin": [12, 19, 4], "size": [56, 0, 56], "uv": [-56, 88]}
|
||||
{"name": "wing1", "origin": [12, 19, 4], "size": [56, 0, 56], "uv": [-56, 88], "inflate": 0.01}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "wingtip1",
|
||||
"parent": "wing1",
|
||||
"pivot": [68, 19, 0],
|
||||
"rotation": [0, 0, 20],
|
||||
"pose": [0, 0, 20],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "wingtip1", "origin": [68, 17, 0], "size": [56, 4, 4], "uv": [112, 136]},
|
||||
{"name": "wingtip1", "origin": [68, 19, 4], "size": [56, 0, 56], "uv": [-56, 144]}
|
||||
{"name": "wingtip1", "origin": [68, 19, 4], "size": [56, 0, 56], "uv": [-56, 144], "inflate": 0.01}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1606,7 +1686,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail2",
|
||||
"parent": "tail",
|
||||
"pivot": [0, 14, 66],
|
||||
"rotation": [1, 0, 0],
|
||||
"pose": [1, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 66], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 68], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1616,7 +1696,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail3",
|
||||
"parent": "tail2",
|
||||
"pivot": [0, 14, 76],
|
||||
"rotation": [1, 0, 0],
|
||||
"pose": [1, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 76], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 78], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1626,7 +1706,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail4",
|
||||
"parent": "tail3",
|
||||
"pivot": [0, 14, 86],
|
||||
"rotation": [1, 0, 0],
|
||||
"pose": [1, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 86], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 88], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1636,7 +1716,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail5",
|
||||
"parent": "tail4",
|
||||
"pivot": [0, 14, 96],
|
||||
"rotation": [2, 0, 0],
|
||||
"pose": [2, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 96], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 98], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1646,7 +1726,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail6",
|
||||
"parent": "tail5",
|
||||
"pivot": [0, 14, 106],
|
||||
"rotation": [3, 0, 0],
|
||||
"pose": [3, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 106], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 108], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1656,7 +1736,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail7",
|
||||
"parent": "tail6",
|
||||
"pivot": [0, 14, 116],
|
||||
"rotation": [3, 0, 0],
|
||||
"pose": [3, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 116], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 118], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1666,7 +1746,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail8",
|
||||
"parent": "tail7",
|
||||
"pivot": [0, 14, 126],
|
||||
"rotation": [1, 0, 0],
|
||||
"pose": [1, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 126], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 128], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1676,7 +1756,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail9",
|
||||
"parent": "tail8",
|
||||
"pivot": [0, 14, 136],
|
||||
"rotation": [-1, 0, 0],
|
||||
"pose": [-1, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 136], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 138], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1686,7 +1766,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail10",
|
||||
"parent": "tail9",
|
||||
"pivot": [0, 14, 146],
|
||||
"rotation": [-2, 0, 0],
|
||||
"pose": [-2, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 146], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 148], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1696,7 +1776,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail11",
|
||||
"parent": "tail10",
|
||||
"pivot": [0, 14, 156],
|
||||
"rotation": [-3, 0, 0],
|
||||
"pose": [-3, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 156], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 158], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -1706,7 +1786,7 @@ skin_presets.enderdragon = `{
|
||||
"name": "tail12",
|
||||
"parent": "tail11",
|
||||
"pivot": [0, 14, 166],
|
||||
"rotation": [-3, 0, 0],
|
||||
"pose": [-3, 0, 0],
|
||||
"cubes": [
|
||||
{"name": "tail", "origin": [-5, 9, 166], "size": [10, 10, 10], "uv": [192, 104]},
|
||||
{"name": "tail", "origin": [-1, 19, 168], "size": [2, 4, 6], "uv": [48, 0]}
|
||||
@ -4310,6 +4390,96 @@ skin_presets.squid = `{
|
||||
}
|
||||
]
|
||||
}`;
|
||||
skin_presets.strider = `{
|
||||
"name": "strider",
|
||||
"texturewidth": 64,
|
||||
"textureheight": 128,
|
||||
"eyes": [
|
||||
[17, 25, 2, 1],
|
||||
[29, 25, 2, 1]
|
||||
],
|
||||
"bones": [
|
||||
{
|
||||
"name": "body",
|
||||
"pivot": [0, 17, 0],
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [-8, 17, -8], "size": [16, 14, 16], "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "right_bristles_1",
|
||||
"parent": "body",
|
||||
"pivot": [-8, 30, 0],
|
||||
"rotation": [0, 0, -60],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [-20, 30, -8], "size": [12, 0, 16], "uv": [4, 33]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "left_bristles_1",
|
||||
"parent": "body",
|
||||
"pivot": [8, 30, 0],
|
||||
"rotation": [0, 0, 60],
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [8, 30, -8], "size": [12, 0, 16], "uv": [4, 33]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "right_bristles_2",
|
||||
"parent": "body",
|
||||
"pivot": [-8, 26, 0],
|
||||
"rotation": [0, 0, -60],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [-20, 26, -8], "size": [12, 0, 16], "uv": [4, 49]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "left_bristles_2",
|
||||
"parent": "body",
|
||||
"pivot": [8, 26, 0],
|
||||
"rotation": [0, 0, 60],
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [8, 26, -8], "size": [12, 0, 16], "uv": [4, 49]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "right_bristles_3",
|
||||
"parent": "body",
|
||||
"pivot": [-8, 21, 0],
|
||||
"rotation": [0, 0, -60],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [-20, 21, -8], "size": [12, 0, 16], "uv": [4, 65]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "left_bristles_3",
|
||||
"parent": "body",
|
||||
"pivot": [8, 21, 0],
|
||||
"rotation": [0, 0, 60],
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [8, 21, -8], "size": [12, 0, 16], "uv": [4, 65]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "right_leg",
|
||||
"pivot": [-4, 17, 0],
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [-6, 0, -2], "size": [4, 17, 4], "uv": [0, 32]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "left_leg",
|
||||
"pivot": [4, 17, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "cube", "origin": [2, 0, -2], "size": [4, 17, 4], "uv": [0, 32]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`;
|
||||
skin_presets.tropicalfish_a = `{
|
||||
"name": "tropicalfish_a",
|
||||
"texturewidth": 32,
|
||||
|
@ -109,7 +109,6 @@ class Cube extends NonGroup {
|
||||
}
|
||||
this.visibility = true;
|
||||
this.autouv = 0
|
||||
this.export = true;
|
||||
this.parent = 'root';
|
||||
|
||||
this.faces = {
|
||||
@ -133,6 +132,7 @@ class Cube extends NonGroup {
|
||||
Merge.number(this, object, 'autouv')
|
||||
Merge.number(this, object, 'color')
|
||||
Merge.boolean(this, object, 'export')
|
||||
Merge.boolean(this, object, 'locked')
|
||||
Merge.boolean(this, object, 'visibility')
|
||||
if (object.from) {
|
||||
Merge.number(this.from, object.from, 0)
|
||||
@ -292,6 +292,7 @@ class Cube extends NonGroup {
|
||||
autouv: this.autouv,
|
||||
color: this.color
|
||||
}
|
||||
el.locked = this.locked;
|
||||
if (!this.visibility) el.visibility = false;
|
||||
if (!this.export) el.export = false;
|
||||
if (!this.shade) el.shade = false;
|
||||
@ -666,40 +667,6 @@ class Cube extends NonGroup {
|
||||
Canvas.updateUV(scope)
|
||||
}
|
||||
}
|
||||
move(val, axis, move_origin) {
|
||||
|
||||
var size = this.size(axis);
|
||||
val+= this.from[axis];
|
||||
var in_box = val;
|
||||
val = limitToBox(limitToBox(val, -this.inflate) + size, this.inflate) - size;
|
||||
in_box = Math.abs(in_box - val) < 1e-4;
|
||||
val -= this.from[axis];
|
||||
|
||||
//Move
|
||||
if (Blockbench.globalMovement && Format.bone_rig && !move_origin) {
|
||||
var m = new THREE.Vector3();
|
||||
m[getAxisLetter(axis)] = val;
|
||||
|
||||
var rotation = new THREE.Quaternion();
|
||||
this.mesh.getWorldQuaternion(rotation);
|
||||
m.applyQuaternion(rotation.inverse());
|
||||
|
||||
this.from.V3_add(m.x, m.y, m.z);
|
||||
this.to.V3_add(m.x, m.y, m.z);
|
||||
|
||||
} else {
|
||||
this.to[axis] += val;
|
||||
this.from[axis] += val;
|
||||
}
|
||||
//Origin
|
||||
if (Blockbench.globalMovement && move_origin) {
|
||||
this.origin[axis] += val;
|
||||
}
|
||||
this.mapAutoUV()
|
||||
Canvas.adaptObjectPosition(this);
|
||||
TickUpdates.selection = true;
|
||||
return in_box;
|
||||
}
|
||||
moveVector(arr, axis) {
|
||||
if (typeof arr == 'number') {
|
||||
var n = arr;
|
||||
@ -734,8 +701,8 @@ class Cube extends NonGroup {
|
||||
|
||||
if (!negative) {
|
||||
var pos = limitToBox(this.from[axis] + modify(before), this.inflate);
|
||||
if (Format.integer_size && Project.box_uv) {
|
||||
pos = Math.round(pos);
|
||||
if (Format.integer_size) {
|
||||
pos = Math.round(pos-this.from[axis])+this.from[axis];
|
||||
}
|
||||
if (pos >= this.from[axis] || settings.negative_size.value || allow_negative) {
|
||||
this.to[axis] = pos;
|
||||
@ -744,6 +711,9 @@ class Cube extends NonGroup {
|
||||
}
|
||||
} else {
|
||||
var pos = limitToBox(this.to[axis] + modify(-before), this.inflate);
|
||||
if (Format.integer_size) {
|
||||
pos = Math.round(pos-this.to[axis])+this.to[axis];
|
||||
}
|
||||
if (pos <= this.to[axis] || settings.negative_size.value || allow_negative) {
|
||||
this.from[axis] = pos;
|
||||
} else {
|
||||
@ -811,8 +781,8 @@ class Cube extends NonGroup {
|
||||
'delete'
|
||||
]);
|
||||
Cube.prototype.buttons = [
|
||||
Outliner.buttons.remove,
|
||||
Outliner.buttons.visibility,
|
||||
Outliner.buttons.locked,
|
||||
Outliner.buttons.export,
|
||||
Outliner.buttons.shading,
|
||||
Outliner.buttons.autouv
|
||||
|
@ -12,6 +12,7 @@ class Group extends OutlinerElement {
|
||||
this.reset = false;
|
||||
this.shade = true;
|
||||
this.selected = false;
|
||||
this.locked = false;
|
||||
this.visibility = true;
|
||||
this.export = true;
|
||||
this.autouv = 0;
|
||||
@ -44,6 +45,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
Merge.number(this, object, 'autouv')
|
||||
Merge.boolean(this, object, 'export')
|
||||
Merge.boolean(this, object, 'locked')
|
||||
Merge.boolean(this, object, 'visibility')
|
||||
return this;
|
||||
}
|
||||
@ -69,7 +71,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
select(event) {
|
||||
var scope = this;
|
||||
if (Blockbench.hasFlag('renaming')) return this;
|
||||
if (Blockbench.hasFlag('renaming') || this.locked) return this;
|
||||
if (!event) event = true
|
||||
var allSelected = Group.selected === this && selected.length && this.matchesSelection()
|
||||
|
||||
@ -223,6 +225,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
showContextMenu(event) {
|
||||
Prop.active_panel = 'outliner'
|
||||
if (this.locked) return this;
|
||||
this.select(event)
|
||||
this.menu.open(event, this)
|
||||
return this;
|
||||
@ -305,6 +308,7 @@ class Group extends OutlinerElement {
|
||||
base_group.rotation.V3_set(this.rotation);
|
||||
base_group.shade = this.shade;
|
||||
base_group.reset = this.reset;
|
||||
base_group.locked = this.locked;
|
||||
base_group.visibility = this.visibility;
|
||||
base_group.export = this.export;
|
||||
base_group.autouv = this.autouv;
|
||||
@ -321,6 +325,7 @@ class Group extends OutlinerElement {
|
||||
obj.uuid = this.uuid;
|
||||
obj.export = this.export;
|
||||
obj.isOpen = this.isOpen === true;
|
||||
obj.locked = this.locked;
|
||||
obj.visibility = this.visibility;
|
||||
obj.autouv = this.autouv;
|
||||
}
|
||||
@ -383,10 +388,10 @@ class Group extends OutlinerElement {
|
||||
Group.prototype.type = 'group';
|
||||
Group.prototype.icon = 'fa fa-folder';
|
||||
Group.prototype.isParent = true;
|
||||
Group.prototype.name_regex = () => Format.bone_rig ? 'a-zA-Z0-9_' : false;
|
||||
Group.prototype.name_regex = () => Format.bone_rig ? 'a-z0-9_' : false;
|
||||
Group.prototype.buttons = [
|
||||
Outliner.buttons.remove,
|
||||
Outliner.buttons.visibility,
|
||||
Outliner.buttons.locked,
|
||||
Outliner.buttons.export,
|
||||
Outliner.buttons.shading,
|
||||
Outliner.buttons.autouv
|
||||
|
@ -4,7 +4,6 @@ class Locator extends NonGroup {
|
||||
super(data, uuid);
|
||||
this.from = new Array().V3_set(0, 0, 0);
|
||||
this.name = 'locator';
|
||||
this.export = true;
|
||||
|
||||
if (data) {
|
||||
this.extend(data);
|
||||
@ -13,6 +12,7 @@ class Locator extends NonGroup {
|
||||
extend(object) {
|
||||
Merge.string(this, object, 'name');
|
||||
this.sanitizeName();
|
||||
Merge.boolean(this, object, 'locked')
|
||||
Merge.boolean(this, object, 'export');
|
||||
Merge.arrayVector(this, object, 'from');
|
||||
return this;
|
||||
@ -28,6 +28,7 @@ class Locator extends NonGroup {
|
||||
var el = {
|
||||
name: this.name,
|
||||
export: this.export ? undefined : false,
|
||||
locked: this.locked,
|
||||
from: this.from,
|
||||
uuid: this.uuid,
|
||||
type: 'locator'
|
||||
@ -61,32 +62,15 @@ class Locator extends NonGroup {
|
||||
|
||||
return pos;
|
||||
}
|
||||
move(val, axis) {
|
||||
|
||||
if (Blockbench.globalMovement) {
|
||||
var m = new THREE.Vector3();
|
||||
m[getAxisLetter(axis)] = val;
|
||||
if (this.parent instanceof Group) {
|
||||
var rotation = new THREE.Quaternion();
|
||||
this.parent.mesh.getWorldQuaternion(rotation);
|
||||
m.applyQuaternion(rotation.inverse());
|
||||
}
|
||||
this.from.V3_add(m);
|
||||
} else {
|
||||
this.from[axis] += val
|
||||
}
|
||||
TickUpdates.selection = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Locator.prototype.title = tl('data.locator');
|
||||
Locator.prototype.type = 'locator';
|
||||
Locator.prototype.icon = 'fa fa-anchor';
|
||||
Locator.prototype.name_regex = 'a-zA-Z0-9_'
|
||||
Locator.prototype.name_regex = 'a-z0-9_'
|
||||
Locator.prototype.movable = true;
|
||||
Locator.prototype.visibility = true;
|
||||
Locator.prototype.buttons = [
|
||||
Outliner.buttons.remove,
|
||||
Outliner.buttons.locked,
|
||||
Outliner.buttons.export
|
||||
];
|
||||
Locator.prototype.needsUniqueName = true;
|
||||
|
@ -4,6 +4,7 @@ const Outliner = {
|
||||
elements: elements,
|
||||
selected: selected,
|
||||
buttons: {
|
||||
/*
|
||||
remove: {
|
||||
id: 'remove',
|
||||
title: tl('generic.delete'),
|
||||
@ -23,6 +24,7 @@ const Outliner = {
|
||||
Undo.finishEdit('remove', {elements: [], outliner: true, selection: true})
|
||||
}
|
||||
},
|
||||
*/
|
||||
visibility: {
|
||||
id: 'visibility',
|
||||
title: tl('switches.visibility'),
|
||||
@ -30,9 +32,22 @@ const Outliner = {
|
||||
icon_off: ' fa fa-eye-slash',
|
||||
advanced_option: false,
|
||||
click: function(obj) {
|
||||
if (obj.locked) return;
|
||||
obj.toggle('visibility')
|
||||
}
|
||||
},
|
||||
locked: {
|
||||
id: 'locked',
|
||||
title: tl('switches.lock'),
|
||||
icon: ' fas fa-lock',
|
||||
icon_off: ' fas fa-lock-open',
|
||||
advanced_option: true,
|
||||
click: function(obj) {
|
||||
if (obj.locked && Format.force_lock) return;
|
||||
obj.toggle('locked')
|
||||
updateSelection()
|
||||
}
|
||||
},
|
||||
export: {
|
||||
id: 'export',
|
||||
title: tl('switches.export'),
|
||||
@ -40,6 +55,7 @@ const Outliner = {
|
||||
icon_off: ' far fa-window-close',
|
||||
advanced_option: true,
|
||||
click: function(obj) {
|
||||
if (obj.locked) return;
|
||||
obj.toggle('export')
|
||||
}
|
||||
},
|
||||
@ -50,8 +66,12 @@ const Outliner = {
|
||||
get icon_off() {return Project.box_uv ? 'fas fa-star-half-alt' : 'far fa-star'},
|
||||
advanced_option: true,
|
||||
click: function(obj) {
|
||||
if (obj.locked) return;
|
||||
obj.toggle('shade')
|
||||
Canvas.updateUVs()
|
||||
if (obj instanceof Cube && obj.visibility && !obj.selected) {
|
||||
Canvas.updateUV(obj);
|
||||
}
|
||||
}
|
||||
},
|
||||
autouv: {
|
||||
@ -62,6 +82,7 @@ const Outliner = {
|
||||
icon_alt: ' fa fa-magic',
|
||||
advanced_option: true,
|
||||
click: function(obj) {
|
||||
if (obj.locked) return;
|
||||
var state = obj.autouv+1
|
||||
if (state > 2) state = 0
|
||||
|
||||
@ -84,6 +105,8 @@ var markerColors = [
|
||||
class OutlinerElement {
|
||||
constructor(uuid) {
|
||||
this.uuid = uuid || guid()
|
||||
this.export = true;
|
||||
this.locked = false;
|
||||
}
|
||||
init() {
|
||||
this.constructor.all.safePush(this);
|
||||
@ -298,6 +321,9 @@ class OutlinerElement {
|
||||
case 'export':
|
||||
return this.export
|
||||
break;
|
||||
case 'locked':
|
||||
return this.locked
|
||||
break;
|
||||
case 'shading':
|
||||
return this.shade
|
||||
break;
|
||||
@ -352,6 +378,7 @@ class NonGroup extends OutlinerElement {
|
||||
}
|
||||
showContextMenu(event) {
|
||||
Prop.active_panel = 'outliner'
|
||||
if (this.locked) return this;
|
||||
if (!this.selected) {
|
||||
this.select()
|
||||
}
|
||||
@ -381,8 +408,8 @@ class NonGroup extends OutlinerElement {
|
||||
if (val === undefined) {
|
||||
var val = !this[key]
|
||||
}
|
||||
this.forSelected((cube) => {
|
||||
cube[key] = val
|
||||
this.forSelected((el) => {
|
||||
el[key] = val
|
||||
}, 'toggle '+key)
|
||||
if (key === 'visibility') {
|
||||
Canvas.updateVisibility()
|
||||
@ -640,13 +667,10 @@ function parseGroups(array, importGroup, startIndex) {
|
||||
}
|
||||
//Outliner
|
||||
function loadOutlinerDraggable() {
|
||||
if (Blockbench.isMobile) {
|
||||
return;
|
||||
}
|
||||
function getOrder(loc, obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
} else if (obj.type === 'group') {
|
||||
} else if (obj instanceof Group) {
|
||||
if (loc < 8) return -1;
|
||||
if (loc > 24) return 1;
|
||||
} else {
|
||||
@ -663,6 +687,12 @@ function loadOutlinerDraggable() {
|
||||
appendTo: 'body',
|
||||
zIndex: 19,
|
||||
cursorAt: {left: 5},
|
||||
start(event, ui) {
|
||||
if (event.target && event.target.parentNode) {
|
||||
var element = Outliner.root.findRecursive('uuid', event.target.parentNode.id)
|
||||
if (!element || element.locked) return false;
|
||||
}
|
||||
},
|
||||
helper: function() {
|
||||
var item = Outliner.root.findRecursive('uuid', $(this).attr('id'))
|
||||
var helper = $(this).clone()
|
||||
@ -682,7 +712,7 @@ function loadOutlinerDraggable() {
|
||||
var tar = $('#cubes_list li .drag_hover.outliner_node').last()
|
||||
var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
|
||||
if (element) {
|
||||
var location = event.clientY - tar.position().top
|
||||
var location = event.clientY - tar.offset().top
|
||||
var order = getOrder(location, element)
|
||||
tar.attr('order', order)
|
||||
}
|
||||
@ -701,7 +731,7 @@ function loadOutlinerDraggable() {
|
||||
addClasses: false,
|
||||
drop: function(event, ui) {
|
||||
$('.outliner_node[order]').attr('order', null)
|
||||
var location = event.clientY - $(event.target).position().top
|
||||
var location = event.clientY - $(event.target).offset().top
|
||||
$('.drag_hover').removeClass('drag_hover')
|
||||
var target = Outliner.root.findRecursive('uuid', $(event.target).attr('id'))
|
||||
|
||||
@ -954,11 +984,11 @@ BARS.defineActions(function() {
|
||||
width: 300,
|
||||
singleButton: true,
|
||||
form: {
|
||||
cubes: {type: 'text', label: tl('dialog.model_stats.cubes'), text: ''+Cube.all.length },
|
||||
locators: {type: 'text', label: tl('dialog.model_stats.locators'), text: ''+Locator.all.length, condition: Format.locators },
|
||||
groups: {type: 'text', label: tl('dialog.model_stats.groups'), text: ''+Group.all.length },
|
||||
vertices: {type: 'text', label: tl('dialog.model_stats.vertices'), text: ''+Cube.all.length*8 },
|
||||
faces: {type: 'text', label: tl('dialog.model_stats.faces'), text: ''+face_count },
|
||||
cubes: {type: 'info', label: tl('dialog.model_stats.cubes'), text: ''+Cube.all.length },
|
||||
locators: {type: 'info', label: tl('dialog.model_stats.locators'), text: ''+Locator.all.length, condition: Format.locators },
|
||||
groups: {type: 'info', label: tl('dialog.model_stats.groups'), text: ''+Group.all.length },
|
||||
vertices: {type: 'info', label: tl('dialog.model_stats.vertices'), text: ''+Cube.all.length*8 },
|
||||
faces: {type: 'info', label: tl('dialog.model_stats.faces'), text: ''+face_count },
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
@ -989,6 +1019,21 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('sort_outliner')
|
||||
}
|
||||
})
|
||||
new Action('unlock_everything', {
|
||||
icon: 'fas.fa-key',
|
||||
category: 'edit',
|
||||
click: function () {
|
||||
let locked = Outliner.elements.filter(el => el.locked);
|
||||
let locked_groups = Group.all.filter(group => group.locked)
|
||||
if (locked.length + locked_groups.length == 0) return;
|
||||
|
||||
Undo.initEdit({outliner: locked_groups.length > 0, elements: locked});
|
||||
[...locked, ...locked_groups].forEach(el => {
|
||||
el.locked = false;
|
||||
})
|
||||
Undo.finishEdit('unlock_everything')
|
||||
}
|
||||
})
|
||||
new Action('element_colors', {
|
||||
icon: 'check_box',
|
||||
category: 'edit',
|
||||
|
@ -6,8 +6,8 @@
|
||||
`<div v-on:contextmenu.prevent.stop="node.showContextMenu($event)"
|
||||
class="outliner_object" v-on:dblclick.stop.self="renameOutliner()"
|
||||
v-on:click="node.select($event, true)" v-on:touchstart="node.select($event)" :title="node.title"
|
||||
v-bind:class="{ cube: node.type === \'cube\', group: node.type === \'group\', selected: node.selected }"
|
||||
v-bind:style="{'padding-left': (node.getDepth ? limitNumber(node.getDepth(), 0, (Interface.Panels.outliner.width-124) / 16) * 16 : 0)+'px'}"
|
||||
v-bind:class="{ cube: node.type === 'cube', group: node.type === 'group', selected: node.selected }"
|
||||
v-bind:style="{'padding-left': getIndentation(node) + 'px'}"
|
||||
>` +
|
||||
//Opener
|
||||
|
||||
@ -16,15 +16,16 @@
|
||||
//Main
|
||||
'<i :class="node.icon + (settings.outliner_colors.value ? \' ec_\'+node.color : \'\')" v-on:dblclick.stop="if (node.children && node.children.length) {node.isOpen = !node.isOpen;}"></i>' +
|
||||
'<input type="text" class="cube_name tab_target" 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}">' +
|
||||
'<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 && (btn.id !== \'locked\' || !node.isIconEnabled(btn))}">' +
|
||||
'<i v-if="node.isIconEnabled(btn) === true" :class="btn.icon"></i>' +
|
||||
'<i v-else-if="node.isIconEnabled(btn) === \'alt\'" :class="btn.icon_alt"></i>' +
|
||||
'<i v-else :class="btn.icon_off"></i>' +
|
||||
'<i v-else :class="[btn.icon_off, \'icon_off\']"></i>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
//Other Entries
|
||||
'<ul v-show="node.isOpen">' +
|
||||
'<vue-tree-item v-for="item in node.children" :node="item" v-key="item.uuid"></vue-tree-item>' +
|
||||
`<div class="outliner_line_guide" v-if="node == Group.selected" v-bind:style="{left: getIndentation(node) + 'px'}"></div>` +
|
||||
'</ul>' +
|
||||
'</li>',
|
||||
props: {
|
||||
@ -51,6 +52,9 @@
|
||||
if (typeof btn.click === 'function') {
|
||||
btn.click(node);
|
||||
}
|
||||
},
|
||||
getIndentation(node) {
|
||||
return node.getDepth ? (limitNumber(node.getDepth(), 0, (Interface.Panels.outliner.width-124) / 16) * 16) : 0;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -14,7 +14,7 @@ const Plugins = {
|
||||
devReload() {
|
||||
var reloads = 0;
|
||||
for (var i = Plugins.all.length-1; i >= 0; i--) {
|
||||
if (Plugins.all[i].fromFile) {
|
||||
if (Plugins.all[i].source == 'file') {
|
||||
Plugins.all[i].reload()
|
||||
reloads++;
|
||||
}
|
||||
@ -28,6 +28,8 @@ const Plugins = {
|
||||
});
|
||||
}
|
||||
}
|
||||
StateMemory.init('installed_plugins', 'array')
|
||||
Plugins.installed = StateMemory.installed_plugins;
|
||||
|
||||
class Plugin {
|
||||
constructor(id, data) {
|
||||
@ -41,6 +43,7 @@ class Plugin {
|
||||
this.icon = '';
|
||||
this.variant = '';
|
||||
this.min_version = '';
|
||||
this.source = 'store'
|
||||
|
||||
this.extend(data)
|
||||
|
||||
@ -79,7 +82,7 @@ class Plugin {
|
||||
scope.uninstall()
|
||||
}
|
||||
})
|
||||
Plugins.installed.safePush(scope.id)
|
||||
this.remember()
|
||||
scope.installed = true;
|
||||
return scope;
|
||||
}
|
||||
@ -127,9 +130,9 @@ class Plugin {
|
||||
localStorage.setItem('plugin_dev_path', file.path)
|
||||
Plugins.all.safePush(this)
|
||||
|
||||
scope.fromFile = true
|
||||
scope.source = 'file'
|
||||
if (isApp) {
|
||||
$.getScript(file.path, function() {
|
||||
$.getScript(file.path, () => {
|
||||
if (window.plugin_data) {
|
||||
scope.id = (plugin_data && plugin_data.id)||pathToName(file.path)
|
||||
scope.extend(plugin_data)
|
||||
@ -137,8 +140,7 @@ class Plugin {
|
||||
}
|
||||
scope.installed = true
|
||||
scope.path = file.path
|
||||
Plugins.installed.safePush(scope.path)
|
||||
saveInstalledPlugins()
|
||||
this.remember()
|
||||
Plugins.sort()
|
||||
})
|
||||
} else {
|
||||
@ -154,14 +156,52 @@ class Plugin {
|
||||
scope.bindGlobalData()
|
||||
}
|
||||
scope.installed = true
|
||||
Plugins.installed.safePush(scope.path)
|
||||
saveInstalledPlugins()
|
||||
this.remember()
|
||||
Plugins.sort()
|
||||
}
|
||||
return this;
|
||||
}
|
||||
loadFromURL(url, first) {
|
||||
if (first) {
|
||||
if (isApp) {
|
||||
if (!confirm(tl('message.load_plugin_app'))) return;
|
||||
} else {
|
||||
if (!confirm(tl('message.load_plugin_web'))) return;
|
||||
}
|
||||
}
|
||||
|
||||
this.id = pathToName(url)
|
||||
Plugins.registered[this.id] = this;
|
||||
localStorage.setItem('plugin_dev_path', url)
|
||||
Plugins.all.safePush(this)
|
||||
|
||||
this.source = 'url';
|
||||
$.getScript(url, () => {
|
||||
if (window.plugin_data) {
|
||||
this.id = (plugin_data && plugin_data.id)||pathToName(url)
|
||||
this.extend(plugin_data)
|
||||
this.bindGlobalData()
|
||||
}
|
||||
this.installed = true
|
||||
this.path = url
|
||||
this.remember()
|
||||
Plugins.sort()
|
||||
})
|
||||
return this;
|
||||
}
|
||||
remember(id = this.id, path = this.path) {
|
||||
if (Plugins.installed.find(plugin => plugin.id == this.id)) {
|
||||
return this;
|
||||
}
|
||||
Plugins.installed.push({
|
||||
id: id,
|
||||
path: path,
|
||||
source: this.source
|
||||
})
|
||||
StateMemory.save('installed_plugins')
|
||||
return this;
|
||||
}
|
||||
uninstall() {
|
||||
var scope = this;
|
||||
try {
|
||||
this.unload();
|
||||
if (this.onuninstall) {
|
||||
@ -171,14 +211,16 @@ class Plugin {
|
||||
console.log('Error in unload or uninstall method: ', err);
|
||||
}
|
||||
delete Plugins.registered[this.id];
|
||||
Plugins.installed.remove(this.fromFile ? this.path : this.id);
|
||||
let in_installed = Plugins.installed.find(plugin => plugin.id == this.id);
|
||||
Plugins.installed.remove(in_installed);
|
||||
StateMemory.save('installed_plugins')
|
||||
this.installed = false;
|
||||
|
||||
if (isApp && this.fromFile) {
|
||||
if (isApp && this.source !== 'store') {
|
||||
Plugins.all.remove(this)
|
||||
|
||||
} else if (isApp) {
|
||||
var filepath = Plugins.path + scope.id + '.js'
|
||||
var filepath = Plugins.path + this.id + '.js'
|
||||
if (fs.existsSync(filepath)) {
|
||||
fs.unlink(filepath, (err) => {
|
||||
if (err) {
|
||||
@ -187,7 +229,7 @@ class Plugin {
|
||||
});
|
||||
}
|
||||
}
|
||||
saveInstalledPlugins()
|
||||
StateMemory.save('installed_plugins')
|
||||
return this;
|
||||
}
|
||||
unload() {
|
||||
@ -197,13 +239,22 @@ class Plugin {
|
||||
return this;
|
||||
}
|
||||
reload() {
|
||||
if (!isApp) return this;
|
||||
if (!isApp && this.source == 'file') return this;
|
||||
|
||||
this.unload()
|
||||
Plugins.all.remove(this)
|
||||
//---------------
|
||||
this.loadFromFile({path: this.path}, false)
|
||||
|
||||
if (this.source == 'file') {
|
||||
this.loadFromFile({path: this.path}, false)
|
||||
|
||||
} else if (this.source == 'url') {
|
||||
this.loadFromURL(this.path, false)
|
||||
}
|
||||
return this;
|
||||
}
|
||||
isReloadable() {
|
||||
return (this.source == 'file' && isApp) || (this.source == 'url')
|
||||
}
|
||||
isInstallable() {
|
||||
var scope = this;
|
||||
var result =
|
||||
@ -281,26 +332,47 @@ function loadInstalledPlugins() {
|
||||
Plugins.loadingStep = true
|
||||
return;
|
||||
}
|
||||
var storage_data = localStorage.getItem('installed_plugins')
|
||||
if (storage_data !== null) {
|
||||
Plugins.installed = JSON.parse(storage_data)
|
||||
if (localStorage.getItem('installed_plugins')) {
|
||||
var legacy_plugins = JSON.parse(localStorage.getItem('installed_plugins'))
|
||||
if (legacy_plugins instanceof Array) {
|
||||
legacy_plugins.forEach((string, i) => {
|
||||
if (typeof string == 'string') {
|
||||
if (string.match(/\.js$/)) {
|
||||
Plugins.installed[i] = {
|
||||
id: string.split(/[\\/]/).last().replace(/\.js$/, ''),
|
||||
path: string,
|
||||
source: 'file'
|
||||
}
|
||||
} else {
|
||||
Plugins.installed[i] = {
|
||||
id: string,
|
||||
source: 'store'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
StateMemory.save('installed_plugins')
|
||||
localStorage.removeItem('installed_plugins')
|
||||
}
|
||||
if (Plugins.json !== undefined) {
|
||||
|
||||
if (Plugins.json instanceof Object) {
|
||||
//From Store
|
||||
for (var id in Plugins.json) {
|
||||
var plugin = new Plugin(id, Plugins.json[id])
|
||||
if (Plugins.installed.includes(id)) {
|
||||
if (Plugins.installed.find(plugin => {
|
||||
return plugin.id == id && plugin.source == 'store'
|
||||
})) {
|
||||
plugin.download()
|
||||
}
|
||||
}
|
||||
Plugins.sort();
|
||||
} else if (Plugins.installed.length > 0 && isApp) {
|
||||
//Offline
|
||||
Plugins.installed.forEach(function(id) {
|
||||
Plugins.installed.forEach(function(plugin) {
|
||||
|
||||
if (id.substr(-3) !== '.js') {
|
||||
//downloaded public plugin
|
||||
var plugin = new Plugin(id).install(false, function() {
|
||||
if (plugin.source == 'store') {
|
||||
var plugin = new Plugin(plugin.id).install(false, function() {
|
||||
this.extend(window.plugin_data)
|
||||
Plugins.sort()
|
||||
})
|
||||
@ -309,22 +381,28 @@ function loadInstalledPlugins() {
|
||||
}
|
||||
if (Plugins.installed.length > 0) {
|
||||
var loaded = []
|
||||
Plugins.installed.forEach(function(id) {
|
||||
Plugins.installed.forEachReverse(function(plugin) {
|
||||
|
||||
if (id && id.substr(-3) === '.js') {
|
||||
if (plugin.source == 'file') {
|
||||
//Dev Plugins
|
||||
if (isApp && fs.existsSync(id)) {
|
||||
var plugin = new Plugin(id).loadFromFile({path: id}, false)
|
||||
loaded.push(pathToName(id))
|
||||
if (isApp && fs.existsSync(plugin.path)) {
|
||||
var plugin = new Plugin(plugin.id).loadFromFile({path: plugin.path}, false)
|
||||
loaded.push('Local: '+ plugin.id || plugin.path)
|
||||
} else {
|
||||
Plugins.installed.remove(id)
|
||||
Plugins.installed.remove(plugin)
|
||||
}
|
||||
} else if (id) {
|
||||
loaded.push(id)
|
||||
|
||||
} else if (plugin.source == 'url') {
|
||||
var plugin = new Plugin(plugin.id).loadFromFile({path: plugin.path}, false)
|
||||
loaded.push('URL: '+ plugin.id || plugin.path)
|
||||
|
||||
} else {
|
||||
loaded.push('Store: '+ plugin.id)
|
||||
}
|
||||
})
|
||||
console.log(`Loaded ${loaded.length} plugin${pluralS(loaded.length)}`, loaded)
|
||||
}
|
||||
StateMemory.save('installed_plugins')
|
||||
|
||||
Plugins.Vue = new Vue({
|
||||
el: '#plugin_list',
|
||||
@ -353,12 +431,6 @@ function loadInstalledPlugins() {
|
||||
}
|
||||
})
|
||||
}
|
||||
function saveInstalledPlugins() {
|
||||
localStorage.setItem('installed_plugins', JSON.stringify(Plugins.installed))
|
||||
}
|
||||
function loadPluginFromFile(file) {
|
||||
var plugin = new Plugin().loadFromFile(file, true)
|
||||
}
|
||||
function switchPluginTabs(installed) {
|
||||
$('#plugins .tab_bar > .open').removeClass('open')
|
||||
if (installed) {
|
||||
@ -391,13 +463,21 @@ BARS.defineActions(function() {
|
||||
icon: 'fa-file-code',
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
var startpath = localStorage.getItem('plugin_dev_path') || undefined;
|
||||
Blockbench.import({
|
||||
resource_id: 'dev_plugin',
|
||||
extensions: ['js'],
|
||||
type: 'Blockbench Plugin',
|
||||
startpath
|
||||
}, function(files) {
|
||||
loadPluginFromFile(files[0])
|
||||
new Plugin().loadFromFile(files[0], true)
|
||||
})
|
||||
}
|
||||
})
|
||||
new Action('load_plugin_from_url', {
|
||||
icon: 'cloud_download',
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
Blockbench.textPrompt('URL', '', url => {
|
||||
new Plugin().loadFromURL(url, true)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -489,10 +489,64 @@ const Canvas = {
|
||||
}
|
||||
iterate(el, elmesh)
|
||||
},
|
||||
getLayeredMaterial() {
|
||||
var vertShader = `
|
||||
varying vec2 vUv;
|
||||
|
||||
void main()
|
||||
{
|
||||
vUv = uv;
|
||||
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}`
|
||||
var fragShader = `
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform sampler2D tOne;
|
||||
uniform sampler2D tSec;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 c;
|
||||
vec4 Ca = texture2D(tOne, vUv);
|
||||
vec4 Cb = texture2D(tSec, vUv);
|
||||
c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a); // blending equation
|
||||
gl_FragColor= vec4(c, 1.0);
|
||||
}`
|
||||
|
||||
var uniforms = {
|
||||
tOne: { type: "t", value: textures[1].getMaterial().map },
|
||||
tSec: { type: "t", value: textures[0].getMaterial().map }
|
||||
};
|
||||
|
||||
var material_shh = new THREE.ShaderMaterial({
|
||||
uniforms: uniforms,
|
||||
vertexShader: vertShader,
|
||||
fragmentShader: fragShader
|
||||
});
|
||||
return material_shh;
|
||||
/*
|
||||
todo:
|
||||
Issues:
|
||||
Painting is one pixel delayed
|
||||
Painting doesn't occur on selected texture
|
||||
needs setting
|
||||
needs to work with 0-3+ textures
|
||||
*/
|
||||
},
|
||||
adaptObjectFaces(cube, mesh) {
|
||||
if (!mesh) mesh = cube.mesh
|
||||
if (!mesh) return;
|
||||
if (!Prop.wireframe) {
|
||||
if (Prop.wireframe) {
|
||||
mesh.material = Canvas.wireframeMaterial
|
||||
/*} else if (settings.layered_textures.value && Format && Format.id.includes('bedrock')) {
|
||||
mesh.material = Canvas.getLayeredMaterial();*/
|
||||
|
||||
} else {
|
||||
var materials = []
|
||||
Canvas.face_order.forEach(function(face) {
|
||||
|
||||
@ -509,8 +563,6 @@ const Canvas = {
|
||||
}
|
||||
})
|
||||
mesh.material = materials
|
||||
} else {
|
||||
mesh.material = Canvas.wireframeMaterial
|
||||
}
|
||||
},
|
||||
updateUV(obj, animation) {
|
||||
|
@ -86,6 +86,22 @@ const DefaultCameraPresets = [
|
||||
zoom: 0.5,
|
||||
locked_angle: 5,
|
||||
default: true
|
||||
},
|
||||
{
|
||||
name: 'camera_angle.isometric_right',
|
||||
projection: 'orthographic',
|
||||
position: [-64, 64*0.8165, -64],
|
||||
target: [0, 0, 0],
|
||||
zoom: 0.5,
|
||||
default: true
|
||||
},
|
||||
{
|
||||
name: 'camera_angle.isometric_left',
|
||||
projection: 'orthographic',
|
||||
position: [64, 64*0.8165, -64],
|
||||
target: [0, 0, 0],
|
||||
zoom: 0.5,
|
||||
default: true
|
||||
}
|
||||
]
|
||||
|
||||
@ -155,12 +171,30 @@ class Preview {
|
||||
this.controls.mouseButtons.ZOOM = undefined;
|
||||
|
||||
//Renderer
|
||||
this.renderer = new THREE.WebGLRenderer({
|
||||
canvas: this.canvas,
|
||||
antialias: true,
|
||||
alpha: true,
|
||||
preserveDrawingBuffer: true
|
||||
});
|
||||
try {
|
||||
this.renderer = new THREE.WebGLRenderer({
|
||||
canvas: this.canvas,
|
||||
antialias: true,
|
||||
alpha: true,
|
||||
preserveDrawingBuffer: true
|
||||
});
|
||||
} catch (err) {
|
||||
document.querySelector('#loading_error_detail').innerHTML = 'Error creating WebGL context. Try to update your graphics drivers.';
|
||||
if (isApp) {
|
||||
var {BrowserWindow} = require('electron').remote
|
||||
new BrowserWindow({
|
||||
icon:'icon.ico',
|
||||
backgroundColor: '#ffffff',
|
||||
title: 'Blockbench GPU Information',
|
||||
webPreferences: {
|
||||
webgl: true,
|
||||
webSecurity: true,
|
||||
nodeIntegration: true
|
||||
}
|
||||
}).loadURL('chrome://gpu')
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
this.renderer.setClearColor( 0x000000, 0 )
|
||||
this.renderer.setSize(500, 400);
|
||||
|
||||
@ -243,7 +277,18 @@ class Preview {
|
||||
}
|
||||
var intersects = this.raycaster.intersectObjects( objects );
|
||||
if (intersects.length > 0) {
|
||||
var intersect = intersects[0].object
|
||||
if (intersects.length > 1 && Toolbox.selected.id == 'vertex_snap_tool') {
|
||||
var intersect;
|
||||
for (var sct of intersects) {
|
||||
if (sct.object.isVertex) {
|
||||
intersect = sct.object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!intersect) intersect = intersects[0].object;
|
||||
} else {
|
||||
var intersect = intersects[0].object
|
||||
}
|
||||
if (intersect.isElement) {
|
||||
this.controls.hasMoved = true
|
||||
var obj = elements.findInArray('uuid', intersects[0].object.name)
|
||||
@ -400,6 +445,14 @@ class Preview {
|
||||
}
|
||||
newAnglePreset() {
|
||||
let scope = this;
|
||||
let position = scope.camera.position.toArray();
|
||||
let target = scope.controls.target.toArray();
|
||||
position.forEach((v, i) => {
|
||||
position[i] = Math.round(v*100)/100
|
||||
})
|
||||
target.forEach((v, i) => {
|
||||
target[i] = Math.round(v*100)/100
|
||||
})
|
||||
|
||||
let dialog = new Dialog({
|
||||
id: 'save_angle',
|
||||
@ -411,7 +464,9 @@ class Preview {
|
||||
unset: 'generic.unset',
|
||||
perspective: 'dialog.save_angle.projection.perspective',
|
||||
orthographic: 'dialog.save_angle.projection.orthographic'
|
||||
}}
|
||||
}},
|
||||
position: {label: 'dialog.save_angle.position', type: 'vector', dimensions: 3, value: position},
|
||||
target: {label: 'dialog.save_angle.target', type: 'vector', dimensions: 3, value: target},
|
||||
},
|
||||
onConfirm: function(formResult) {
|
||||
|
||||
@ -420,8 +475,8 @@ class Preview {
|
||||
let preset = {
|
||||
name: formResult.name,
|
||||
projection: formResult.projection,
|
||||
position: scope.camera.position.toArray(),
|
||||
target: scope.controls.target.toArray(),
|
||||
position: formResult.position,
|
||||
target: formResult.target,
|
||||
}
|
||||
if (this.isOrtho) preset.zoom = this.camOrtho.zoom;
|
||||
|
||||
@ -488,7 +543,15 @@ class Preview {
|
||||
var data = this.raycast(event);
|
||||
if (data) {
|
||||
//this.static_rclick = false
|
||||
if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data.type === 'cube') {
|
||||
if (data.cube && data.cube.locked) {
|
||||
$('#preview').css('cursor', 'not-allowed')
|
||||
function resetCursor() {
|
||||
$('#preview').css('cursor', (Toolbox.selected.cursor ? Toolbox.selected.cursor : 'default'))
|
||||
removeEventListeners(document, 'mouseup touchend', resetCursor, false)
|
||||
}
|
||||
addEventListeners(document, 'mouseup touchend', resetCursor, false)
|
||||
|
||||
} else if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data.type === 'cube') {
|
||||
if (Toolbox.selected.selectFace) {
|
||||
main_uv.setFace(data.face, false)
|
||||
}
|
||||
@ -524,8 +587,10 @@ class Preview {
|
||||
}
|
||||
}
|
||||
mousemove(event) {
|
||||
var data = this.raycast(event);
|
||||
if (Settings.get('highlight_cubes')) updateCubeHighlights(data && data.cube);
|
||||
if (Settings.get('highlight_cubes')) {
|
||||
var data = this.raycast(event);
|
||||
updateCubeHighlights(data && data.cube);
|
||||
}
|
||||
}
|
||||
raycastMouseCoords(x,y) {
|
||||
var scope = this;
|
||||
@ -888,6 +953,7 @@ class Preview {
|
||||
return [
|
||||
{icon: 'folder', name: 'menu.preview.background.load', click: function(preview) {
|
||||
Blockbench.import({
|
||||
resource_id: 'preview_background',
|
||||
extensions: ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'tif', 'gif'],
|
||||
type: 'Image',
|
||||
readtype: 'image'
|
||||
@ -1044,13 +1110,23 @@ const Screencam = {
|
||||
cancel: 0
|
||||
}, function(result) {
|
||||
if (result === 1) {
|
||||
Blockbench.export()
|
||||
ElecDialogs.showSaveDialog(currentwindow, {filters: [ {name: tl('data.image'), extensions: [is_gif ? 'gif' : 'png']} ]}, function (fileName) {
|
||||
if (fileName === undefined) {
|
||||
return;
|
||||
}
|
||||
fs.writeFile(fileName, Buffer(dataUrl.split(',')[1], 'base64'), err => {})
|
||||
})
|
||||
if (is_gif) {
|
||||
Blockbench.export({
|
||||
resource_id: 'screenshot',
|
||||
extensions: ['gif'],
|
||||
type: tl('data.image'),
|
||||
savetype: 'binary',
|
||||
content: Buffer(dataUrl.split(',')[1], 'base64')
|
||||
})
|
||||
} else {
|
||||
Blockbench.export({
|
||||
resource_id: 'screenshot',
|
||||
extensions: ['png'],
|
||||
type: tl('data.image'),
|
||||
savetype: 'image',
|
||||
content: dataUrl
|
||||
})
|
||||
}
|
||||
} else if (result === 2) {
|
||||
clipboard.writeImage(screenshot)
|
||||
}
|
||||
@ -1318,7 +1394,7 @@ function initCanvas() {
|
||||
Sun = new THREE.AmbientLight( 0xffffff );
|
||||
Sun.name = 'sun'
|
||||
scene.add(Sun);
|
||||
Sun.intensity = 0.44
|
||||
Sun.intensity = 0.5
|
||||
|
||||
lights = new THREE.Object3D()
|
||||
lights.name = 'lights'
|
||||
@ -1328,7 +1404,14 @@ function initCanvas() {
|
||||
light_top.position.set(8, 100, 8)
|
||||
lights.add(light_top);
|
||||
|
||||
light_top.intensity = 0.66
|
||||
light_top.intensity = 0.45
|
||||
|
||||
var light_bottom = new THREE.DirectionalLight();
|
||||
light_bottom.name = 'light_bottom'
|
||||
light_bottom.position.set(8, 100, 8)
|
||||
lights.add(light_bottom);
|
||||
|
||||
light_bottom.intensity = 0.11
|
||||
|
||||
var light_north = new THREE.DirectionalLight();
|
||||
light_north.name = 'light_north'
|
||||
@ -1340,7 +1423,7 @@ function initCanvas() {
|
||||
light_south.position.set(8, 8, 100)
|
||||
lights.add(light_south);
|
||||
|
||||
light_north.intensity = light_south.intensity = 0.44
|
||||
light_north.intensity = light_south.intensity = 0.33
|
||||
|
||||
var light_west = new THREE.DirectionalLight();
|
||||
light_west.name = 'light_west'
|
||||
@ -1491,7 +1574,6 @@ function buildGrid() {
|
||||
three_grid.add(line)
|
||||
}
|
||||
//Axis Lines
|
||||
if (settings.base_grid.value || settings.full_grid.value)
|
||||
if (Format.centered_grid || !settings.full_grid.value) {
|
||||
var length = Format.centered_grid
|
||||
? (settings.full_grid.value ? 24 : 8)
|
||||
@ -1508,7 +1590,8 @@ function buildGrid() {
|
||||
|
||||
if (settings.full_grid.value === true) {
|
||||
//Grid
|
||||
var grid = new THREE.GridHelper(48, 48/canvasGridSize(), gizmo_colors.grid)
|
||||
let size = settings.large_grid_size.value*16;
|
||||
var grid = new THREE.GridHelper(size, size/canvasGridSize(), gizmo_colors.grid)
|
||||
if (Format.centered_grid) {
|
||||
grid.position.set(0,0,0)
|
||||
} else {
|
||||
@ -1522,9 +1605,9 @@ function buildGrid() {
|
||||
geometry = new THREE.PlaneGeometry(5, 5)
|
||||
var north_mark = new THREE.Mesh(geometry, Canvas.northMarkMaterial)
|
||||
if (Format.centered_grid) {
|
||||
north_mark.position.set(0,0,-27)
|
||||
north_mark.position.set(0,0, -3 - size/2)
|
||||
} else {
|
||||
north_mark.position.set(8,0,-19)
|
||||
north_mark.position.set(8, 0, 5 - size/2)
|
||||
}
|
||||
north_mark.rotation.x = Math.PI / -2
|
||||
three_grid.add(north_mark)
|
||||
@ -1532,7 +1615,8 @@ function buildGrid() {
|
||||
} else {
|
||||
if (settings.large_grid.value === true) {
|
||||
//Grid
|
||||
var grid = new THREE.GridHelper(48, 3, gizmo_colors.grid)
|
||||
let size = settings.large_grid_size.value
|
||||
var grid = new THREE.GridHelper(size*16, size, gizmo_colors.grid)
|
||||
if (Format.centered_grid) {
|
||||
grid.position.set(0,0,0)
|
||||
} else {
|
||||
|
@ -917,7 +917,7 @@
|
||||
Transformer.rotation_ref = rotation_object.mesh.parent;
|
||||
|
||||
} else if (space === 2 || Toolbox.selected.id == 'resize_tool') {
|
||||
Transformer.rotation_ref = selected[0].mesh;
|
||||
Transformer.rotation_ref = selected[0] && selected[0].mesh;
|
||||
|
||||
} else if (space instanceof Group) {
|
||||
Transformer.rotation_ref = space.mesh;
|
||||
@ -1273,19 +1273,6 @@
|
||||
|
||||
moveElementsInSpace(difference, axisNumber)
|
||||
|
||||
|
||||
/*
|
||||
if (_has_groups && Blockbench.globalMovement) {
|
||||
Group.selected.forEachChild(g => {
|
||||
g.origin[axisNumber] += difference
|
||||
}, Group, true)
|
||||
}
|
||||
selected.forEach(function(obj, i) {
|
||||
if (obj.movable) {
|
||||
obj.move(difference, axisNumber, _has_groups||!Format.bone_rig)
|
||||
}
|
||||
})
|
||||
*/
|
||||
scope.updateSelection()
|
||||
}
|
||||
previousValue = point[axis]
|
||||
|
@ -5,310 +5,46 @@ function colorDistance(color1, color2) {
|
||||
Math.pow(color2._b - color1._b, 2)
|
||||
);
|
||||
}
|
||||
|
||||
onVueSetup(() => {
|
||||
(function() {
|
||||
var palettes = {
|
||||
default: [
|
||||
'#1a1a1b',
|
||||
'#353637',
|
||||
'#464849',
|
||||
'#5d5f60',
|
||||
'#757677',
|
||||
'#868788',
|
||||
'#979b9d',
|
||||
'#b8bdbe',
|
||||
'#dadedf',
|
||||
'#ffffff',
|
||||
'#9a080f',
|
||||
'#b40a1a',
|
||||
'#d21129',
|
||||
'#ef2142',
|
||||
'#ff5774',
|
||||
'#bb7907',
|
||||
'#cc9104',
|
||||
'#edb508',
|
||||
'#fcd720',
|
||||
'#fef364',
|
||||
'#0d7e36',
|
||||
'#12933d',
|
||||
'#11aa38',
|
||||
'#1cc93d',
|
||||
'#29e64d',
|
||||
'#044b8f',
|
||||
'#0955a8',
|
||||
'#126bc3',
|
||||
'#1782db',
|
||||
'#339afc',
|
||||
'#cd3e00',
|
||||
'#e65b00',
|
||||
'#f37800',
|
||||
'#f89520',
|
||||
'#fdaf40',
|
||||
'#02a8c1',
|
||||
'#0cc3ca',
|
||||
'#17d1c7',
|
||||
'#38debd',
|
||||
'#5be9b7',
|
||||
'#1a1a1b','#353637','#464849','#5d5f60','#757677','#868788','#979b9d','#b8bdbe','#dadedf','#ffffff',
|
||||
'#9a080f','#b40a1a','#d21129','#ef2142','#ff5774','#bb7907','#cc9104','#edb508','#fcd720','#fef364',
|
||||
'#0d7e36','#12933d','#11aa38','#1cc93d','#29e64d','#044b8f','#0955a8','#126bc3','#1782db','#339afc',
|
||||
'#cd3e00','#e65b00','#f37800','#f89520','#fdaf40','#02a8c1','#0cc3ca','#17d1c7','#38debd','#5be9b7',
|
||||
],
|
||||
material: [
|
||||
'#FFEBEE',
|
||||
'#FFCDD2',
|
||||
'#EF9A9A',
|
||||
'#E57373',
|
||||
'#EF5350',
|
||||
'#F44336',
|
||||
'#E53935',
|
||||
'#D32F2F',
|
||||
'#C62828',
|
||||
'#B71C1C',
|
||||
'#FCE4EC',
|
||||
'#F8BBD0',
|
||||
'#F48FB1',
|
||||
'#F06292',
|
||||
'#EC407A',
|
||||
'#E91E63',
|
||||
'#D81B60',
|
||||
'#C2185B',
|
||||
'#AD1457',
|
||||
'#880E4F',
|
||||
'#F3E5F5',
|
||||
'#E1BEE7',
|
||||
'#CE93D8',
|
||||
'#BA68C8',
|
||||
'#AB47BC',
|
||||
'#9C27B0',
|
||||
'#8E24AA',
|
||||
'#7B1FA2',
|
||||
'#6A1B9A',
|
||||
'#4A148C',
|
||||
'#EDE7F6',
|
||||
'#D1C4E9',
|
||||
'#B39DDB',
|
||||
'#9575CD',
|
||||
'#7E57C2',
|
||||
'#673AB7',
|
||||
'#5E35B1',
|
||||
'#512DA8',
|
||||
'#4527A0',
|
||||
'#311B92',
|
||||
'#E8EAF6',
|
||||
'#C5CAE9',
|
||||
'#9FA8DA',
|
||||
'#7986CB',
|
||||
'#5C6BC0',
|
||||
'#3F51B5',
|
||||
'#3949AB',
|
||||
'#303F9F',
|
||||
'#283593',
|
||||
'#1A237E',
|
||||
'#E3F2FD',
|
||||
'#BBDEFB',
|
||||
'#90CAF9',
|
||||
'#64B5F6',
|
||||
'#42A5F5',
|
||||
'#2196F3',
|
||||
'#1E88E5',
|
||||
'#1976D2',
|
||||
'#1565C0',
|
||||
'#0D47A1',
|
||||
'#E1F5FE',
|
||||
'#B3E5FC',
|
||||
'#81D4FA',
|
||||
'#4FC3F7',
|
||||
'#29B6F6',
|
||||
'#03A9F4',
|
||||
'#039BE5',
|
||||
'#0288D1',
|
||||
'#0277BD',
|
||||
'#01579B',
|
||||
'#E0F7FA',
|
||||
'#B2EBF2',
|
||||
'#80DEEA',
|
||||
'#4DD0E1',
|
||||
'#26C6DA',
|
||||
'#00BCD4',
|
||||
'#00ACC1',
|
||||
'#0097A7',
|
||||
'#00838F',
|
||||
'#006064',
|
||||
'#E0F2F1',
|
||||
'#B2DFDB',
|
||||
'#80CBC4',
|
||||
'#4DB6AC',
|
||||
'#26A69A',
|
||||
'#009688',
|
||||
'#00897B',
|
||||
'#00796B',
|
||||
'#00695C',
|
||||
'#004D40',
|
||||
'#E8F5E9',
|
||||
'#C8E6C9',
|
||||
'#A5D6A7',
|
||||
'#81C784',
|
||||
'#66BB6A',
|
||||
'#4CAF50',
|
||||
'#43A047',
|
||||
'#388E3C',
|
||||
'#2E7D32',
|
||||
'#1B5E20',
|
||||
'#F1F8E9',
|
||||
'#DCEDC8',
|
||||
'#C5E1A5',
|
||||
'#AED581',
|
||||
'#9CCC65',
|
||||
'#8BC34A',
|
||||
'#7CB342',
|
||||
'#689F38',
|
||||
'#558B2F',
|
||||
'#33691E',
|
||||
'#F9FBE7',
|
||||
'#F0F4C3',
|
||||
'#E6EE9C',
|
||||
'#DCE775',
|
||||
'#D4E157',
|
||||
'#CDDC39',
|
||||
'#C0CA33',
|
||||
'#AFB42B',
|
||||
'#9E9D24',
|
||||
'#827717',
|
||||
'#FFFDE7',
|
||||
'#FFF9C4',
|
||||
'#FFF59D',
|
||||
'#FFF176',
|
||||
'#FFEE58',
|
||||
'#FFEB3B',
|
||||
'#FDD835',
|
||||
'#FBC02D',
|
||||
'#F9A825',
|
||||
'#F57F17',
|
||||
'#FFF8E1',
|
||||
'#FFECB3',
|
||||
'#FFE082',
|
||||
'#FFD54F',
|
||||
'#FFCA28',
|
||||
'#FFC107',
|
||||
'#FFB300',
|
||||
'#FFA000',
|
||||
'#FF8F00',
|
||||
'#FF6F00',
|
||||
'#FFF3E0',
|
||||
'#FFE0B2',
|
||||
'#FFCC80',
|
||||
'#FFB74D',
|
||||
'#FFA726',
|
||||
'#FF9800',
|
||||
'#FB8C00',
|
||||
'#F57C00',
|
||||
'#EF6C00',
|
||||
'#E65100',
|
||||
'#FBE9E7',
|
||||
'#FFCCBC',
|
||||
'#FFAB91',
|
||||
'#FF8A65',
|
||||
'#FF7043',
|
||||
'#FF5722',
|
||||
'#F4511E',
|
||||
'#E64A19',
|
||||
'#D84315',
|
||||
'#BF360C',
|
||||
'#EFEBE9',
|
||||
'#D7CCC8',
|
||||
'#BCAAA4',
|
||||
'#A1887F',
|
||||
'#8D6E63',
|
||||
'#795548',
|
||||
'#6D4C41',
|
||||
'#5D4037',
|
||||
'#4E342E',
|
||||
'#3E2723',
|
||||
'#FAFAFA',
|
||||
'#F5F5F5',
|
||||
'#EEEEEE',
|
||||
'#E0E0E0',
|
||||
'#BDBDBD',
|
||||
'#9E9E9E',
|
||||
'#757575',
|
||||
'#616161',
|
||||
'#424242',
|
||||
'#212121',
|
||||
'#ECEFF1',
|
||||
'#CFD8DC',
|
||||
'#B0BEC5',
|
||||
'#90A4AE',
|
||||
'#78909C',
|
||||
'#607D8B',
|
||||
'#546E7A',
|
||||
'#455A64',
|
||||
'#37474F',
|
||||
'#263238',
|
||||
'#ffebee','#ffcdd2','#ef9a9a','#e57373','#ef5350','#f44336','#e53935','#d32f2f','#c62828','#b71c1c','#ff5252','#ff1744',
|
||||
'#fce4ec','#f8bbd0','#f48fb1','#f06292','#ec407a','#e91e63','#d81b60','#c2185b','#ad1457','#880e4f','#ff4081','#f50057',
|
||||
'#f3e5f5','#e1bee7','#ce93d8','#ba68c8','#ab47bc','#9c27b0','#8e24aa','#7b1fa2','#6a1b9a','#4a148c','#e040fb','#d500f9',
|
||||
'#ede7f6','#d1c4e9','#b39ddb','#9575cd','#7e57c2','#673ab7','#5e35b1','#512da8','#4527a0','#311b92','#7c4dff','#651fff',
|
||||
'#e8eaf6','#c5cae9','#9fa8da','#7986cb','#5c6bc0','#3f51b5','#3949ab','#303f9f','#283593','#1a237e','#536dfe','#3d5afe',
|
||||
'#e3f2fd','#bbdefb','#90caf9','#64b5f6','#42a5f5','#2196f3','#1e88e5','#1976d2','#1565c0','#0d47a1','#448aff','#2979ff',
|
||||
'#e1f5fe','#b3e5fc','#81d4fa','#4fc3f7','#29b6f6','#03a9f4','#039be5','#0288d1','#0277bd','#01579b','#40c4ff','#00b0ff',
|
||||
'#e0f7fa','#b2ebf2','#80deea','#4dd0e1','#26c6da','#00bcd4','#00acc1','#0097a7','#00838f','#006064','#18ffff','#00e5ff',
|
||||
'#e0f2f1','#b2dfdb','#80cbc4','#4db6ac','#26a69a','#009688','#00897b','#00796b','#00695c','#004d40','#64ffda','#1de9b6',
|
||||
'#e8f5e9','#c8e6c9','#a5d6a7','#81c784','#66bb6a','#4caf50','#43a047','#388e3c','#2e7d32','#1b5e20','#69f0ae','#00e676',
|
||||
'#f1f8e9','#dcedc8','#c5e1a5','#aed581','#9ccc65','#8bc34a','#7cb342','#689f38','#558b2f','#33691e','#b2ff59','#76ff03',
|
||||
'#f9fbe7','#f0f4c3','#e6ee9c','#dce775','#d4e157','#cddc39','#c0ca33','#afb42b','#9e9d24','#827717','#eeff41','#c6ff00',
|
||||
'#fffde7','#fff9c4','#fff59d','#fff176','#ffee58','#ffeb3b','#fdd835','#fbc02d','#f9a825','#f57f17','#ffff00','#ffea00',
|
||||
'#fff8e1','#ffecb3','#ffe082','#ffd54f','#ffca28','#ffc107','#ffb300','#ffa000','#ff8f00','#ff6f00','#ffd740','#ffc400',
|
||||
'#fff3e0','#ffe0b2','#ffcc80','#ffb74d','#ffa726','#ff9800','#fb8c00','#f57c00','#ef6c00','#e65100','#ffab40','#ff9100',
|
||||
'#fbe9e7','#ffccbc','#ffab91','#ff8a65','#ff7043','#ff5722','#f4511e','#e64a19','#d84315','#bf360c','#ff6e40','#ff3d00',
|
||||
'#efebe9','#d7ccc8','#bcaaa4','#a1887f','#8d6e63','#795548','#6d4c41','#5d4037','#4e342e','#3e2723','#6d422d','#593022',
|
||||
'#fafafa','#f5f5f5','#eeeeee','#e0e0e0','#bdbdbd','#9e9e9e','#757575','#616161','#424242','#212121','#ffffff','#000000',
|
||||
'#eceff1','#cfd8dc','#b0bec5','#90a4ae','#78909c','#607d8b','#546e7a','#455a64','#37474f','#263238',
|
||||
],
|
||||
endesga64: [
|
||||
'#ff0040',
|
||||
'#131313',
|
||||
'#1b1b1b',
|
||||
'#272727',
|
||||
'#3d3d3d',
|
||||
'#5d5d5d',
|
||||
'#858585',
|
||||
'#b4b4b4',
|
||||
'#ffffff',
|
||||
'#c7cfdd',
|
||||
'#92a1b9',
|
||||
'#657392',
|
||||
'#424c6e',
|
||||
'#2a2f4e',
|
||||
'#1a1932',
|
||||
'#0e071b',
|
||||
'#1c121c',
|
||||
'#391f21',
|
||||
'#5d2c28',
|
||||
'#8a4836',
|
||||
'#bf6f4a',
|
||||
'#e69c69',
|
||||
'#f6ca9f',
|
||||
'#f9e6cf',
|
||||
'#edab50',
|
||||
'#e07438',
|
||||
'#c64524',
|
||||
'#8e251d',
|
||||
'#ff5000',
|
||||
'#ed7614',
|
||||
'#ffa214',
|
||||
'#ffc825',
|
||||
'#ffeb57',
|
||||
'#d3fc7e',
|
||||
'#99e65f',
|
||||
'#5ac54f',
|
||||
'#33984b',
|
||||
'#1e6f50',
|
||||
'#134c4c',
|
||||
'#0c2e44',
|
||||
'#00396d',
|
||||
'#0069aa',
|
||||
'#0098dc',
|
||||
'#00cdf9',
|
||||
'#0cf1ff',
|
||||
'#94fdff',
|
||||
'#fdd2ed',
|
||||
'#f389f5',
|
||||
'#db3ffd',
|
||||
'#7a09fa',
|
||||
'#3003d9',
|
||||
'#0c0293',
|
||||
'#03193f',
|
||||
'#3b1443',
|
||||
'#622461',
|
||||
'#93388f',
|
||||
'#ca52c9',
|
||||
'#c85086',
|
||||
'#f68187',
|
||||
'#f5555d',
|
||||
'#ea323c',
|
||||
'#c42430',
|
||||
'#891e2b',
|
||||
'#571c27',
|
||||
'#ff0040','#131313','#1b1b1b','#272727','#3d3d3d','#5d5d5d','#858585','#b4b4b4','#ffffff','#c7cfdd',
|
||||
'#92a1b9','#657392','#424c6e','#2a2f4e','#1a1932','#0e071b','#1c121c','#391f21','#5d2c28','#8a4836',
|
||||
'#bf6f4a','#e69c69','#f6ca9f','#f9e6cf','#edab50','#e07438','#c64524','#8e251d','#ff5000','#ed7614',
|
||||
'#ffa214','#ffc825','#ffeb57','#d3fc7e','#99e65f','#5ac54f','#33984b','#1e6f50','#134c4c','#0c2e44',
|
||||
'#00396d','#0069aa','#0098dc','#00cdf9','#0cf1ff','#94fdff','#fdd2ed','#f389f5','#db3ffd','#7a09fa',
|
||||
'#3003d9','#0c0293','#03193f','#3b1443','#622461','#93388f','#ca52c9','#c85086','#f68187','#f5555d',
|
||||
'#ea323c','#c42430','#891e2b','#571c27',
|
||||
]
|
||||
}
|
||||
onVueSetup(() => {
|
||||
ColorPanel = Interface.Panels.color = new Panel({
|
||||
id: 'color',
|
||||
condition: () => Modes.id === 'paint',
|
||||
@ -321,18 +57,7 @@ onVueSetup(() => {
|
||||
},
|
||||
menu: new Menu([
|
||||
'sort_palette',
|
||||
'clear_palette',
|
||||
{name: 'menu.palette.load', id: 'load', icon: 'fa-tasks', children: [
|
||||
{name: 'menu.palette.load.default', icon: 'bubble_chart', id: 'default', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.default);
|
||||
}},
|
||||
{name: 'Endesga 64', description: 'Pixel art palette created by lospec.com/endesga', icon: 'bubble_chart', id: 'endesga64', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.endesga64);
|
||||
}},
|
||||
{name: 'Material', icon: 'bubble_chart', id: 'material', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.material);
|
||||
}},
|
||||
]}
|
||||
'load_palette'
|
||||
])
|
||||
})
|
||||
var saved_colors = localStorage.getItem('colors');
|
||||
@ -398,6 +123,20 @@ onVueSetup(() => {
|
||||
if (!color.match(/^#[0-9a-f]{6}$/)) {
|
||||
this.main_color = tinycolor(color).toHexString();
|
||||
}
|
||||
},
|
||||
isDarkColor(hex) {
|
||||
if (hex) {
|
||||
hex = hex.replace('#', '')
|
||||
let dgts = hex.substr(0, 1) + hex.substr(2, 1) + hex.substr(4, 1)
|
||||
let bg = parseInt(CustomTheme.data.colors.back.substr(1, 1), 16);
|
||||
let color_range = (bg).toString(16)
|
||||
+ (Math.isBetween(bg+2, 0, 15) ? (bg+2).toString(16) : '')
|
||||
+ (Math.isBetween(bg+1, 0, 15) ? (bg+1).toString(16) : '')
|
||||
+ (Math.isBetween(bg-1, 0, 15) ? (bg-1).toString(16) : '')
|
||||
+ (Math.isBetween(bg-2, 0, 15) ? (bg-2).toString(16) : '')
|
||||
let regex = new RegExp(`[^${color_range}]`)
|
||||
return dgts.search(regex) == -1
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -854,6 +593,7 @@ BARS.defineActions(function() {
|
||||
category: 'color',
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
resource_id: 'palette',
|
||||
extensions: ['gpl', 'css', 'txt', 'hex', 'png', 'aco', 'act', 'ase', 'bbpalette'],
|
||||
type: 'Blockbench Palette',
|
||||
readtype: (path) => {
|
||||
@ -881,6 +621,7 @@ BARS.defineActions(function() {
|
||||
content += `${t._r}\t${t._g}\t${t._b}\t${color}\n`;
|
||||
})
|
||||
Blockbench.export({
|
||||
resource_id: 'palette',
|
||||
extensions: ['gpl'],
|
||||
type: 'GPL Palette',
|
||||
content
|
||||
@ -936,12 +677,28 @@ BARS.defineActions(function() {
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action('clear_palette', {
|
||||
icon: 'clear',
|
||||
|
||||
new Action('load_palette', {
|
||||
icon: 'fa-tasks',
|
||||
category: 'color',
|
||||
click: function () {
|
||||
ColorPanel.palette.purge();
|
||||
}
|
||||
click: function (e) {
|
||||
new Menu(this.children).open(e.target)
|
||||
},
|
||||
children: [
|
||||
{name: 'menu.palette.load.default', icon: 'bubble_chart', id: 'default', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.default);
|
||||
}},
|
||||
{name: 'Endesga 64', description: 'Pixel art palette created by lospec.com/endesga', icon: 'bubble_chart', id: 'endesga64', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.endesga64);
|
||||
}},
|
||||
{name: 'Material', icon: 'bubble_chart', id: 'material', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity, ...palettes.material);
|
||||
}},
|
||||
'_',
|
||||
{name: 'menu.palette.load.empty', icon: 'clear', id: 'empty', click: () => {
|
||||
ColorPanel.palette.splice(0, Infinity);
|
||||
}},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@ -1005,4 +762,5 @@ BARS.defineActions(function() {
|
||||
ColorPanel.updateFromHsv();
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})()
|
||||
|
@ -112,7 +112,7 @@ const Painter = {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data) return;
|
||||
if (!data || (data.cube && data.cube.locked)) return;
|
||||
var texture = data.cube.faces[data.face].getTexture()
|
||||
if (!texture || (texture.error && texture.error !== 2)) {
|
||||
Blockbench.showQuickMessage('message.untextured')
|
||||
@ -131,7 +131,7 @@ const Painter = {
|
||||
movePaintToolCanvas(event) {
|
||||
convertTouchEvent(event);
|
||||
var data = Canvas.raycast(event)
|
||||
if (data) {
|
||||
if (data && data.cube && !data.cube.locked) {
|
||||
var texture = data.cube.faces[data.face].getTexture()
|
||||
if (texture) {
|
||||
var x, y, new_face;
|
||||
@ -204,7 +204,7 @@ const Painter = {
|
||||
Painter.drawBrushLine(texture, x, y, event, false, uvTag);
|
||||
} else {
|
||||
Painter.current.x = Painter.current.y = 0
|
||||
Painter.useBrush(texture, x, y, event, uvTag)
|
||||
Painter.useBrushlike(texture, x, y, event, uvTag)
|
||||
}
|
||||
Painter.current.x = x;
|
||||
Painter.current.y = y;
|
||||
@ -233,7 +233,7 @@ const Painter = {
|
||||
Painter.currentPixel = [-1, -1];
|
||||
},
|
||||
// Tools
|
||||
useBrush(texture, x, y, event, uvTag, no_update, is_opposite) {
|
||||
useBrushlike(texture, x, y, event, uvTag, no_update, is_opposite) {
|
||||
if (Painter.currentPixel[0] === x && Painter.currentPixel[1] === y) return;
|
||||
Painter.currentPixel = [x, y]
|
||||
Painter.brushChanges = true;
|
||||
@ -248,12 +248,6 @@ const Painter = {
|
||||
var ctx = canvas.getContext('2d')
|
||||
ctx.save()
|
||||
|
||||
var color = tinycolor(ColorPanel.get()).toRgb();
|
||||
var size = BarItems.slider_brush_size.get();
|
||||
let softness = BarItems.slider_brush_softness.get()/100;
|
||||
let b_opacity = BarItems.slider_brush_opacity.get()/100;
|
||||
let tool = Toolbox.selected.id;
|
||||
|
||||
ctx.beginPath();
|
||||
if (uvTag) {
|
||||
var rect = Painter.editing_area = [
|
||||
@ -275,129 +269,159 @@ const Painter = {
|
||||
var [w, h] = [rect[2] - rect[0], rect[3] - rect[1]]
|
||||
ctx.rect(rect[0], rect[1], w, h)
|
||||
|
||||
if (tool === 'fill_tool') {
|
||||
|
||||
ctx.fillStyle = tinycolor(ColorPanel.get()).setAlpha(b_opacity).toRgbString();
|
||||
|
||||
var fill_mode = BarItems.fill_mode.get()
|
||||
var cube = Painter.current.cube;
|
||||
if (cube && fill_mode === 'cube') {
|
||||
for (var face in cube.faces) {
|
||||
var tag = cube.faces[face]
|
||||
if (tag.texture === Painter.current.texture.uuid) {
|
||||
var rect = getRectangle(
|
||||
Math.floor(tag.uv[0] * uvFactorX),
|
||||
Math.floor(tag.uv[1] * uvFactorY),
|
||||
Math.ceil(tag.uv[2] * uvFactorX),
|
||||
Math.ceil(tag.uv[3] * uvFactorY)
|
||||
)
|
||||
ctx.rect(rect.ax, rect.ay, rect.x, rect.y)
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
|
||||
} else if (fill_mode === 'face') {
|
||||
ctx.fill()
|
||||
} else {
|
||||
|
||||
var pxcol = [];
|
||||
var map = {}
|
||||
Painter.scanCanvas(ctx, x, y, 1, 1, (x, y, px) => {
|
||||
px.forEach((val, i) => {
|
||||
pxcol[i] = val
|
||||
})
|
||||
})
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (pxcol.equals(px)) {
|
||||
if (!map[x]) map[x] = {}
|
||||
map[x][y] = true
|
||||
}
|
||||
})
|
||||
var scan_value = true;
|
||||
if (fill_mode === 'color_connected') {
|
||||
function checkPx(x, y) {
|
||||
if (map[x] && map[x][y]) {
|
||||
map[x][y] = false;
|
||||
|
||||
checkPx(x+1, y)
|
||||
checkPx(x-1, y)
|
||||
checkPx(x, y+1)
|
||||
checkPx(x, y-1)
|
||||
}
|
||||
}
|
||||
checkPx(x, y)
|
||||
scan_value = false;
|
||||
}
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (map[x] && map[x][y] === scan_value) {
|
||||
var pxcolor = {
|
||||
r: px[0],
|
||||
g: px[1],
|
||||
b: px[2],
|
||||
a: px[3]/255
|
||||
}
|
||||
var result_color = Painter.combineColors(pxcolor, color, b_opacity);
|
||||
px[0] = result_color.r
|
||||
px[1] = result_color.g
|
||||
px[2] = result_color.b
|
||||
if (!Painter.lock_alpha) px[3] = result_color.a*255
|
||||
}
|
||||
})
|
||||
}
|
||||
if (Toolbox.selected.id === 'fill_tool') {
|
||||
Painter.useFilltool(texture, ctx, x, y, { rect, uvFactorX, uvFactorY, w, h })
|
||||
} else {
|
||||
ctx.clip()
|
||||
if (event.touches && event.touches[0] && event.touches[0].force) {
|
||||
var touch = event.touches[0];
|
||||
if (touch.force == 1) touch.force == Painter.current.force || 0;
|
||||
Painter.current.force = touch.force;
|
||||
|
||||
if (settings.brush_opacity_modifier.value == 'pressure' && touch.force) {
|
||||
b_opacity = Math.clamp(b_opacity * touch.force*1.25, 0, 100);
|
||||
//m_opacity = Math.clamp(m_opacity * touch.force*1.25, 0, 100);
|
||||
|
||||
} else if (settings.brush_opacity_modifier.value == 'tilt' && touch.altitudeAngle !== undefined) {
|
||||
var modifier = Math.clamp(1.5 / (touch.altitudeAngle + 0.3), 1, 4)/2;
|
||||
b_opacity = Math.clamp(b_opacity * modifier, 0, 100);
|
||||
//m_opacity = Math.clamp(m_opacity * modifier, 0, 100);
|
||||
}
|
||||
if (settings.brush_size_modifier.value == 'pressure' && touch.force) {
|
||||
size = Math.clamp(touch.force * size * 2, 1, 20);
|
||||
|
||||
} else if (settings.brush_size_modifier.value == 'tilt' && touch.altitudeAngle !== undefined) {
|
||||
size *= Math.clamp(1.5 / (touch.altitudeAngle + 0.3), 1, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (tool === 'brush_tool') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity, px, py) {
|
||||
var a = b_opacity * opacity;
|
||||
var before = Painter.getAlphaMatrix(texture, px, py)
|
||||
Painter.setAlphaMatrix(texture, px, py, a);
|
||||
if (a > before) {
|
||||
a = (a - before) / (1 - before);
|
||||
} else if (before) {
|
||||
a = 0;
|
||||
}
|
||||
var result_color = Painter.combineColors(pxcolor, color, a);
|
||||
if (Painter.lock_alpha) result_color.a = pxcolor.a
|
||||
return result_color;
|
||||
})
|
||||
} else if (tool === 'eraser') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity) {
|
||||
return {
|
||||
r: pxcolor.r,
|
||||
g: pxcolor.g,
|
||||
b: pxcolor.b,
|
||||
a: Painter.lock_alpha ? pxcolor.a : (pxcolor.a*(1-b_opacity))
|
||||
};
|
||||
})
|
||||
}
|
||||
ctx.restore();
|
||||
Painter.useBrush(texture, ctx, x, y, event)
|
||||
}
|
||||
Painter.editing_area = undefined;
|
||||
|
||||
|
||||
}, {no_undo: true, use_cache: true, no_update});
|
||||
},
|
||||
useBrush(texture, ctx, x, y, event) {
|
||||
|
||||
var color = tinycolor(ColorPanel.get()).toRgb();
|
||||
var size = BarItems.slider_brush_size.get();
|
||||
let softness = BarItems.slider_brush_softness.get()/100;
|
||||
let b_opacity = BarItems.slider_brush_opacity.get()/100;
|
||||
let tool = Toolbox.selected.id;
|
||||
|
||||
ctx.clip()
|
||||
if (event.touches && event.touches[0] && event.touches[0].force) {
|
||||
|
||||
// Stylus
|
||||
var touch = event.touches[0];
|
||||
if (touch.force == 1) touch.force == Painter.current.force || 0;
|
||||
Painter.current.force = touch.force;
|
||||
|
||||
if (settings.brush_opacity_modifier.value == 'pressure' && touch.force) {
|
||||
b_opacity = Math.clamp(b_opacity * touch.force*1.25, 0, 100);
|
||||
|
||||
} else if (settings.brush_opacity_modifier.value == 'tilt' && touch.altitudeAngle !== undefined) {
|
||||
var modifier = Math.clamp(1.5 / (touch.altitudeAngle + 0.3), 1, 4)/2;
|
||||
b_opacity = Math.clamp(b_opacity * modifier, 0, 100);
|
||||
}
|
||||
if (settings.brush_size_modifier.value == 'pressure' && touch.force) {
|
||||
size = Math.clamp(touch.force * size * 2, 1, 20);
|
||||
|
||||
} else if (settings.brush_size_modifier.value == 'tilt' && touch.altitudeAngle !== undefined) {
|
||||
size *= Math.clamp(1.5 / (touch.altitudeAngle + 0.3), 1, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (tool === 'brush_tool') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity, px, py) {
|
||||
var a = b_opacity * opacity;
|
||||
var before = Painter.getAlphaMatrix(texture, px, py)
|
||||
Painter.setAlphaMatrix(texture, px, py, a);
|
||||
if (a > before) {
|
||||
a = (a - before) / (1 - before);
|
||||
} else if (before) {
|
||||
a = 0;
|
||||
}
|
||||
var result_color = Painter.combineColors(pxcolor, color, a);
|
||||
if (Painter.lock_alpha) result_color.a = pxcolor.a
|
||||
return result_color;
|
||||
})
|
||||
} else if (tool === 'eraser') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity, px, py) {
|
||||
if (Painter.lock_alpha) return pxcolor;
|
||||
|
||||
var a = b_opacity * opacity;
|
||||
|
||||
var before = Painter.getAlphaMatrix(texture, px, py)
|
||||
Painter.setAlphaMatrix(texture, px, py, a);
|
||||
|
||||
if (a > before) {
|
||||
a = (a - before) / (1 - before);
|
||||
} else if (before) {
|
||||
a = 0;
|
||||
}
|
||||
pxcolor.a = Math.clamp(pxcolor.a * (1-a), 0, 1);
|
||||
return pxcolor;
|
||||
|
||||
})
|
||||
}
|
||||
ctx.restore();
|
||||
},
|
||||
useFilltool(texture, ctx, x, y, area) {
|
||||
|
||||
var color = tinycolor(ColorPanel.get()).toRgb();
|
||||
let b_opacity = BarItems.slider_brush_opacity.get()/100;
|
||||
let tool = Toolbox.selected.id;
|
||||
|
||||
let {rect, uvFactorX, uvFactorY, w, h} = area;
|
||||
|
||||
ctx.fillStyle = tinycolor(ColorPanel.get()).setAlpha(b_opacity).toRgbString();
|
||||
|
||||
var fill_mode = BarItems.fill_mode.get()
|
||||
var cube = Painter.current.cube;
|
||||
if (cube && fill_mode === 'cube') {
|
||||
for (var face in cube.faces) {
|
||||
var tag = cube.faces[face]
|
||||
ctx.beginPath();
|
||||
if (tag.texture === Painter.current.texture.uuid) {
|
||||
var face_rect = getRectangle(
|
||||
Math.floor(tag.uv[0] * uvFactorX),
|
||||
Math.floor(tag.uv[1] * uvFactorY),
|
||||
Math.ceil(tag.uv[2] * uvFactorX),
|
||||
Math.ceil(tag.uv[3] * uvFactorY)
|
||||
)
|
||||
ctx.rect(face_rect.ax, face_rect.ay, face_rect.x, face_rect.y)
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
|
||||
} else if (fill_mode === 'face') {
|
||||
ctx.fill()
|
||||
} else {
|
||||
|
||||
var pxcol = [];
|
||||
var map = {}
|
||||
Painter.scanCanvas(ctx, x, y, 1, 1, (x, y, px) => {
|
||||
px.forEach((val, i) => {
|
||||
pxcol[i] = val
|
||||
})
|
||||
})
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (pxcol.equals(px)) {
|
||||
if (!map[x]) map[x] = {}
|
||||
map[x][y] = true
|
||||
}
|
||||
})
|
||||
var scan_value = true;
|
||||
if (fill_mode === 'color_connected') {
|
||||
function checkPx(x, y) {
|
||||
if (map[x] && map[x][y]) {
|
||||
map[x][y] = false;
|
||||
|
||||
checkPx(x+1, y)
|
||||
checkPx(x-1, y)
|
||||
checkPx(x, y+1)
|
||||
checkPx(x, y-1)
|
||||
}
|
||||
}
|
||||
checkPx(x, y)
|
||||
scan_value = false;
|
||||
}
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (map[x] && map[x][y] === scan_value) {
|
||||
var pxcolor = {
|
||||
r: px[0],
|
||||
g: px[1],
|
||||
b: px[2],
|
||||
a: px[3]/255
|
||||
}
|
||||
var result_color = Painter.combineColors(pxcolor, color, b_opacity);
|
||||
px[0] = result_color.r
|
||||
px[1] = result_color.g
|
||||
px[2] = result_color.b
|
||||
if (!Painter.lock_alpha) px[3] = result_color.a*255
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
runMirrorBrush(texture, x, y, event, uvTag) {
|
||||
if (uvTag && Painter.current.cube) {
|
||||
let mirror_cube = Painter.getMirrorCube(Painter.current.cube);
|
||||
@ -436,7 +460,7 @@ const Painter = {
|
||||
|
||||
let cube = Painter.current.cube;
|
||||
Painter.current.cube = mirror_cube;
|
||||
Painter.useBrush(texture, ...point_on_uv, event, face.uv, true, true);
|
||||
Painter.useBrushlike(texture, ...point_on_uv, event, face.uv, true, true);
|
||||
Painter.current.cube = cube;
|
||||
}
|
||||
}
|
||||
@ -457,7 +481,7 @@ const Painter = {
|
||||
while (i <= length) {
|
||||
x = Math.round(start_x + diff_x / length * i)
|
||||
y = Math.round(start_y + diff_y / length * i)
|
||||
Painter.useBrush(texture, x, y, event, uv, i < length-1);
|
||||
Painter.useBrushlike(texture, x, y, event, uv, i < length-1);
|
||||
i++;
|
||||
}
|
||||
},
|
||||
@ -617,15 +641,16 @@ const Painter = {
|
||||
},
|
||||
getMirrorCube(cube) {
|
||||
let center = Format.centered_grid ? 0 : 8;
|
||||
let e = 0.002
|
||||
if (cube.from[0]-center === center-cube.to[0] && !cube.rotation[1] && !cube.rotation[2]) {
|
||||
return cube;
|
||||
} else {
|
||||
for (var cube2 of Cube.all) {
|
||||
if (
|
||||
cube.inflate === cube2.inflate &&
|
||||
cube.from[2] === cube2.from[2] && cube.to[2] === cube2.to[2] &&
|
||||
cube.from[1] === cube2.from[1] && cube.to[1] === cube2.to[1] &&
|
||||
cube.size(0) === cube2.size(0) && cube.to[0]-center === center-cube2.from[0]
|
||||
Math.epsilon(cube.from[2], cube2.from[2], e) && Math.epsilon(cube.to[2], cube2.to[2], e) &&
|
||||
Math.epsilon(cube.from[1], cube2.from[1], e) && Math.epsilon(cube.to[1], cube2.to[1], e) &&
|
||||
Math.epsilon(cube.size(0), cube2.size(0), e) && Math.epsilon(cube.to[0]-center, center-cube2.from[0], e)
|
||||
) {
|
||||
return cube2;
|
||||
}
|
||||
@ -957,7 +982,7 @@ BARS.defineActions(function() {
|
||||
condition: () => (Toolbox && ['brush_tool', 'eraser', 'draw_shape_tool'].includes(Toolbox.selected.id)),
|
||||
category: 'paint',
|
||||
settings: {
|
||||
min: 1, max: 20, interval: 1, default: 1,
|
||||
min: 1, max: 50, interval: 1, default: 1,
|
||||
}
|
||||
})
|
||||
new NumSlider('slider_brush_softness', {
|
||||
|
@ -371,14 +371,23 @@ const TextureGenerator = {
|
||||
coords.w*res_multiple,
|
||||
coords.h*res_multiple
|
||||
)
|
||||
if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2 && color) {
|
||||
ctx.fillStyle = color
|
||||
ctx.fillRect(
|
||||
coords.x * res_multiple + 1,
|
||||
coords.y * res_multiple + 1,
|
||||
coords.w * res_multiple - 2,
|
||||
coords.h * res_multiple - 2
|
||||
)
|
||||
if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2) {
|
||||
if (color == null) {
|
||||
ctx.clearRect(
|
||||
coords.x * res_multiple + 1,
|
||||
coords.y * res_multiple + 1,
|
||||
coords.w * res_multiple - 2,
|
||||
coords.h * res_multiple - 2
|
||||
)
|
||||
} else if (color) {
|
||||
ctx.fillStyle = color
|
||||
ctx.fillRect(
|
||||
coords.x * res_multiple + 1,
|
||||
coords.y * res_multiple + 1,
|
||||
coords.w * res_multiple - 2,
|
||||
coords.h * res_multiple - 2
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
boxUVdrawTexture(face, coords, texture, canvas) {
|
||||
@ -423,9 +432,9 @@ const TextureGenerator = {
|
||||
ctx.drawImage(
|
||||
texture.img,
|
||||
src.ax/Project.texture_width * texture.img.naturalWidth,
|
||||
src.ay/Project.texture_height * texture.img.naturalHeight,
|
||||
src.ay/Project.texture_width * texture.img.naturalWidth,
|
||||
src.x /Project.texture_width * texture.img.naturalWidth,
|
||||
src.y /Project.texture_height * texture.img.naturalHeight,
|
||||
src.y /Project.texture_width * texture.img.naturalWidth,
|
||||
coords.x*res_multiple*flip[0],
|
||||
coords.y*res_multiple*flip[1],
|
||||
coords.w*res_multiple*flip[0],
|
||||
@ -434,7 +443,7 @@ const TextureGenerator = {
|
||||
ctx.restore()
|
||||
return true;
|
||||
},
|
||||
paintCubeBoxTemplate(cube, texture, canvas, template) {
|
||||
paintCubeBoxTemplate(cube, texture, canvas, template, transparent) {
|
||||
|
||||
if (!template) {
|
||||
template = new TextureGenerator.boxUVCubeTemplate(cube, Project.box_uv ? 0 : 1);
|
||||
@ -446,7 +455,7 @@ const TextureGenerator = {
|
||||
if (!cube.faces[face].texture ||
|
||||
!TextureGenerator.boxUVdrawTexture(cube.faces[face], d.place(template), texture, canvas)
|
||||
) {
|
||||
TextureGenerator.boxUVdrawTemplateRectangle(d.c1, d.c2, cube.faces[face], d.place(template), texture, canvas)
|
||||
TextureGenerator.boxUVdrawTemplateRectangle(d.c1, transparent ? null : d.c2, cube.faces[face], d.place(template), texture, canvas)
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,13 +697,15 @@ const TextureGenerator = {
|
||||
w: ftemp.width,
|
||||
h: ftemp.height
|
||||
}
|
||||
var d = TextureGenerator.face_data[ftemp.face_key];
|
||||
var d = TextureGenerator.face_data[ftemp.face_key];
|
||||
var flip_rotation = false
|
||||
if (!ftemp.texture ||
|
||||
!drawTexture(ftemp.face, pos)
|
||||
) {
|
||||
drawTemplateRectangle(d.c1, d.c2, ftemp.face, pos)
|
||||
} else {
|
||||
flip_rotation = ftemp.face.rotation % 180 != 0;
|
||||
}
|
||||
var flip_rotation = ftemp.face.rotation % 180 != 0;
|
||||
ftemp.face.extend({
|
||||
rotation: 0,
|
||||
uv: flip_rotation ? [pos.y, pos.x] : [pos.x, pos.y]
|
||||
|
@ -80,15 +80,10 @@ class Texture {
|
||||
|
||||
//Width / Animation
|
||||
if (img.naturalWidth !== img.naturalHeight && Format.id == 'java_block') {
|
||||
if (img.naturalHeight % img.naturalWidth !== 0) {
|
||||
scope.error = 2;
|
||||
Blockbench.showQuickMessage('message.square_textures')
|
||||
} else {
|
||||
BARS.updateConditions()
|
||||
}
|
||||
BARS.updateConditions()
|
||||
}
|
||||
|
||||
if (Project.box_uv && Format.single_texture) {
|
||||
if (Project.box_uv && Format.single_texture && !scope.error) {
|
||||
|
||||
if (!scope.keep_size) {
|
||||
let pw = Project.texture_width;
|
||||
@ -101,13 +96,12 @@ class Texture {
|
||||
//Resolution of this texture has changed
|
||||
var changed = size_control.old_width && (size_control.old_width != nw || size_control.old_height != nh);
|
||||
//Resolution could be a multiple of project size
|
||||
var multi = !(
|
||||
(pw%nw || ph%nh) &&
|
||||
(nw%pw || nh%ph)
|
||||
var multi = (
|
||||
(pw%nw == 0 || nw%pw == 0) &&
|
||||
(ph%nh == 0 || nh%ph == 0)
|
||||
)
|
||||
|
||||
|
||||
if (unlike && changed) {
|
||||
if (unlike && changed && !multi) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'update_res',
|
||||
icon: 'photo_size_select_small',
|
||||
@ -129,11 +123,6 @@ class Texture {
|
||||
size_control.old_height = img.naturalHeight
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($('.dialog#texture_edit:visible').length > 0 && scope.selected === true) {
|
||||
scope.openMenu()
|
||||
}
|
||||
TextureAnimator.updateButton()
|
||||
Canvas.updateAllFaces(scope)
|
||||
if (typeof scope.load_callback === 'function') {
|
||||
@ -141,7 +130,7 @@ class Texture {
|
||||
delete scope.load_callback;
|
||||
}
|
||||
}
|
||||
this.img.onerror = function() {
|
||||
this.img.onerror = function(error) {
|
||||
if (isApp &&
|
||||
!scope.isDefault &&
|
||||
scope.mode !== 'bitmap' &&
|
||||
@ -166,7 +155,7 @@ class Texture {
|
||||
case 0: return ''; break;
|
||||
case 1: return tl('texture.error.file'); break;
|
||||
//case 1: return tl('texture.error.invalid'); break;
|
||||
case 2: return tl('texture.error.ratio'); break;
|
||||
//case 2: return tl('texture.error.ratio'); break;
|
||||
case 3: return tl('texture.error.parent'); break;
|
||||
}
|
||||
}
|
||||
@ -402,6 +391,7 @@ class Texture {
|
||||
|
||||
function _replace() {
|
||||
Blockbench.import({
|
||||
resource_id: 'texture',
|
||||
extensions: ['png', 'tga'],
|
||||
type: 'PNG Texture',
|
||||
readtype: 'image',
|
||||
@ -453,21 +443,21 @@ class Texture {
|
||||
var scope = this;
|
||||
this.stopWatcher();
|
||||
|
||||
fs.watchFile(scope.path, {interval: 50}, function(curr, prev) {
|
||||
if (curr.mtime !== prev.mtime) {
|
||||
if (fs.existsSync(scope.path)) {
|
||||
let timeout;
|
||||
this.watcher = fs.watch(scope.path, (eventType) => {
|
||||
if (eventType == 'change') {
|
||||
if (timeout) clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
scope.reloadTexture();
|
||||
} else {
|
||||
scope.stopWatcher();
|
||||
}
|
||||
}, 60)
|
||||
}
|
||||
})
|
||||
}
|
||||
stopWatcher() {
|
||||
if (this.mode !== 'link' || !isApp || !fs.existsSync(this.path)) {
|
||||
return;
|
||||
if (isApp && this.watcher) {
|
||||
this.watcher.close()
|
||||
}
|
||||
fs.unwatchFile(this.path)
|
||||
return this;
|
||||
}
|
||||
generateFolder(path) {
|
||||
var scope = this
|
||||
@ -499,6 +489,9 @@ class Texture {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
getMaterial() {
|
||||
return Canvas.materials[this.uuid]
|
||||
}
|
||||
//Management
|
||||
select(event) {
|
||||
textures.forEach(s => {
|
||||
@ -509,6 +502,7 @@ class Texture {
|
||||
}
|
||||
this.selected = true
|
||||
textures.selected = this
|
||||
this.scrollTo()
|
||||
return this;
|
||||
}
|
||||
add(undo) {
|
||||
@ -655,31 +649,54 @@ class Texture {
|
||||
openMenu() {
|
||||
var scope = this
|
||||
scope.select()
|
||||
showDialog('texture_edit')
|
||||
|
||||
let title = `${scope.name} (${scope.width} x ${scope.height})`;
|
||||
var path = '';
|
||||
|
||||
if (scope.path) {
|
||||
var arr = scope.path.split(osfs)
|
||||
arr.splice(-1)
|
||||
var path = arr.join('<span class="slash">/</span>') + '<span class="slash">/</span><span class="accent_color">' + scope.name + '</span>'
|
||||
$('#texture_edit #te_path').html(path)
|
||||
} else {
|
||||
$('#texture_edit #te_path').html('')
|
||||
path = arr.join('<span class="slash">/</span>') + '<span class="slash">/</span><span class="accent_color">' + scope.name + '</span>'
|
||||
}
|
||||
|
||||
$('#texture_edit #te_title').text(scope.name + ' ('+scope.img.naturalWidth+' x '+scope.img.naturalHeight+')')
|
||||
$('#texture_edit input#te_variable').val(scope.id)
|
||||
$('#texture_edit input#te_name').val(scope.name)
|
||||
$('#texture_edit input#te_folder').val(scope.folder)
|
||||
$('#texture_edit input#te_namespace').val(scope.namespace)
|
||||
$('#texture_menu_thumbnail').html(scope.img)
|
||||
var dialog = new Dialog({
|
||||
id: 'texture_edit',
|
||||
title,
|
||||
lines: [
|
||||
`<div style="height: 140px;">
|
||||
<div id="texture_menu_thumbnail">${scope.img.outerHTML}</div>
|
||||
<p class="multiline_text" id="te_path">${path}</p>
|
||||
</div>`
|
||||
],
|
||||
form: {
|
||||
name: {label: 'generic.name', value: scope.name},
|
||||
variable: {label: 'dialog.texture.variable', value: scope.id, condition: () => Format.id === 'java_block'},
|
||||
folder: {label: 'dialog.texture.folder', value: scope.folder, condition: () => Format.id === 'java_block'},
|
||||
namespace: {label: 'dialog.texture.namespace', value: scope.namespace, condition: () => Format.id === 'java_block'},
|
||||
},
|
||||
onConfirm: function(results) {
|
||||
|
||||
if (scope.mode === 'link') {
|
||||
$('#texture_edit .tool.link_only').show()
|
||||
$('#texture_edit .tool.bitmap_only').hide()
|
||||
} else {
|
||||
$('#texture_edit .tool.link_only').hide()
|
||||
$('#texture_edit .tool.bitmap_only').show()
|
||||
}
|
||||
dialog.hide();
|
||||
if (
|
||||
(scope.name === results.name) &&
|
||||
(results.variable === undefined || scope.id === results.variable) &&
|
||||
(results.folder === undefined || scope.folder === results.folder) &&
|
||||
(results.namespace === undefined || scope.namespace === results.namespace)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.initEdit({textures: [scope]})
|
||||
|
||||
scope.name = results.name;
|
||||
if (results.variable !== undefined) scope.id = results.variable;
|
||||
if (results.folder !== undefined) scope.folder = results.folder;
|
||||
if (results.namespace !== undefined) scope.namespace = results.namespace;
|
||||
|
||||
|
||||
Undo.finishEdit('texture_edit')
|
||||
}
|
||||
}).show()
|
||||
}
|
||||
resizeDialog() {
|
||||
let scope = this;
|
||||
@ -776,6 +793,22 @@ class Texture {
|
||||
dialog.show()
|
||||
return this;
|
||||
}
|
||||
scrollTo() {
|
||||
var el = $(`#texture_list > li[texid=${this.uuid}]`)
|
||||
if (el.length === 0 || textures.length < 2) return;
|
||||
|
||||
var outliner_pos = $('#texture_list').offset().top
|
||||
var el_pos = el.offset().top
|
||||
if (el_pos > outliner_pos && el_pos + 48 < $('#texture_list').height() + outliner_pos) return;
|
||||
|
||||
var multiple = el_pos > outliner_pos ? 0.5 : 0.2
|
||||
var scroll_amount = el_pos + $('#texture_list').scrollTop() - outliner_pos - 20
|
||||
scroll_amount -= $('#texture_list').height()*multiple - 15
|
||||
|
||||
$('#texture_list').animate({
|
||||
scrollTop: scroll_amount
|
||||
}, 200);
|
||||
}
|
||||
//Export
|
||||
javaTextureLink() {
|
||||
var link = this.name.replace(/\.png$/, '')
|
||||
@ -819,6 +852,7 @@ class Texture {
|
||||
find_path = arr.join(osfs)
|
||||
}
|
||||
Blockbench.export({
|
||||
resource_id: 'texture',
|
||||
type: 'PNG Texture',
|
||||
extensions: ['png'],
|
||||
name: scope.name,
|
||||
@ -968,29 +1002,6 @@ function saveTextures() {
|
||||
}
|
||||
})
|
||||
}
|
||||
function saveTextureMenu() {
|
||||
hideDialog()
|
||||
var tex = textures.selected
|
||||
|
||||
var name = $('#texture_edit input#te_name').val(),
|
||||
id = $('#texture_edit input#te_variable').val(),
|
||||
folder = $('#texture_edit input#te_folder').val(),
|
||||
namespace = $('#texture_edit input#te_namespace').val();
|
||||
|
||||
if (!(
|
||||
tex.name === name &&
|
||||
tex.id === id &&
|
||||
tex.folder === folder &&
|
||||
tex.namespace === namespace)
|
||||
) {
|
||||
Undo.initEdit({textures})
|
||||
tex.name = name;
|
||||
tex.id = id;
|
||||
tex.folder = folder;
|
||||
tex.namespace = namespace;
|
||||
Undo.finishEdit('texture_edit')
|
||||
}
|
||||
}
|
||||
function loadTextureDraggable() {
|
||||
Vue.nextTick(function() {
|
||||
setTimeout(function() {
|
||||
@ -1046,14 +1057,6 @@ function unselectTextures() {
|
||||
})
|
||||
textures.selected = false
|
||||
}
|
||||
function getTextureById(id) {
|
||||
if (id === undefined || id === false) return;
|
||||
if (id == null) {
|
||||
return {material: transparentMaterial};
|
||||
}
|
||||
id = id.replace('#', '');
|
||||
return $.grep(textures, function(e) {return e.id == id})[0];
|
||||
}
|
||||
function getTexturesById(id) {
|
||||
if (id === undefined) return;
|
||||
id = id.replace('#', '');
|
||||
@ -1183,6 +1186,7 @@ BARS.defineActions(function() {
|
||||
start_path = arr.join(osfs)
|
||||
}
|
||||
Blockbench.import({
|
||||
resource_id: 'texture',
|
||||
readtype: 'image',
|
||||
type: 'PNG Texture',
|
||||
extensions: ['png', 'tga'],
|
||||
|
@ -20,6 +20,12 @@ class UVEditor {
|
||||
this.setGrid(BarItems.uv_grid.get().replace(/x/, ''));
|
||||
}
|
||||
}
|
||||
get width() {
|
||||
return this.size;
|
||||
}
|
||||
set width(v) {
|
||||
this.size = v;
|
||||
}
|
||||
buildDom(toolbar) {
|
||||
var scope = this
|
||||
if (this.jquery.main) {
|
||||
@ -47,6 +53,7 @@ class UVEditor {
|
||||
</div>
|
||||
</div>`);
|
||||
this.img = new Image();
|
||||
this.img.style.objectFit = Format.animated_textures ? 'cover' : 'fill';
|
||||
this.jquery.frame.append(this.img)
|
||||
this.jquery.size = this.jquery.frame.find('div#uv_size')
|
||||
this.jquery.viewport.append(this.jquery.frame)
|
||||
@ -56,6 +63,7 @@ class UVEditor {
|
||||
if (Toolbox.selected.paintTool) {
|
||||
this.jquery.size.hide()
|
||||
}
|
||||
this.jquery.main.toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
|
||||
|
||||
this.jquery.sliders = $('<div class="bar" style="margin-left: 2px;"></div>')
|
||||
|
||||
@ -271,13 +279,17 @@ class UVEditor {
|
||||
var n = (event.deltaY < 0) ? 0.1 : -0.1;
|
||||
n *= scope.zoom
|
||||
var number = limitNumber(scope.zoom + n, 1, scope.max_zoom)
|
||||
if (Math.abs(number - scope.zoom) > 0.001) {
|
||||
this.scrollLeft += (scope.inner_width * n / 2) * (event.offsetX / scope.jquery.frame.width());
|
||||
this.scrollTop += (scope.inner_width * n / 2) * (event.offsetY / scope.jquery.frame.height());
|
||||
}
|
||||
let old_zoom = scope.zoom;
|
||||
|
||||
|
||||
scope.setZoom(number)
|
||||
event.preventDefault()
|
||||
e.preventDefault()
|
||||
|
||||
let zoom_diff = scope.zoom - old_zoom;
|
||||
this.scrollLeft += ((this.scrollLeft + event.offsetX) * zoom_diff) / old_zoom
|
||||
this.scrollTop += ((this.scrollTop + event.offsetY) * zoom_diff) / old_zoom
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
@ -306,25 +318,29 @@ class UVEditor {
|
||||
//Paint brush outline
|
||||
this.brush_outline = $('<div id="uv_brush_outline"></div>');
|
||||
scope.jquery.frame.on('mouseenter mousemove', e => {
|
||||
if (Modes.paint && Toolbox.selected.brushTool) {
|
||||
scope.jquery.frame.append(this.brush_outline);
|
||||
var pixel_size = scope.inner_width / (scope.texture ? scope.texture.width : Project.texture_width);
|
||||
//pos
|
||||
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
|
||||
let left = (0.5 - offset + Math.floor(e.offsetX / pixel_size + offset)) * pixel_size;
|
||||
let top = (0.5 - offset + Math.floor(e.offsetY / pixel_size + offset)) * pixel_size;
|
||||
this.brush_outline.css('left', left+'px').css('top', top+'px');
|
||||
//size
|
||||
var radius = (BarItems.slider_brush_size.get()/2) * pixel_size;
|
||||
this.brush_outline.css('padding', radius+'px').css('margin', (-radius)+'px');
|
||||
}
|
||||
this.updateBrushOutline(e)
|
||||
})
|
||||
scope.jquery.frame.on('mouseleave', e => {
|
||||
this.brush_outline.detach();
|
||||
})
|
||||
this.setSize(this.size)
|
||||
return this;
|
||||
}
|
||||
updateBrushOutline(e) {
|
||||
if (Modes.paint && Toolbox.selected.brushTool) {
|
||||
this.jquery.frame.append(this.brush_outline);
|
||||
var pixel_size = this.inner_width / (this.texture ? this.texture.width : Project.texture_width);
|
||||
//pos
|
||||
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
|
||||
let left = (0.5 - offset + Math.floor(e.offsetX / pixel_size + offset)) * pixel_size;
|
||||
let top = (0.5 - offset + Math.floor(e.offsetY / pixel_size + offset)) * pixel_size;
|
||||
this.brush_outline.css('left', left+'px').css('top', top+'px');
|
||||
//size
|
||||
var radius = (BarItems.slider_brush_size.get()/2) * pixel_size;
|
||||
this.brush_outline.css('padding', radius+'px').css('margin', (-radius)+'px');
|
||||
} else {
|
||||
this.brush_outline.detach();
|
||||
}
|
||||
}
|
||||
message(msg, vars) {
|
||||
msg = tl(msg, vars)
|
||||
var box = $('<div class="uv_message_box">' + msg + '</div>')
|
||||
@ -703,12 +719,12 @@ class UVEditor {
|
||||
this.jquery.viewport.css('overflow', 'hidden')
|
||||
}
|
||||
}
|
||||
setFace(face, update) {
|
||||
setFace(face, update = true) {
|
||||
this.face = face
|
||||
if (this.id === 'main_uv') {
|
||||
$('input#'+face+'_radio').prop("checked", true)
|
||||
}
|
||||
if (update !== false) {
|
||||
if (update) {
|
||||
this.loadData()
|
||||
}
|
||||
return this;
|
||||
@ -867,7 +883,7 @@ class UVEditor {
|
||||
}
|
||||
var tex = face ? face.getTexture() : textures[0];
|
||||
if (!tex || typeof tex !== 'object' || (tex.error && tex.error != 2)) {
|
||||
main_uv.img.src = '';
|
||||
this.img.src = '';
|
||||
this.img.style.display = 'none';
|
||||
this.texture = false;
|
||||
} else {
|
||||
@ -1795,9 +1811,9 @@ const uv_dialog = {
|
||||
}
|
||||
},
|
||||
updateSelection: function() {
|
||||
$('#uv_dialog_all .UVEditor .uv_headline').removeClass('selected')
|
||||
$('#uv_dialog_all .UVEditor').removeClass('selected')
|
||||
uv_dialog.selection.forEach(function(id) {
|
||||
$('#uv_dialog_all #UVEditor_'+id+' .uv_headline').addClass('selected')
|
||||
$('#uv_dialog_all #UVEditor_'+id).addClass('selected')
|
||||
})
|
||||
},
|
||||
openDialog: function() {
|
||||
|
221
js/transform.js
221
js/transform.js
@ -62,42 +62,6 @@ function getSelectionCenter() {
|
||||
}
|
||||
return center;
|
||||
}
|
||||
function isMovementGlobal() {
|
||||
if (selected.length === 0 || (Toolbox.selected.id !== 'resize_tool')) {
|
||||
return true;
|
||||
}
|
||||
if (Format.rotate_cubes) {
|
||||
if (Cube.selected.length > 1) {
|
||||
if (Cube.selected[0].rotation.equals([0,0,0])) return true;
|
||||
var i = 0;
|
||||
while (i < Cube.selected.length) {
|
||||
if (!Cube.selected[0].rotation.equals(Cube.selected[i].rotation)) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return Format.bone_rig && Group.selected;
|
||||
}
|
||||
if (Format.bone_rig) {
|
||||
if (Cube.selected[0] && Cube.selected[0].parent.type === 'group') {
|
||||
var ref_group = Cube.selected[0].parent
|
||||
var i = 0;
|
||||
while (i < Cube.selected.length) {
|
||||
var obj = Cube.selected[i]
|
||||
if (
|
||||
obj.parent.type !== 'group' ||
|
||||
!obj.parent.rotation.equals(ref_group.rotation)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//Canvas Restriction
|
||||
function isInBox(val) {
|
||||
return !(Format.canvas_limit && !settings.deactivate_size_limit.value) || (val < 32 && val > -16)
|
||||
@ -229,7 +193,29 @@ const Vertexsnap = {
|
||||
vertexes: new THREE.Object3D(),
|
||||
vertexed_cubes: [],
|
||||
hovering: false,
|
||||
addVertexes: function(cube) {
|
||||
createVertexGizmo(cube, vec, id) {
|
||||
//Each vertex needs it's own material for hovering
|
||||
let outline_color = '0x'+CustomTheme.data.colors.accent.replace('#', '')
|
||||
let material = new THREE.MeshBasicMaterial({color: parseInt(outline_color)})
|
||||
let mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material)
|
||||
|
||||
let pos = mesh.position.copy(vec)
|
||||
pos.applyMatrix4(cube.mesh.matrixWorld)
|
||||
if (!Format.centered_grid) {
|
||||
pos.addScalar(8)
|
||||
}
|
||||
mesh.rotation.copy(cube.mesh.rotation)
|
||||
if (id == 100) {
|
||||
mesh.rotation.y += Math.PI/4;
|
||||
}
|
||||
mesh.cube = cube
|
||||
mesh.isVertex = true
|
||||
mesh.vertex_id = id
|
||||
mesh.material.transparent = true;
|
||||
mesh.renderOrder = 999;
|
||||
Vertexsnap.vertexes.add(mesh)
|
||||
},
|
||||
addVertices: function(cube) {
|
||||
if (Vertexsnap.vertexed_cubes.includes(cube)) return;
|
||||
if (cube.visibility === false) return;
|
||||
|
||||
@ -239,21 +225,9 @@ const Vertexsnap = {
|
||||
var o_vertices = cube.mesh.geometry.vertices
|
||||
cube.mesh.updateMatrixWorld()
|
||||
o_vertices.forEach(function(v, id) {
|
||||
var outline_color = '0x'+CustomTheme.data.colors.accent.replace('#', '')
|
||||
//Each vertex needs it's own material for hovering
|
||||
var material = new THREE.MeshBasicMaterial({color: parseInt(outline_color)})
|
||||
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material)
|
||||
var pos = mesh.position.copy(v)
|
||||
pos.applyMatrix4(cube.mesh.matrixWorld)
|
||||
if (!Format.centered_grid) {
|
||||
pos.addScalar(8)
|
||||
}
|
||||
mesh.rotation.copy(cube.mesh.rotation)
|
||||
mesh.cube = cube
|
||||
mesh.isVertex = true
|
||||
mesh.vertex_id = id
|
||||
Vertexsnap.vertexes.add(mesh)
|
||||
Vertexsnap.createVertexGizmo(cube, v, id)
|
||||
})
|
||||
Vertexsnap.createVertexGizmo(cube, new THREE.Vector3(), 100)
|
||||
Vertexsnap.vertexed_cubes.push(cube)
|
||||
Vertexsnap.updateVertexSize()
|
||||
},
|
||||
@ -273,6 +247,7 @@ const Vertexsnap = {
|
||||
Vertexsnap.vertexes.remove(v)
|
||||
} else {
|
||||
v.material.color.set(parseInt('0x'+CustomTheme.data.colors.accent.replace('#', '')))
|
||||
v.material.depthTest = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -285,6 +260,8 @@ const Vertexsnap = {
|
||||
vertex.material.color.g = 1
|
||||
Vertexsnap.hovering = true
|
||||
|
||||
vertex.material.depthTest = false;
|
||||
|
||||
if (Vertexsnap.step1 === false) {
|
||||
//Line
|
||||
var geometry = new THREE.Geometry();
|
||||
@ -302,7 +279,7 @@ const Vertexsnap = {
|
||||
select: function() {
|
||||
Vertexsnap.removeVertexes()
|
||||
Cube.selected.forEach(function(obj) {
|
||||
Vertexsnap.addVertexes(obj)
|
||||
Vertexsnap.addVertices(obj)
|
||||
})
|
||||
if (Cube.selected.length) {
|
||||
$('#preview').css('cursor', (Vertexsnap.step1 ? 'copy' : 'alias'))
|
||||
@ -320,6 +297,7 @@ const Vertexsnap = {
|
||||
Vertexsnap.cubes = Cube.selected.slice()
|
||||
Vertexsnap.removeVertexes()
|
||||
$('#preview').css('cursor', (Vertexsnap.step1 ? 'copy' : 'alias'))
|
||||
|
||||
} else {
|
||||
Vertexsnap.snap(data)
|
||||
$('#preview').css('cursor', (Vertexsnap.step1 ? 'copy' : 'alias'))
|
||||
@ -329,55 +307,73 @@ const Vertexsnap = {
|
||||
snap: function(data) {
|
||||
Undo.initEdit({elements: Vertexsnap.cubes})
|
||||
|
||||
var global_delta = data.vertex.position
|
||||
global_delta.sub(Vertexsnap.vertex_pos)
|
||||
let mode = BarItems.vertex_snap_mode.get()
|
||||
|
||||
if (BarItems.vertex_snap_mode.get() === 'scale') {
|
||||
//Scale
|
||||
if (Vertexsnap.vertex_id === 100) {
|
||||
|
||||
var m;
|
||||
switch (Vertexsnap.vertex_id) {
|
||||
case 0: m=[ 1,1,1 ]; break;
|
||||
case 1: m=[ 1,1,0 ]; break;
|
||||
case 2: m=[ 1,0,1 ]; break;
|
||||
case 3: m=[ 1,0,0 ]; break;
|
||||
case 4: m=[ 0,1,0 ]; break;
|
||||
case 5: m=[ 0,1,1 ]; break;
|
||||
case 6: m=[ 0,0,0 ]; break;
|
||||
case 7: m=[ 0,0,1 ]; break;
|
||||
}
|
||||
Vertexsnap.cubes.forEach(function(cube) {
|
||||
let vec = new THREE.Vector3().copy(data.vertex.position)
|
||||
|
||||
Vertexsnap.cubes.forEach(function(obj) {
|
||||
var q = obj.mesh.getWorldQuaternion(new THREE.Quaternion()).inverse()
|
||||
var cube_pos = new THREE.Vector3().copy(global_delta).applyQuaternion(q)
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
if (m[i] === 1) {
|
||||
obj.to[i] = limitToBox(obj.to[i] + cube_pos.getComponent(i), obj.inflate)
|
||||
} else {
|
||||
obj.from[i] = limitToBox(obj.from[i] + cube_pos.getComponent(i), -obj.inflate)
|
||||
}
|
||||
}
|
||||
if (Project.box_uv && obj.visibility) {
|
||||
Canvas.updateUV(obj)
|
||||
if (Format.bone_rig && cube.parent instanceof Group && cube.mesh.parent) {
|
||||
cube.mesh.parent.worldToLocal(vec);
|
||||
}
|
||||
let vec_array = vec.toArray()
|
||||
vec_array.V3_add(cube.parent.origin);
|
||||
cube.transferOrigin(vec_array)
|
||||
})
|
||||
} else {
|
||||
Vertexsnap.cubes.forEach(function(obj) {
|
||||
var cube_pos = new THREE.Vector3().copy(global_delta)
|
||||
|
||||
if (Format.bone_rig && obj.parent instanceof Group && obj.mesh.parent) {
|
||||
var q = obj.mesh.parent.getWorldQuaternion(new THREE.Quaternion()).inverse();
|
||||
cube_pos.applyQuaternion(q);
|
||||
var global_delta = data.vertex.position
|
||||
global_delta.sub(Vertexsnap.vertex_pos)
|
||||
|
||||
if (mode === 'scale') {
|
||||
//Scale
|
||||
|
||||
var m;
|
||||
switch (Vertexsnap.vertex_id) {
|
||||
case 0: m=[ 1,1,1 ]; break;
|
||||
case 1: m=[ 1,1,0 ]; break;
|
||||
case 2: m=[ 1,0,1 ]; break;
|
||||
case 3: m=[ 1,0,0 ]; break;
|
||||
case 4: m=[ 0,1,0 ]; break;
|
||||
case 5: m=[ 0,1,1 ]; break;
|
||||
case 6: m=[ 0,0,0 ]; break;
|
||||
case 7: m=[ 0,0,1 ]; break;
|
||||
}
|
||||
if (Format.rotate_cubes) {
|
||||
obj.origin.V3_add(cube_pos);
|
||||
}
|
||||
var in_box = obj.moveVector(cube_pos.toArray());
|
||||
if (!in_box && Format.canvas_limit && !settings.deactivate_size_limit.value) {
|
||||
Blockbench.showMessageBox({translateKey: 'canvas_limit_error'})
|
||||
}
|
||||
})
|
||||
|
||||
Vertexsnap.cubes.forEach(function(obj) {
|
||||
var q = obj.mesh.getWorldQuaternion(new THREE.Quaternion()).inverse()
|
||||
var cube_pos = new THREE.Vector3().copy(global_delta).applyQuaternion(q)
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
if (m[i] === 1) {
|
||||
obj.to[i] = limitToBox(obj.to[i] + cube_pos.getComponent(i), obj.inflate)
|
||||
} else {
|
||||
obj.from[i] = limitToBox(obj.from[i] + cube_pos.getComponent(i), -obj.inflate)
|
||||
}
|
||||
}
|
||||
if (Project.box_uv && obj.visibility) {
|
||||
Canvas.updateUV(obj)
|
||||
}
|
||||
})
|
||||
} else if (mode === 'move') {
|
||||
Vertexsnap.cubes.forEach(function(obj) {
|
||||
var cube_pos = new THREE.Vector3().copy(global_delta)
|
||||
|
||||
if (Format.bone_rig && obj.parent instanceof Group && obj.mesh.parent) {
|
||||
var q = obj.mesh.parent.getWorldQuaternion(new THREE.Quaternion()).inverse();
|
||||
cube_pos.applyQuaternion(q);
|
||||
}
|
||||
if (Format.rotate_cubes) {
|
||||
obj.origin.V3_add(cube_pos);
|
||||
}
|
||||
var in_box = obj.moveVector(cube_pos.toArray());
|
||||
if (!in_box && Format.canvas_limit && !settings.deactivate_size_limit.value) {
|
||||
Blockbench.showMessageBox({translateKey: 'canvas_limit_error'})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vertexsnap.removeVertexes()
|
||||
@ -518,7 +514,7 @@ function setScaleAllPivot(mode) {
|
||||
}
|
||||
function scaleAllSelectOverflow() {
|
||||
cancelScaleAll()
|
||||
selected.length = 0;
|
||||
selected.empty();
|
||||
scaleAll.overflow.forEach(obj => {
|
||||
obj.selectLow()
|
||||
})
|
||||
@ -601,24 +597,36 @@ function moveElementsInSpace(difference, axis) {
|
||||
if (el.resizable) el.to[axis] += difference;
|
||||
if (el.rotatable) el.origin[axis] += difference;
|
||||
} else {
|
||||
let move_origin = !!group;
|
||||
if (group_m) {
|
||||
var m = group_m
|
||||
} else {
|
||||
var m = new THREE.Vector3();
|
||||
m[getAxisLetter(axis)] = difference;
|
||||
|
||||
var rotation = new THREE.Quaternion();
|
||||
if (el.mesh) {
|
||||
el.mesh.getWorldQuaternion(rotation);
|
||||
} else if (el.parent instanceof Group) {
|
||||
el.parent.mesh.getWorldQuaternion(rotation);
|
||||
|
||||
let parent = el.parent;
|
||||
while (parent instanceof Group) {
|
||||
if (!parent.rotation.allEqual(0)) break;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
if (parent == 'root') {
|
||||
// If none of the parent groups are rotated, move origin.
|
||||
move_origin = true;
|
||||
} else {
|
||||
var rotation = new THREE.Quaternion();
|
||||
if (el.mesh) {
|
||||
el.mesh.getWorldQuaternion(rotation);
|
||||
} else if (el.parent instanceof Group) {
|
||||
el.parent.mesh.getWorldQuaternion(rotation);
|
||||
}
|
||||
m.applyQuaternion(rotation.inverse());
|
||||
}
|
||||
m.applyQuaternion(rotation.inverse());
|
||||
}
|
||||
|
||||
if (el.movable) el.from.V3_add(m.x, m.y, m.z);
|
||||
if (el.resizable) el.to.V3_add(m.x, m.y, m.z);
|
||||
if (group) {
|
||||
if (move_origin) {
|
||||
if (el.rotatable) el.origin.V3_add(m.x, m.y, m.z);
|
||||
}
|
||||
}
|
||||
@ -1315,13 +1323,16 @@ BARS.defineActions(function() {
|
||||
new Action('toggle_visibility', {
|
||||
icon: 'visibility',
|
||||
category: 'transform',
|
||||
condition: {modes: ['edit']},
|
||||
click: function () {toggleCubeProperty('visibility')}
|
||||
})
|
||||
new Action('toggle_locked', {
|
||||
icon: 'fas.fa-lock',
|
||||
category: 'transform',
|
||||
click: function () {toggleCubeProperty('locked')}
|
||||
})
|
||||
new Action('toggle_export', {
|
||||
icon: 'save',
|
||||
category: 'transform',
|
||||
condition: {modes: ['edit']},
|
||||
click: function () {toggleCubeProperty('export')}
|
||||
})
|
||||
new Action('toggle_autouv', {
|
||||
@ -1339,7 +1350,7 @@ BARS.defineActions(function() {
|
||||
new Action('toggle_mirror_uv', {
|
||||
icon: 'icon-mirror_x',
|
||||
category: 'transform',
|
||||
condition: () => Project.box_uv && Modes.edit,
|
||||
condition: () => Project.box_uv && (Modes.edit || Modes.paint),
|
||||
click: function () {toggleCubeProperty('shade')}
|
||||
})
|
||||
new Action('update_autouv', {
|
||||
|
21
js/util.js
21
js/util.js
@ -162,6 +162,9 @@ Math.lerp = function(a,b,m) {
|
||||
Math.isBetween = function(n, a, b) {
|
||||
return (n - a) * (n - b) <= 0
|
||||
}
|
||||
Math.epsilon = function(a, b, epsilon) {
|
||||
return Math.abs(b - a) < epsilon
|
||||
}
|
||||
Math.trimDeg = function(a) {
|
||||
return (a+180*15)%360-180
|
||||
}
|
||||
@ -181,13 +184,23 @@ Math.areMultiples = function(n1, n2) {
|
||||
(n2/n1)%1 === 0
|
||||
)
|
||||
}
|
||||
Math.getNextPower =function(num, min) {
|
||||
Math.getNextPower = function(num, min) {
|
||||
var i = min ? min : 2
|
||||
while (i < num && i < 4000) {
|
||||
i *= 2
|
||||
}
|
||||
return i;
|
||||
}
|
||||
Math.snapToValues = function(val, snap_points, epsilon = 12) {
|
||||
let snaps = snap_points.slice().sort((a, b) => {
|
||||
return Math.abs(val-a) - Math.abs(val-b)
|
||||
})
|
||||
if (Math.abs(snaps[0] - val) < epsilon) {
|
||||
return snaps[0]
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
function trimFloatNumber(val) {
|
||||
if (val == '') return val;
|
||||
var string = val.toFixed(4)
|
||||
@ -332,13 +345,17 @@ Array.prototype.remove = function (item) { {
|
||||
}
|
||||
}
|
||||
Array.prototype.empty = function() {
|
||||
this.length = 0;
|
||||
this.splice(0, Infinity);
|
||||
return this;
|
||||
}
|
||||
Array.prototype.purge = function() {
|
||||
this.splice(0, Infinity);
|
||||
return this;
|
||||
}
|
||||
Array.prototype.replace = function(items) {
|
||||
this.splice(0, Infinity, ...items);
|
||||
return this;
|
||||
}
|
||||
Array.prototype.findInArray = function(key, value) {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
if (this[i][key] === value) return this[i]
|
||||
|
@ -33,6 +33,9 @@ function initializeWebApp() {
|
||||
}
|
||||
})
|
||||
}
|
||||
if (Blockbench.browser == 'firefox') {
|
||||
document.body.style.imageRendering = 'crisp-edges'
|
||||
}
|
||||
|
||||
}
|
||||
setInterval(function() {
|
||||
|
38
lang/de.json
38
lang/de.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Abbrechen",
|
||||
"action.slider_inflate": "Aufblasen",
|
||||
"action.slider_inflate.desc": "Vergrößert Elemente in alle Richtungen, ohne dabei die Textur zu verändern",
|
||||
"action.brush_mode": "Pinselmodus",
|
||||
"action.slider_brush_size": "Radius",
|
||||
"action.slider_brush_size.desc": "Radius des Pinsels in Pixeln",
|
||||
"action.slider_brush_opacity": "Deckkraft",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Aktuelle Version",
|
||||
"dialog.update.installed": "Installierte Version",
|
||||
"dialog.update.update": "Aktualisieren",
|
||||
"action.brush_mode.brush": "Rund",
|
||||
"action.brush_mode.noise": "Rauschen",
|
||||
"action.vertex_snap_mode.move": "Verschieben",
|
||||
"action.vertex_snap_mode.scale": "Größe ändern",
|
||||
"action.open_model_folder": "Modellordner öffnen",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Beeinflusse die Größe des Pinsels bei Benutzung von einem Stylus",
|
||||
"settings.brush_modifier.pressure": "Druck",
|
||||
"settings.brush_modifier.tilt": "Neigung",
|
||||
"settings.class_export_version": "Mod-Entity Exportversopm",
|
||||
"settings.class_export_version.desc": "Die Spielversion, für die Entitymodelle für Mods exportiert werden",
|
||||
"category.color": "Farbe",
|
||||
"action.import_theme": "Theme importieren",
|
||||
"action.export_theme": "Theme exportieren",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Erstellt eine Palette aus einer Textur",
|
||||
"action.sort_palette": "Palette sortieren",
|
||||
"action.sort_palette.desc": "Sortiert alle Farben der Palette nach Farbton und Helligkeit",
|
||||
"action.clear_palette": "Palette leeren",
|
||||
"action.clear_palette.desc": "Alle Farben aus der Palette entfernen",
|
||||
"action.timelapse": "Zeitraffer...",
|
||||
"action.timelapse.desc": "Zeichnet eine Zeitrafferaufnahme von der Benutzung von Blockbench auf",
|
||||
"action.add_keyframe": "Keyframe hinzufügen",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Ausschneiden",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Spiegeln (X)",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Spiegeln (Y)",
|
||||
"uv_editor.copy_paste_tool.rotate": "Um 90 Grad drehen"
|
||||
"uv_editor.copy_paste_tool.rotate": "Um 90 Grad drehen",
|
||||
"dialog.project.modded_entity_version": "Exportversion",
|
||||
"dialog.save_angle.position": "Kameraposition",
|
||||
"dialog.save_angle.target": "Zielpunkt",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Fensterrahmen",
|
||||
"layout.color.frame.desc": "Rand und Titelleiste des Fensters",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Palette laden",
|
||||
"action.load_palette.desc": "Eine der mitgelieferten Paletten laden",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "Verwendet",
|
||||
"menu.palette.load.empty": "Leer",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
51
lang/en.json
51
lang/en.json
@ -230,6 +230,7 @@
|
||||
"dialog.project.parent": "Parent Model",
|
||||
"dialog.project.geoname": "Model Identifier",
|
||||
"dialog.project.openparent": "Open Parent",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.project.ao": "Ambient Occlusion",
|
||||
"dialog.project.box_uv": "Box UV",
|
||||
"dialog.project.width": "Texture Width",
|
||||
@ -328,6 +329,8 @@
|
||||
"dialog.save_angle.projection": "Projection",
|
||||
"dialog.save_angle.projection.perspective": "Perspective",
|
||||
"dialog.save_angle.projection.orthographic": "Orthographic",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
|
||||
"dialog.input.title": "Input",
|
||||
|
||||
@ -335,7 +338,6 @@
|
||||
"dialog.update.refresh": "Refresh",
|
||||
"dialog.update.up_to_date": "Blockbench is up to date!",
|
||||
"dialog.update.connecting": "Connecting to server",
|
||||
"dialog.update.refresh": "Retry",
|
||||
"dialog.update.no_connection": "No internet connection",
|
||||
"dialog.update.latest": "Latest Version",
|
||||
"dialog.update.installed": "Installed Version",
|
||||
@ -360,8 +362,9 @@
|
||||
"dialog.model_stats.faces": "Faces",
|
||||
|
||||
"dialog.skin.title": "Create Skin",
|
||||
"dialog.skin.model": "Skin",
|
||||
"dialog.skin.model": "Model",
|
||||
"dialog.skin.texture": "Texture (Optional)",
|
||||
"dialog.skin.pose": "Pose",
|
||||
|
||||
"dialog.settings.settings": "Settings",
|
||||
"dialog.settings.keybinds": "Keybindings",
|
||||
@ -390,6 +393,8 @@
|
||||
"layout.color.border.desc": "Border of buttons and inputs",
|
||||
"layout.color.accent": "Accent",
|
||||
"layout.color.accent.desc": "Slider thumb and other details",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"layout.color.grid": "Grid",
|
||||
"layout.color.grid.desc": "3D preview grid",
|
||||
"layout.color.wireframe": "Wireframe",
|
||||
@ -465,10 +470,12 @@
|
||||
|
||||
"settings.base_grid": "Small Grid",
|
||||
"settings.base_grid.desc": "Show small grid and axes",
|
||||
"settings.large_grid": "Large Grid",
|
||||
"settings.large_grid.desc": "Show 3x3 block grid",
|
||||
"settings.full_grid": "Full Large Grid",
|
||||
"settings.full_grid.desc": "Show 3x3 precise grid",
|
||||
"settings.large_grid": "Block Grid",
|
||||
"settings.large_grid.desc": "Show 16x16 block-size grid",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"settings.full_grid": "Precise Block Grid",
|
||||
"settings.full_grid.desc": "Show pixel-precise block grid",
|
||||
"settings.large_box": "Large Box",
|
||||
"settings.large_box.desc": "Show 3x3 block boundaries",
|
||||
"settings.display_grid": "Display Mode",
|
||||
@ -516,8 +523,6 @@
|
||||
"settings.brush_modifier.tilt": "Tilt",
|
||||
"settings.brush_modifier.none": "None",
|
||||
|
||||
"settings.dialog_unsaved_textures": "Unsaved Textures",
|
||||
"settings.dialog_unsaved_textures.desc": "Show \"Unsaved Textures\" dialog",
|
||||
"settings.dialog_larger_cubes": "Model Too Large",
|
||||
"settings.dialog_larger_cubes.desc": "Show \"Model Too Large\" dialog",
|
||||
"settings.dialog_rotation_limit": "Rotation Limits",
|
||||
@ -527,8 +532,6 @@
|
||||
"settings.minifiedout.desc": "Write JSON file in one line",
|
||||
"settings.export_groups": "Export Groups",
|
||||
"settings.export_groups.desc": "Save groups in blockmodel files",
|
||||
"settings.class_export_version": "Modded Entity Export Version",
|
||||
"settings.class_export_version.desc": "The format version for modded entity models",
|
||||
"settings.credit": "Credit Comment",
|
||||
"settings.credit.desc": "Add a credit comment to exported files",
|
||||
"settings.sketchfab_token": "Sketchfab Token",
|
||||
@ -698,6 +701,8 @@
|
||||
"action.reset_keybindings.desc": "Reset all keybindings to Blockbench's defaults",
|
||||
"action.load_plugin": "Load Plugin from File",
|
||||
"action.load_plugin.desc": "Load a plugin by importing the source file",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.reload_plugins": "Reload Plugins",
|
||||
"action.reload_plugins.desc": "Reload all development plugins",
|
||||
"action.reset_layout": "Reset Layout",
|
||||
@ -732,7 +737,7 @@
|
||||
"action.outliner_toggle": "Toggle More Options",
|
||||
"action.outliner_toggle.desc": "Toggles switches for more options in the outliner",
|
||||
"action.cube_counter": "Cube Counter",
|
||||
"action.cube_counter": "Displays the current number of cubes and other statistics",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
|
||||
"action.duplicate": "Duplicate",
|
||||
"action.duplicate.desc": "Duplicates the selected cubes or group",
|
||||
@ -740,6 +745,8 @@
|
||||
"action.delete.desc": "Deletes the selected cubes or group",
|
||||
"action.sort_outliner": "Sort Outliner",
|
||||
"action.sort_outliner.desc": "Sort the outliner alphabetically",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.element_colors": "Cube Colors",
|
||||
"action.element_colors.desc": "Show cube colors in the outliner",
|
||||
"action.select_window": "Select...",
|
||||
@ -764,8 +771,8 @@
|
||||
"action.generate_palette.desc": "Generate palette from a texture",
|
||||
"action.sort_palette": "Sort Palette",
|
||||
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
|
||||
"action.clear_palette": "Clear Palette",
|
||||
"action.clear_palette.desc": "Remove all colors from the palette",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
|
||||
"action.transform_space": "Transform Space",
|
||||
"action.transform_space.desc": "Default transform space for elements and bones",
|
||||
@ -788,6 +795,8 @@
|
||||
"action.toggle_visibility.desc": "Toggle the visibility of the selected cubes",
|
||||
"action.toggle_export": "Toggle Export",
|
||||
"action.toggle_export.desc": "Toggle the export setting of the selected cubes",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.toggle_autouv": "Toggle Auto UV",
|
||||
"action.toggle_autouv.desc": "Toggle the auto UV setting of the selected cubes",
|
||||
"action.toggle_shade": "Toggle Shading",
|
||||
@ -801,6 +810,10 @@
|
||||
|
||||
"action.add_display_preset": "New Preset",
|
||||
"action.add_display_preset.desc": "Add a new display setting preset",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.gui_light": "GUI Light",
|
||||
"action.gui_light.desc": "Select the way the item is lit in the inventory",
|
||||
"action.gui_light.side": "Side Light",
|
||||
@ -924,6 +937,8 @@
|
||||
"action.change_keyframe_file.desc": "Select an audio file to preview a sound effect.",
|
||||
"action.reset_keyframe": "Reset Keyframe",
|
||||
"action.reset_keyframe.desc": "Reset all values of the selected keyframes",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.reverse_keyframes": "Reverse Keyframes",
|
||||
"action.reverse_keyframes.desc": "Reverse the order of the selected keyframes",
|
||||
"action.select_all_keyframes": "Select All Keyframes",
|
||||
@ -942,8 +957,9 @@
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"action.bring_up_all_animations": "Bring Up All Animations",
|
||||
"action.bring_up_all_animations": "Bring Up All Animators",
|
||||
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.clear_timeline": "Clear Timeline",
|
||||
"action.clear_timeline.desc": "Clear all unselected bones from the timeline",
|
||||
"action.select_effect_animator": "Animate Effects",
|
||||
@ -951,6 +967,7 @@
|
||||
"action.timeline_focus": "Channel",
|
||||
"action.timeline_focus.desc": "Select the animation channels to display in the timeline",
|
||||
"action.timeline_focus.all": "All",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
|
||||
|
||||
"timeline.rotation": "Rotation",
|
||||
@ -1007,8 +1024,8 @@
|
||||
"menu.group.sort": "Sort",
|
||||
"menu.group.resolve": "Resolve",
|
||||
|
||||
"menu.palette.load": "Load Palette",
|
||||
"menu.palette.load.default": "Default",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
|
||||
"menu.texture.face": "Apply to Face",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
@ -1077,6 +1094,7 @@
|
||||
"cube.color.lime": "Lime",
|
||||
|
||||
"switches.visibility": "Visibility",
|
||||
"switches.lock": "Lock",
|
||||
"switches.export": "Export",
|
||||
"switches.shading": "Shade",
|
||||
"switches.mirror": "Mirror UV",
|
||||
@ -1152,6 +1170,9 @@
|
||||
"direction.top": "Top",
|
||||
"direction.bottom": "Bottom",
|
||||
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left",
|
||||
|
||||
"dialog.edit_session.title": "Edit Session",
|
||||
"edit_session.username": "Username",
|
||||
"edit_session.token": "Token",
|
||||
|
38
lang/es.json
38
lang/es.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Cancelar",
|
||||
"action.slider_inflate": "Inflar",
|
||||
"action.slider_inflate.desc": "Inflar cubos en todas las direcciones sin cambiar el UV",
|
||||
"action.brush_mode": "Modo Pincel",
|
||||
"action.slider_brush_size": "Tamaño",
|
||||
"action.slider_brush_size.desc": "Radio del pincel en píxeles",
|
||||
"action.slider_brush_opacity": "Opacidad",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Última version",
|
||||
"dialog.update.installed": "Versión instalada",
|
||||
"dialog.update.update": "Actualizar",
|
||||
"action.brush_mode.brush": "Redondo",
|
||||
"action.brush_mode.noise": "Ruido",
|
||||
"action.vertex_snap_mode.move": "Mover",
|
||||
"action.vertex_snap_mode.scale": "Reescalar",
|
||||
"action.open_model_folder": "Abrir la Carpeta del Modelo",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Modifica el tamaño del pincel al usar un lápiz",
|
||||
"settings.brush_modifier.pressure": "Presión",
|
||||
"settings.brush_modifier.tilt": "Inclinar",
|
||||
"settings.class_export_version": "Versión de Exportación de Entidad de Mod",
|
||||
"settings.class_export_version.desc": "La versión de formato para modelos de entidades de mod",
|
||||
"category.color": "Color",
|
||||
"action.import_theme": "Importar Tema",
|
||||
"action.export_theme": "Exportar Tema",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Genera la paleta a partir de una textura",
|
||||
"action.sort_palette": "Organizar Paleta",
|
||||
"action.sort_palette.desc": "Organiza todos los colores de la paleta por color y brillo",
|
||||
"action.clear_palette": "Limpiar Paleta",
|
||||
"action.clear_palette.desc": "Elimina todos los colores de la Paleta",
|
||||
"action.timelapse": "Timelapse...",
|
||||
"action.timelapse.desc": "Graba un timelapse de tu proceso de modelaje",
|
||||
"action.add_keyframe": "Añadir Frame Clave",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cortar",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Invertir X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Invertir Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotar 90 Grados"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotar 90 Grados",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
38
lang/fr.json
38
lang/fr.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Annuler",
|
||||
"action.slider_inflate": "Gonflement",
|
||||
"action.slider_inflate.desc": "Grossir les cubes dans toutes les directions sans changer les UV.",
|
||||
"action.brush_mode": "Mode pinceau",
|
||||
"action.slider_brush_size": "Taille",
|
||||
"action.slider_brush_size.desc": "Rayon du pinceau en pixels",
|
||||
"action.slider_brush_opacity": "Opacité",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Dernière version",
|
||||
"dialog.update.installed": "Version installée",
|
||||
"dialog.update.update": "Mettre à jour",
|
||||
"action.brush_mode.brush": "Rond",
|
||||
"action.brush_mode.noise": "Bruit",
|
||||
"action.vertex_snap_mode.move": "Déplacer",
|
||||
"action.vertex_snap_mode.scale": "Redimensionner",
|
||||
"action.open_model_folder": "Ouvrir le dossier du modèle",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Modifier la taille du pinceau avec un stylet",
|
||||
"settings.brush_modifier.pressure": "Pression",
|
||||
"settings.brush_modifier.tilt": "Inclinaison",
|
||||
"settings.class_export_version": "Version d'export d'entité moddée",
|
||||
"settings.class_export_version.desc": "Version de format pour des modèles d'entités moddées",
|
||||
"category.color": "Couleur",
|
||||
"action.import_theme": "Thème d'importation",
|
||||
"action.export_theme": "Thème d'exportation",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Générer une palette à partir d'une texture",
|
||||
"action.sort_palette": "Trier palette",
|
||||
"action.sort_palette.desc": "Trier toutes les couleurs par teinte et luminosité",
|
||||
"action.clear_palette": "Vider la palette",
|
||||
"action.clear_palette.desc": "Retire toutes les couleurs de la palette",
|
||||
"action.timelapse": "Timelapse…",
|
||||
"action.timelapse.desc": "Enregistrer un timelapse de la modélisation",
|
||||
"action.add_keyframe": "Ajouter une keyframe",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Couper",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Miroir X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Miroir Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotation de 90 degrés"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotation de 90 degrés",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
74
lang/it.json
74
lang/it.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Annulla",
|
||||
"action.slider_inflate": "Gonfiare",
|
||||
"action.slider_inflate.desc": "Gonfiare cubi in tutte le direzioni non modificando l'UV",
|
||||
"action.brush_mode": "Modalità Pennello",
|
||||
"action.slider_brush_size": "Dimensione",
|
||||
"action.slider_brush_size.desc": "Raggio del pennello in pixel",
|
||||
"action.slider_brush_opacity": "Opacità",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Versione più Recente",
|
||||
"dialog.update.installed": "Versione Installata",
|
||||
"dialog.update.update": "Aggiornamento",
|
||||
"action.brush_mode.brush": "Pennello",
|
||||
"action.brush_mode.noise": "Sfumatura",
|
||||
"action.vertex_snap_mode.move": "Muovi",
|
||||
"action.vertex_snap_mode.scale": "Scala",
|
||||
"action.open_model_folder": "Apri Cartella Modello",
|
||||
@ -875,7 +872,7 @@
|
||||
"panel.element.origin": "Origine",
|
||||
"panel.element.rotation": "Rotazione",
|
||||
"message.canvas_limit_error.title": "Errore di Limite della Tela",
|
||||
"message.canvas_limit_error.message": "The action could not be performed correctly because the format limits the canvas to 48 units. Shift the pivot point to prevent this.",
|
||||
"message.canvas_limit_error.message": "L'azione non può essere eseguita correttamente perché il formato limita la tela a 48 unità. Spostare il punto di articolazione per impedirlo.",
|
||||
"data.effect": "Effetto",
|
||||
"generic.name": "Nome",
|
||||
"settings.recent_projects": "Limite Modelli Recenti",
|
||||
@ -929,7 +926,7 @@
|
||||
"message.timelapse_start": "Timelapse avviato",
|
||||
"message.timelapse_stop": "Timelapse interrotto",
|
||||
"message.import_palette.replace_palette": "Sostituisci vecchia tavolozza",
|
||||
"message.import_palette.threshold": "Merge Threshold",
|
||||
"message.import_palette.threshold": "Unisci soglia",
|
||||
"dialog.timelapse.interval": "Intervallo (Secondi)",
|
||||
"dialog.timelapse.source": "Sorgente",
|
||||
"dialog.timelapse.source.interface": "Interfaccia",
|
||||
@ -941,15 +938,13 @@
|
||||
"layout.css": "CSS Personalizzato",
|
||||
"settings.category.paint": "Dipingere",
|
||||
"settings.deactivate_size_limit": "Disattiva Limite Dimensioni",
|
||||
"settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
|
||||
"settings.deactivate_size_limit.desc": "Disattiva il limite di dimensioni per formati di modelli specifici. ATTENZIONE: ciò può causare modelli non validi.",
|
||||
"settings.brush_opacity_modifier": "Modificatore Opacità Pennello",
|
||||
"settings.brush_opacity_modifier.desc": "Modifica l'opacità del pennello quando viene utilizzato uno stilo",
|
||||
"settings.brush_size_modifier": "Modificatore Dimensioni Pennello",
|
||||
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
|
||||
"settings.brush_size_modifier.desc": "Modifica le dimensioni del pennello quando si utilizza uno stilo",
|
||||
"settings.brush_modifier.pressure": "Pressione",
|
||||
"settings.brush_modifier.tilt": "Inclinazione",
|
||||
"settings.class_export_version": "Versione Entity Export per Mod",
|
||||
"settings.class_export_version.desc": "La versione del formato per modelli entity per i mod",
|
||||
"category.color": "Colore",
|
||||
"action.import_theme": "Importa Tema",
|
||||
"action.export_theme": "Esporta Tema",
|
||||
@ -969,13 +964,11 @@
|
||||
"action.generate_palette.desc": "Genera una tavolozza da una texture",
|
||||
"action.sort_palette": "Ordina Tavolozza",
|
||||
"action.sort_palette.desc": "Ordina tutti i colori della tavolozza per colore e luminosità",
|
||||
"action.clear_palette": "Pulisci Tavolozza",
|
||||
"action.clear_palette.desc": "Rimuovi tutti i colori dalla tavolozza",
|
||||
"action.timelapse": "Timelapse...",
|
||||
"action.timelapse.desc": "Registra un timelapse del tuo processo di modellazione",
|
||||
"action.add_keyframe": "Aggiungi Fotogramma",
|
||||
"action.add_keyframe.desc": "Aggiungi un fotogramma automaticamente. Premi shift per forzare valori predefinti",
|
||||
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
|
||||
"action.bring_up_all_animations.desc": "Porta tutti gli animatori modificati nella sequenza temporale",
|
||||
"timeline.timeline": "Istruzioni",
|
||||
"menu.palette.load": "Carica Tavolozza",
|
||||
"menu.palette.load.default": "Predefinita",
|
||||
@ -1012,21 +1005,21 @@
|
||||
"menu.help.donate": "Dona",
|
||||
"menu.help.about": "Informazioni",
|
||||
"menu.preview.background.clipboard": "Carica dagli Appunti",
|
||||
"dialog.ignore": "Ignore",
|
||||
"generic.unset": "Unset",
|
||||
"dialog.ignore": "Ignora",
|
||||
"generic.unset": "Non settato",
|
||||
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
|
||||
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
|
||||
"dialog.resize_texture.fill": "Fill with",
|
||||
"dialog.resize_texture.fill.transparent": "Transparent",
|
||||
"dialog.resize_texture.fill.color": "Color",
|
||||
"dialog.resize_texture.fill.repeat": "Repeat",
|
||||
"dialog.resize_texture.fill.stretch": "Stretch",
|
||||
"message.invalid_builtin_parent.message": "Il collegamento al modello principale non valido '% 0' è stato rimosso per esportare un modello valido.",
|
||||
"dialog.resize_texture.fill": "Riempire con",
|
||||
"dialog.resize_texture.fill.transparent": "Trasparente",
|
||||
"dialog.resize_texture.fill.color": "Colore",
|
||||
"dialog.resize_texture.fill.repeat": "Ripeti",
|
||||
"dialog.resize_texture.fill.stretch": "Allunga",
|
||||
"dialog.scale.element_pivot": "Element Pivot",
|
||||
"dialog.scale.selection_center": "Selection Center",
|
||||
"dialog.create_gif.length_mode": "Length Mode",
|
||||
"dialog.create_gif.length_mode.seconds": "Seconds",
|
||||
"dialog.create_gif.length_mode.frames": "Frames",
|
||||
"dialog.create_gif.length_mode.animation": "Animation Length",
|
||||
"dialog.scale.selection_center": "Centro di Selezione",
|
||||
"dialog.create_gif.length_mode": "Modalità lunghezza",
|
||||
"dialog.create_gif.length_mode.seconds": "Secondi",
|
||||
"dialog.create_gif.length_mode.frames": "Montatura",
|
||||
"dialog.create_gif.length_mode.animation": "Lunghezza della'animazione",
|
||||
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
|
||||
"dialog.save_angle.projection": "Projection",
|
||||
"dialog.save_angle.projection.perspective": "Perspective",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
38
lang/ja.json
38
lang/ja.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "キャンセル",
|
||||
"action.slider_inflate": "Inflate",
|
||||
"action.slider_inflate.desc": "UVを変えずにキューブを膨張させる",
|
||||
"action.brush_mode": "Brush Mode",
|
||||
"action.slider_brush_size": "Size",
|
||||
"action.slider_brush_size.desc": "ブラシの半径",
|
||||
"action.slider_brush_opacity": "Opacity",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "最新のバージョン",
|
||||
"dialog.update.installed": "インストールされたバージョン",
|
||||
"dialog.update.update": "更新する",
|
||||
"action.brush_mode.brush": "Round",
|
||||
"action.brush_mode.noise": "Noise",
|
||||
"action.vertex_snap_mode.move": "Move",
|
||||
"action.vertex_snap_mode.scale": "Scale",
|
||||
"action.open_model_folder": "モデルフォルダを開く",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "ブラシの大きさを変更します",
|
||||
"settings.brush_modifier.pressure": "筆圧",
|
||||
"settings.brush_modifier.tilt": "チルト",
|
||||
"settings.class_export_version": "エンティティエクスポートバージョン",
|
||||
"settings.class_export_version.desc": "modエンティティモデルのバージョンを変更します",
|
||||
"category.color": "カラー",
|
||||
"action.import_theme": "テーマをインポート",
|
||||
"action.export_theme": "テーマをエクスポート",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "テクスチャからパレットを生成します",
|
||||
"action.sort_palette": "ソート",
|
||||
"action.sort_palette.desc": "パレット上のすべてのカラーを色と明るさで並べ替えます",
|
||||
"action.clear_palette": "クリアー",
|
||||
"action.clear_palette.desc": "パレット上のすべてのカラーを削除します",
|
||||
"action.timelapse": "タイムラプス…",
|
||||
"action.timelapse.desc": "モデリングプロセスのタイムラプスを記録します",
|
||||
"action.add_keyframe": "キーフレームを追加",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "カット",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90°"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90°",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
162
lang/nl.json
162
lang/nl.json
@ -83,7 +83,7 @@
|
||||
"message.default_textures.select": "Selecteer de standaard \"textures\"-map",
|
||||
"message.image_editor.title": "Selecteer een afbeelding-bewerker",
|
||||
"message.image_editor.file": "Selecteer Bestand...",
|
||||
"message.image_editor.exe": "Selecteer een foto-editor uitvoerbaar bestand",
|
||||
"message.image_editor.exe": "Selecteer een foto-bewerker uitvoerbaar bestand",
|
||||
"message.display_skin.title": "Toon Skin",
|
||||
"message.display_skin.message": "Selecteer een skin bestand van je computer of vul een spelernaam in",
|
||||
"message.display_skin.upload": "Upload Skin",
|
||||
@ -206,8 +206,8 @@
|
||||
"settings.show_actions.desc": "Toon alle acties in de status balk",
|
||||
"settings.backup_interval": "Backup Frequentie",
|
||||
"settings.backup_interval.desc": "Frequentie van de automatische backups in minuten",
|
||||
"settings.origin_size": "Oorsprong Markeerder",
|
||||
"settings.origin_size.desc": "Grootte van de rotatie oorsprong",
|
||||
"settings.origin_size": "Draaipunt Markeerder",
|
||||
"settings.origin_size.desc": "Grootte van rotatie draaipunt markeerder",
|
||||
"settings.control_size": "As Controle Grootte",
|
||||
"settings.control_size.desc": "Grootte van de 3 assen controle gereedschap",
|
||||
"settings.display_skin": "Toon Skin",
|
||||
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Annuleer",
|
||||
"action.slider_inflate": "Opblazen",
|
||||
"action.slider_inflate.desc": "Kubussen alle kanten op opblazen zonder de UV te veranderen",
|
||||
"action.brush_mode": "Mode",
|
||||
"action.slider_brush_size": "Grootte",
|
||||
"action.slider_brush_size.desc": "Formaat van de kwast",
|
||||
"action.slider_brush_opacity": "Doorzichtigheid",
|
||||
@ -302,7 +301,7 @@
|
||||
"action.resize_tool": "Formaat veranderen",
|
||||
"action.resize_tool.desc": "Gereedschap om elementen te selecteren en te vergrootten",
|
||||
"action.brush_tool": "Verfkwast",
|
||||
"action.brush_tool.desc": "Gereedschap om te tekenen op bitmap texturen op oppervlakken of in de UV editor.",
|
||||
"action.brush_tool.desc": "Gereedschap om te tekenen op bitmap texturen op oppervlakken of in de UV bewerker.",
|
||||
"action.vertex_snap_tool": "Hoeken Snap",
|
||||
"action.vertex_snap_tool.desc": "Beweeg een kubus naar een ander kubus door twee hoeken te verbinden",
|
||||
"action.swap_tools": "Verwissel Gereedschap",
|
||||
@ -413,8 +412,8 @@
|
||||
"action.save_textures.desc": "Sla alle niet-opgeslagen texturen op",
|
||||
"action.animated_textures": "Start Geanimeerde Texturen",
|
||||
"action.animated_textures.desc": "Start en pauzeer de weergave van geanimeerde texturen",
|
||||
"action.origin_to_geometry": "Centreer Oorsprong",
|
||||
"action.origin_to_geometry.desc": "Zet de oorsprong naar het midden van de geometrie",
|
||||
"action.origin_to_geometry": "Centreer Draaipunt",
|
||||
"action.origin_to_geometry.desc": "Zet het draaipunt naar het midden van de geometrie",
|
||||
"action.rescale_toggle": "Zet Herschaal Aan/Uit",
|
||||
"action.rescale_toggle.desc": "Herschaal kubussen gebaseerd op hun huidige rotatie",
|
||||
"action.bone_reset_toggle": "Herstel bot",
|
||||
@ -488,7 +487,7 @@
|
||||
"panel.display": "Toning",
|
||||
"panel.textures": "Afbeeldingen",
|
||||
"panel.outliner": "Omlijning",
|
||||
"uv_editor.title": "UV Editor",
|
||||
"uv_editor.title": "UV Bewerker",
|
||||
"uv_editor.all_faces": "Alle",
|
||||
"uv_editor.no_faces": "Geen",
|
||||
"face.north": "Noord",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Laatste Versie",
|
||||
"dialog.update.installed": "Geïnstalleerde Versie",
|
||||
"dialog.update.update": "Update",
|
||||
"action.brush_mode.brush": "Penseel",
|
||||
"action.brush_mode.noise": "Lawaai ",
|
||||
"action.vertex_snap_mode.move": "Beweeg",
|
||||
"action.vertex_snap_mode.scale": "Schaal",
|
||||
"action.open_model_folder": "Open Model Map",
|
||||
@ -707,7 +704,7 @@
|
||||
"language_name": "Nederlands",
|
||||
"message.plugin_reload": "%0 lokale plugins herlaadden",
|
||||
"settings.brightness": "Helderheid",
|
||||
"settings.brightness.desc": "Helderheid van de ",
|
||||
"settings.brightness.desc": "Helderheid van de voorvertoning. Standaard is 50",
|
||||
"menu.preview.perspective.reset": "Herstel Camera",
|
||||
"action.fill_mode": "Vul Modus",
|
||||
"action.fill_mode.face": "Oppervlak",
|
||||
@ -725,7 +722,7 @@
|
||||
"keybindings.recording": "Neem Toetsbinding Op",
|
||||
"keybindings.press": "Druk op een knop of een combinatie van knoppen of klik ergens op het scherm om toetsbinding op te nemen",
|
||||
"action.pivot_tool": "Draai Gereedschap",
|
||||
"action.pivot_tool.desc": "Gereedschap om het pivot punt van de kubussen en botten te veranderen",
|
||||
"action.pivot_tool.desc": "Gereedschap om het Draaipunt van de kubussen en botten te veranderen",
|
||||
"action.slider_animation_speed": "Terugspeelsnelheid",
|
||||
"action.slider_animation_speed.desc": "Terugspeelsnelheid van de tijdlijn in percent",
|
||||
"action.previous_keyframe": "Vorige Keyframe",
|
||||
@ -747,7 +744,7 @@
|
||||
"settings.sketchfab_token": "Sketchfab Token",
|
||||
"settings.sketchfab_token.desc": "Token om blockbench te autoriseren om te uploaden naar u Sketchfab account",
|
||||
"panel.color": "Kleur",
|
||||
"data.origin": "Rotatie",
|
||||
"data.origin": "Draaipunt",
|
||||
"message.sketchfab.success": "Model succesvol geüpload",
|
||||
"message.sketchfab.error": "Gefaald om model up te loaden naar Sketchfab",
|
||||
"settings.outliner_colors": "Omlijning Kleuren",
|
||||
@ -872,10 +869,10 @@
|
||||
"panel.element": "Element",
|
||||
"panel.element.position": "Positie",
|
||||
"panel.element.size": "Grootte",
|
||||
"panel.element.origin": "Rotatie Punt",
|
||||
"panel.element.origin": "Draaipunt",
|
||||
"panel.element.rotation": "Rotatie",
|
||||
"message.canvas_limit_error.title": "Canvas limiet Error",
|
||||
"message.canvas_limit_error.message": "De actie kon niet correct worden uitgevoerd omdat het format het canvas limiteert tot 48 eenheden. Verschuif de rotatie oorsprong om dit te voorkomen.",
|
||||
"message.canvas_limit_error.message": "De actie kon niet correct worden uitgevoerd omdat het format het canvas limiteert tot 48 eenheden. Verschuif het draaipunt om dit te voorkomen.",
|
||||
"data.effect": "Effect",
|
||||
"generic.name": "Naam",
|
||||
"settings.recent_projects": "Recent Model Limiet",
|
||||
@ -908,8 +905,8 @@
|
||||
"action.slider_size.desc": "Herschaal kubussen op de %0 as",
|
||||
"action.slider_rotation": "Roteer %0",
|
||||
"action.slider_rotation.desc": "Roteer kubussen op de %0 as",
|
||||
"action.slider_origin": "Oorsprong %0",
|
||||
"action.slider_origin.desc": "Verplaats oorsprong op de %0 as",
|
||||
"action.slider_origin": "Draaipunt %0",
|
||||
"action.slider_origin.desc": "Verplaats draaipunt op de %0 as",
|
||||
"action.rotate_cw": "Roteer %0 +90",
|
||||
"action.rotate_cw.desc": "Roteer de geselecteerde kubussen 90° om de %0 as",
|
||||
"action.rotate_ccw": "Roteer %0 -90",
|
||||
@ -935,7 +932,7 @@
|
||||
"dialog.timelapse.source.interface": "Deactiveer het grootte limiet voor specifieke model formaten. WARNING: Dit kan ongeldige modellen veroorzaken.",
|
||||
"dialog.timelapse.source.locked": "Vastgezette Hoek",
|
||||
"dialog.timelapse.destination": "Bestemmingsmap",
|
||||
"layout.color.checkerboard": "Schaakbord",
|
||||
"layout.color.checkerboard": "Dambord",
|
||||
"layout.color.checkerboard.desc": "Achtergrond van canvas en UV editor",
|
||||
"layout.font.code": "Code Font",
|
||||
"layout.css": "Custom CSS",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Bewerk de kwast grootte wanneer een pen wordt gebruikt",
|
||||
"settings.brush_modifier.pressure": "Druk",
|
||||
"settings.brush_modifier.tilt": "Tilt",
|
||||
"settings.class_export_version": "Modded Entity Exporteer Versie",
|
||||
"settings.class_export_version.desc": "De formaat versie voor modded entity modellen",
|
||||
"category.color": "Kleur",
|
||||
"action.import_theme": "Importeer Thema",
|
||||
"action.export_theme": "Exporteer Thema",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Genereer palette van een textuur",
|
||||
"action.sort_palette": "Sorteer Palet",
|
||||
"action.sort_palette.desc": "Sorteer alle kleuren op het palet op basis van kleur en helderheid",
|
||||
"action.clear_palette": "Maak Palet Schoon",
|
||||
"action.clear_palette.desc": "Verwijder alle kleuren van het palet",
|
||||
"action.timelapse": "Timelapse...",
|
||||
"action.timelapse.desc": "Neem een timelapse van u modeleer proces op",
|
||||
"action.add_keyframe": "Voeg Keyframe toe",
|
||||
@ -1012,55 +1005,55 @@
|
||||
"menu.help.donate": "Doneer",
|
||||
"menu.help.about": "Over...",
|
||||
"menu.preview.background.clipboard": "Laad van Klembord",
|
||||
"dialog.ignore": "Ignore",
|
||||
"generic.unset": "Unset",
|
||||
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
|
||||
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
|
||||
"dialog.resize_texture.fill": "Fill with",
|
||||
"dialog.resize_texture.fill.transparent": "Transparent",
|
||||
"dialog.resize_texture.fill.color": "Color",
|
||||
"dialog.resize_texture.fill.repeat": "Repeat",
|
||||
"dialog.ignore": "Negeer",
|
||||
"generic.unset": "Ongezet",
|
||||
"message.invalid_builtin_parent.title": "Ongeldige Ingebouwde Ouder",
|
||||
"message.invalid_builtin_parent.message": "De link naar het ongeldige ouder model '%0' was verwijderd om een geldig model te exporteren",
|
||||
"dialog.resize_texture.fill": "Vul met",
|
||||
"dialog.resize_texture.fill.transparent": "Transparant",
|
||||
"dialog.resize_texture.fill.color": "Kleur",
|
||||
"dialog.resize_texture.fill.repeat": "Herhaal",
|
||||
"dialog.resize_texture.fill.stretch": "Stretch",
|
||||
"dialog.scale.element_pivot": "Element Pivot",
|
||||
"dialog.scale.selection_center": "Selection Center",
|
||||
"dialog.create_gif.length_mode": "Length Mode",
|
||||
"dialog.create_gif.length_mode.seconds": "Seconds",
|
||||
"dialog.create_gif.length_mode.frames": "Frames",
|
||||
"dialog.create_gif.length_mode.animation": "Animation Length",
|
||||
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
|
||||
"dialog.save_angle.projection": "Projection",
|
||||
"dialog.save_angle.projection.perspective": "Perspective",
|
||||
"dialog.save_angle.projection.orthographic": "Orthographic",
|
||||
"dialog.sketchfab_uploader.animations": "Animations",
|
||||
"dialog.settings.theme": "Theme",
|
||||
"dialog.scale.element_pivot": "Element Draaipunt",
|
||||
"dialog.scale.selection_center": "Selectie Midden",
|
||||
"dialog.create_gif.length_mode": "Lengte Modus",
|
||||
"dialog.create_gif.length_mode.seconds": "Seconden",
|
||||
"dialog.create_gif.length_mode.frames": "Beelden",
|
||||
"dialog.create_gif.length_mode.animation": "Animatie Lengte",
|
||||
"dialog.create_gif.length_mode.turntable": "Draaitafel Rotatie",
|
||||
"dialog.save_angle.projection": "Projectie",
|
||||
"dialog.save_angle.projection.perspective": "Perspectief",
|
||||
"dialog.save_angle.projection.orthographic": "Orthografisch",
|
||||
"dialog.sketchfab_uploader.animations": "Animaties",
|
||||
"dialog.settings.theme": "Thema",
|
||||
"settings.category.interface": "Interface",
|
||||
"settings.preview_checkerboard": "Preview Checkerboard",
|
||||
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
|
||||
"settings.uv_checkerboard": "UV Editor Checkerboard",
|
||||
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
|
||||
"category.paint": "Paint",
|
||||
"action.fill_mode.color_connected": "Connected Colors",
|
||||
"action.draw_shape_type": "Shape Type",
|
||||
"action.draw_shape_type.rectangle": "Rectangle",
|
||||
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
|
||||
"action.draw_shape_type.ellipse": "Ellipse",
|
||||
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
|
||||
"action.draw_shape_type.line": "Line",
|
||||
"action.mirror_painting": "Mirror Painting",
|
||||
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
|
||||
"action.lock_alpha": "Lock Alpha Channel",
|
||||
"action.lock_alpha.description": "Lock the transparency of all pixels",
|
||||
"action.draw_shape_tool": "Draw Shape",
|
||||
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
|
||||
"action.copy_paste_tool": "Copy Paste Tool",
|
||||
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
|
||||
"action.export_gltf": "Export As glTF",
|
||||
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
|
||||
"action.transform_space": "Transform Space",
|
||||
"action.transform_space.desc": "Default transform space for elements and bones",
|
||||
"action.transform_space.global": "Global",
|
||||
"action.transform_space.bone": "Bone",
|
||||
"action.transform_space.local": "Local",
|
||||
"settings.preview_checkerboard": "Preview Dambord",
|
||||
"settings.preview_checkerboard.desc": "Zet de dambord achtergrond achter de voorvertoning",
|
||||
"settings.uv_checkerboard": "UV Bewerker Dambord",
|
||||
"settings.uv_checkerboard.desc": "Zet de dambord achtergrond achter de UV bewerker",
|
||||
"category.paint": "Verf",
|
||||
"action.fill_mode.color_connected": "Verbonden Kleuren",
|
||||
"action.draw_shape_type": "Vorm Type",
|
||||
"action.draw_shape_type.rectangle": "Rechthoek",
|
||||
"action.draw_shape_type.rectangle_h": "Rechthoek (Hol)",
|
||||
"action.draw_shape_type.ellipse": "Elipse",
|
||||
"action.draw_shape_type.ellipse_h": "Elipse (Hol)",
|
||||
"action.draw_shape_type.line": "Lijn",
|
||||
"action.mirror_painting": "Spiegel Schilderij",
|
||||
"action.mirror_painting.description": "Spiegel je verfstreken naar de andere kant van het model",
|
||||
"action.lock_alpha": "Zet Alpha Kanaal Vast",
|
||||
"action.lock_alpha.description": "Zet de doorzichtigheid van alle pixels vast",
|
||||
"action.draw_shape_tool": "Teken Vorm",
|
||||
"action.draw_shape_tool.desc": "Gereedschap om simpele vormen op texturen tekenen",
|
||||
"action.copy_paste_tool": "Kopieer Plak Gereedschap",
|
||||
"action.copy_paste_tool.desc": "Gereedschap om selecties van texturen te kopiëren en te plakken",
|
||||
"action.export_gltf": "Exporteer Als glTF",
|
||||
"action.export_gltf.desc": "Exporteer model en animaties als glTF bestand om te gebruiken in andere 3D applicaties",
|
||||
"action.transform_space": "Transformeer Ruimte",
|
||||
"action.transform_space.desc": "Standaard transformeer ruimte voor elementen en botten",
|
||||
"action.transform_space.global": "Globaal",
|
||||
"action.transform_space.bone": "Bot",
|
||||
"action.transform_space.local": "Locaal",
|
||||
"action.toggle_camera_projection": "Toggle Camera Projection",
|
||||
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
|
||||
"action.load_camera_angle": "Camera Angle: %0",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
220
lang/pl.json
220
lang/pl.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Anuluj",
|
||||
"action.slider_inflate": "Nadmuchaj",
|
||||
"action.slider_inflate.desc": "Nadmuchaj kostki we wszystkich kierunkach, bez zmieniania UV.",
|
||||
"action.brush_mode": "Tryb pędzla",
|
||||
"action.slider_brush_size": "Wielkość",
|
||||
"action.slider_brush_size.desc": "Promień pędzla w pikselach",
|
||||
"action.slider_brush_opacity": "Nieprzezroczystość",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Najnowsza wersja",
|
||||
"dialog.update.installed": "Zainstalowana wersja",
|
||||
"dialog.update.update": "Aktualizacja",
|
||||
"action.brush_mode.brush": "Szczotka",
|
||||
"action.brush_mode.noise": "Mieszanie",
|
||||
"action.vertex_snap_mode.move": "Przesuń",
|
||||
"action.vertex_snap_mode.scale": "Skaluj",
|
||||
"action.open_model_folder": "Otwórz folder modelu",
|
||||
@ -705,24 +702,24 @@
|
||||
"action.open_backup_folder.desc": "Otwórz folder kopii zapasowej BlockBench",
|
||||
"switches.mirror": "Lustro UV",
|
||||
"language_name": "Polski",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Colors",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"message.plugin_reload": "Przeładowano %0 lokalnych pluginów",
|
||||
"settings.brightness": "Jasność",
|
||||
"settings.brightness.desc": "Jasność podglądu. Domyślnie 50.",
|
||||
"menu.preview.perspective.reset": "Zresetuj kamerę",
|
||||
"action.fill_mode": "Tryb wypełniania",
|
||||
"action.fill_mode.face": "Przód",
|
||||
"action.fill_mode.color": "Kolory",
|
||||
"action.fill_mode.cube": "Sześcian",
|
||||
"action.toggle_mirror_uv": "Odbicie UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay": "Przełącz pokrycie UV",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"dialog.create_texture.compress": "Skompresuj Szablon",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.recording": "Nagrywanie skrótów klawiszowych",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
@ -739,25 +736,25 @@
|
||||
"action.upload_sketchfab": "Sketchfab Upload",
|
||||
"message.sketchfab.name_or_token": "Please enter your Sketchfab token and a name",
|
||||
"dialog.sketchfab_uploader.title": "Upload Sketchfab Model",
|
||||
"dialog.sketchfab_uploader.token": "API Token",
|
||||
"dialog.sketchfab_uploader.token": "Token API",
|
||||
"dialog.sketchfab_uploader.about_token": "The token is used to connect Blockbench to your Sketchfab account. You can find it on %0",
|
||||
"dialog.sketchfab_uploader.name": "Model Name",
|
||||
"dialog.sketchfab_uploader.description": "Description",
|
||||
"dialog.sketchfab_uploader.tags": "Tags",
|
||||
"dialog.sketchfab_uploader.name": "Nazwa modelu",
|
||||
"dialog.sketchfab_uploader.description": "Opis",
|
||||
"dialog.sketchfab_uploader.tags": "Tagi",
|
||||
"settings.sketchfab_token": "Sketchfab Token",
|
||||
"settings.sketchfab_token.desc": "Token to authorize Blockbench to upload to your Sketchfab account",
|
||||
"panel.color": "Color",
|
||||
"panel.color": "Kolor",
|
||||
"data.origin": "Pivot",
|
||||
"message.sketchfab.success": "Uploaded model successfully",
|
||||
"message.sketchfab.error": "Failed to upload model to Sketchfab",
|
||||
"message.sketchfab.success": "Model został wysłany",
|
||||
"message.sketchfab.error": "Wystąpił problem podczas udostępniania modelu na Sketchfab",
|
||||
"settings.outliner_colors": "Outliner Colors",
|
||||
"settings.outliner_colors.desc": "Display cube colors in the outliner",
|
||||
"action.upload_sketchfab.desc": "Upload your model to Sketchfab",
|
||||
"action.upload_sketchfab.desc": "Udostępnij model na Sketchfab",
|
||||
"action.element_colors": "Cube Colors",
|
||||
"action.element_colors.desc": "Show cube colors in the outliner",
|
||||
"texture.error.file": "File not found",
|
||||
"texture.error.invalid": "Invalid file",
|
||||
"texture.error.ratio": "Invalid aspect ratio",
|
||||
"texture.error.file": "Plik nieznaleziony",
|
||||
"texture.error.invalid": "Niepoprawny plik",
|
||||
"texture.error.ratio": "Niepoprawny format",
|
||||
"texture.error.parent": "Texture file provided by parent model",
|
||||
"message.recover_backup.title": "Recover Model",
|
||||
"message.recover_backup.message": "Blockbench was closed without saving. Do you want to recover the model?",
|
||||
@ -771,23 +768,23 @@
|
||||
"action.reset_keyframe": "Reset Keyframe",
|
||||
"action.reset_keyframe.desc": "Reset all values of the selected keyframes",
|
||||
"dialog.edit_session.title": "Edit Session",
|
||||
"edit_session.username": "Username",
|
||||
"edit_session.username": "Nazwa użytkownika",
|
||||
"edit_session.token": "Token",
|
||||
"edit_session.about": "Edit Sessions can be used to collaborate on models across the internet. Create a session and copy the token and send it to friends, who can then use it to join.",
|
||||
"edit_session.join": "Join Session",
|
||||
"edit_session.create": "Create Session",
|
||||
"edit_session.quit": "Quit Session",
|
||||
"edit_session.joined": "%0 joined the session",
|
||||
"edit_session.left": "%0 left the session",
|
||||
"edit_session.quit_session": "Left current session",
|
||||
"edit_session.join": "Dołącz do sesji",
|
||||
"edit_session.create": "Stwórz sesję",
|
||||
"edit_session.quit": "Wyjdź z sesji",
|
||||
"edit_session.joined": "%0 dołączył do sesji",
|
||||
"edit_session.left": "%0 opuścił sesję",
|
||||
"edit_session.quit_session": "Opuść aktualną sesję",
|
||||
"edit_session.status": "Status",
|
||||
"edit_session.hosting": "Hosting",
|
||||
"edit_session.connected": "Connected to a session",
|
||||
"dialog.sketchfab_uploader.private": "Private (Pro)",
|
||||
"dialog.sketchfab_uploader.password": "Password (Pro)",
|
||||
"action.toggle_chat": "Toggle Chat",
|
||||
"action.toggle_chat.desc": "Toggle the visibility of the chat history",
|
||||
"action.uv_select_all": "Select All",
|
||||
"edit_session.connected": "Połączono z sesją",
|
||||
"dialog.sketchfab_uploader.private": "Prywatne (Pro)",
|
||||
"dialog.sketchfab_uploader.password": "Hasło (Pro)",
|
||||
"action.toggle_chat": "Przełącz czat",
|
||||
"action.toggle_chat.desc": "Przełącz widoczność historii czatu",
|
||||
"action.uv_select_all": "Zaznacz wszystkie",
|
||||
"action.uv_select_all.desc": "Select all faces in the UV dialog",
|
||||
"panel.chat": "Chat",
|
||||
"edit_session.welcome": "Welcome to this session by %0",
|
||||
@ -805,10 +802,10 @@
|
||||
"mode.start.recent": "Recent",
|
||||
"format.free": "Free Model",
|
||||
"format.free.desc": "Model without restrictions for Unity etc.",
|
||||
"format.java_block": "Java Block/Item",
|
||||
"format.java_block.desc": "Block model for Java Edition. Size and rotations are limited.",
|
||||
"format.java_block": "Java Blok/Przedmiot",
|
||||
"format.java_block.desc": "Model bloku na Java Edition. Rozmiar i kąty obrotu są ograniczone.",
|
||||
"format.bedrock": "Bedrock Model",
|
||||
"format.bedrock.desc": "Model for Bedrock Edition",
|
||||
"format.bedrock.desc": "Model na Bedrock Edition",
|
||||
"format.bedrock_old": "Bedrock Legacy Model",
|
||||
"format.bedrock_old.desc": "Pre-1.12 Bedrock Edition entity model",
|
||||
"format.modded_entity": "Modded Entity",
|
||||
@ -829,24 +826,24 @@
|
||||
"dialog.model_stats.locators": "Locators",
|
||||
"dialog.model_stats.groups": "Groups",
|
||||
"dialog.model_stats.vertices": "Vertices",
|
||||
"dialog.model_stats.faces": "Faces",
|
||||
"settings.username": "Username",
|
||||
"dialog.model_stats.faces": "Powierzchnie",
|
||||
"settings.username": "Nazwa użytkownika",
|
||||
"settings.username.desc": "Username for edit sessions",
|
||||
"settings.painting_grid": "Painting Grid",
|
||||
"settings.painting_grid.desc": "Show grid on textured cubes in paint mode",
|
||||
"action.slider_brush_min_opacity": "Minimum Opacity",
|
||||
"action.slider_brush_min_opacity.desc": "Minimum opacity of the noise brush in percent",
|
||||
"action.convert_project": "Convert Project",
|
||||
"action.convert_project": "Konwertuj projekt",
|
||||
"action.convert_project.desc": "Converts the current project to a project for another model format",
|
||||
"action.close_project": "Close Project",
|
||||
"action.close_project": "Zamknij projekt",
|
||||
"action.close_project.desc": "Closes the currently open project",
|
||||
"action.export_bedrock": "Export Bedrock Geometry",
|
||||
"action.export_bedrock.desc": "Export the model as a bedrock edition geometry file.",
|
||||
"action.save_project": "Save Project",
|
||||
"action.save_project": "Zapisz projekt",
|
||||
"action.save_project.desc": "Saves the current model as a project file",
|
||||
"action.save_project_as": "Save Project As",
|
||||
"action.save_project_as": "Zapisz projekt jako",
|
||||
"action.save_project_as.desc": "Saves the current model as a project file at a new location",
|
||||
"action.export_over": "Save Model",
|
||||
"action.export_over": "Zapisz model",
|
||||
"action.export_over.desc": "Saves the model, textures and animations by overwriting the files",
|
||||
"action.add_locator": "Add Locator",
|
||||
"action.add_locator.desc": "Adds a new locator to control positions of particles, leashes etc",
|
||||
@ -856,13 +853,13 @@
|
||||
"action.sidebar_right.desc": "Open the interface to edit elements",
|
||||
"action.uv_turn_mapping": "Turn Mapping",
|
||||
"action.uv_turn_mapping.desc": "Turn the UV mapping around 90 degrees",
|
||||
"action.remove_blank_faces": "Remove Blank Faces",
|
||||
"action.remove_blank_faces.desc": "Deletes all untextured faces of the selection",
|
||||
"menu.uv.select": "Select Cubes",
|
||||
"web.download_app": "Download App",
|
||||
"action.remove_blank_faces": "Usuń puste powierzchnie",
|
||||
"action.remove_blank_faces.desc": "Usuwa wszystkie nieoteksturowane powierzchnie z zaznaczenia",
|
||||
"menu.uv.select": "Wybierz sześcian",
|
||||
"web.download_app": "Pobierz aplikację",
|
||||
"uv_editor.turned": "Turned Mapping",
|
||||
"display.reference.crossbow": "Crossbow",
|
||||
"dialog.settings.search_results": "Search Results",
|
||||
"dialog.settings.search_results": "Wyniki wyszukiwania",
|
||||
"settings.animation_snap": "Animation Snap",
|
||||
"settings.animation_snap.desc": "Snap interval for keyframes in the animation timeline in steps per second",
|
||||
"action.import_optifine_part": "Import OptiFine Part",
|
||||
@ -870,10 +867,10 @@
|
||||
"data.locator": "Locator",
|
||||
"mode.start.no_recents": "No recently opened models",
|
||||
"panel.element": "Element",
|
||||
"panel.element.position": "Position",
|
||||
"panel.element.size": "Size",
|
||||
"panel.element.position": "Pozycja",
|
||||
"panel.element.size": "Rozmiar",
|
||||
"panel.element.origin": "Pivot Point",
|
||||
"panel.element.rotation": "Rotation",
|
||||
"panel.element.rotation": "Obrót",
|
||||
"message.canvas_limit_error.title": "Canvas Limit Error",
|
||||
"message.canvas_limit_error.message": "The action could not be performed correctly because the format limits the canvas to 48 units. Shift the pivot point to prevent this.",
|
||||
"data.effect": "Effect",
|
||||
@ -890,19 +887,19 @@
|
||||
"action.select_effect_animator.desc": "Opens timeline to add sound and particle effects",
|
||||
"action.timeline_focus": "Channel",
|
||||
"action.timeline_focus.desc": "Select the animation channels to display in the timeline",
|
||||
"action.timeline_focus.all": "All",
|
||||
"timeline.particle": "Particle",
|
||||
"timeline.sound": "Sound",
|
||||
"timeline.effects": "Effects",
|
||||
"action.timeline_focus.all": "Wszystko",
|
||||
"timeline.particle": "Cząsteczka",
|
||||
"timeline.sound": "Dźwięk",
|
||||
"timeline.effects": "Efekty",
|
||||
"data.format": "Format",
|
||||
"format.optifine_part": "OptiFine Part",
|
||||
"format.optifine_part.desc": "JPM part for OptiFine entity models",
|
||||
"action.reverse_keyframes": "Reverse Keyframes",
|
||||
"action.reverse_keyframes.desc": "Reverse the order of the selected keyframes",
|
||||
"generic.help": "Help",
|
||||
"message.removed_faces": "Removed %0 faces",
|
||||
"dialog.sketchfab_uploader.draft": "Draft",
|
||||
"action.slider_pos": "Move %0",
|
||||
"generic.help": "Pomoc",
|
||||
"message.removed_faces": "Usunięto %0 powierzchni",
|
||||
"dialog.sketchfab_uploader.draft": "Szkic",
|
||||
"action.slider_pos": "Przesuń %0",
|
||||
"action.slider_pos.desc": "Move cubes on the %0 axis",
|
||||
"action.slider_size": "Size %0",
|
||||
"action.slider_size.desc": "Resize cubes on the %0 axis",
|
||||
@ -918,11 +915,11 @@
|
||||
"action.flip.desc": "Flip the selected cubes on the %0 axis",
|
||||
"action.center": "Center %0",
|
||||
"action.center.desc": "Center the selected cubes on the %0 axis",
|
||||
"action.bring_up_all_animations": "Bring Up All Animations",
|
||||
"panel.bone": "Bone",
|
||||
"data.color": "Color",
|
||||
"generic.export": "Export",
|
||||
"generic.none": "None",
|
||||
"action.bring_up_all_animations": "Bring Up All Animators",
|
||||
"panel.bone": "Kość",
|
||||
"data.color": "Kolor",
|
||||
"generic.export": "Eksportuj",
|
||||
"generic.none": "Żadne",
|
||||
"status_bar.recording": "Recording Timelapse",
|
||||
"message.add_to_palette": "Added to palette",
|
||||
"message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.",
|
||||
@ -931,25 +928,23 @@
|
||||
"message.import_palette.replace_palette": "Replace old palette",
|
||||
"message.import_palette.threshold": "Merge Threshold",
|
||||
"dialog.timelapse.interval": "Interval (Seconds)",
|
||||
"dialog.timelapse.source": "Source",
|
||||
"dialog.timelapse.source.interface": "Interface",
|
||||
"dialog.timelapse.source": "Źródło",
|
||||
"dialog.timelapse.source.interface": "Interfejs",
|
||||
"dialog.timelapse.source.locked": "Locked Angle",
|
||||
"dialog.timelapse.destination": "Destination Folder",
|
||||
"layout.color.checkerboard": "Checkerboard",
|
||||
"layout.color.checkerboard.desc": "Background of canvas and UV editor",
|
||||
"layout.font.code": "Code Font",
|
||||
"layout.css": "Custom CSS",
|
||||
"settings.category.paint": "Paint",
|
||||
"settings.category.paint": "Maluj",
|
||||
"settings.deactivate_size_limit": "Deactivate Size Limit",
|
||||
"settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
|
||||
"settings.brush_opacity_modifier": "Brush Opacity Modifier",
|
||||
"settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus",
|
||||
"settings.brush_size_modifier": "Brush Size Modifier",
|
||||
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
|
||||
"settings.brush_modifier.pressure": "Pressure",
|
||||
"settings.brush_modifier.pressure": "Nacisk",
|
||||
"settings.brush_modifier.tilt": "Tilt",
|
||||
"settings.class_export_version": "Modded Entity Export Version",
|
||||
"settings.class_export_version.desc": "The format version for modded entity models",
|
||||
"category.color": "Kolor",
|
||||
"action.import_theme": "Importuj styl",
|
||||
"action.export_theme": "Eksportuj styl",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Generate palette from a texture",
|
||||
"action.sort_palette": "Sort Palette",
|
||||
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
|
||||
"action.clear_palette": "Wyczyść paletę",
|
||||
"action.clear_palette.desc": "Usuń wszystkie kolory z palety",
|
||||
"action.timelapse": "Timelapse",
|
||||
"action.timelapse.desc": "Nagraj timelaps procesu modelowania",
|
||||
"action.add_keyframe": "Dodaj klatkę kluczową",
|
||||
@ -1010,26 +1003,26 @@
|
||||
"menu.help.plugin_documentation": "Plugin API Documentation",
|
||||
"menu.help.search_action": "Search and Run Action",
|
||||
"menu.help.donate": "Wesprzyj",
|
||||
"menu.help.about": "About...",
|
||||
"menu.help.about": "O Blockbench...",
|
||||
"menu.preview.background.clipboard": "Wczytaj ze schowka",
|
||||
"dialog.ignore": "Ignore",
|
||||
"dialog.ignore": "Ignoruj",
|
||||
"generic.unset": "Unset",
|
||||
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
|
||||
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
|
||||
"dialog.resize_texture.fill": "Fill with",
|
||||
"dialog.resize_texture.fill.transparent": "Transparent",
|
||||
"dialog.resize_texture.fill.color": "Color",
|
||||
"dialog.resize_texture.fill.repeat": "Repeat",
|
||||
"dialog.resize_texture.fill.stretch": "Stretch",
|
||||
"dialog.resize_texture.fill.transparent": "Przeźroczysty",
|
||||
"dialog.resize_texture.fill.color": "Kolor",
|
||||
"dialog.resize_texture.fill.repeat": "Powtórz",
|
||||
"dialog.resize_texture.fill.stretch": "Rozciągnij",
|
||||
"dialog.scale.element_pivot": "Element Pivot",
|
||||
"dialog.scale.selection_center": "Selection Center",
|
||||
"dialog.create_gif.length_mode": "Length Mode",
|
||||
"dialog.create_gif.length_mode.seconds": "Seconds",
|
||||
"dialog.create_gif.length_mode.frames": "Frames",
|
||||
"dialog.create_gif.length_mode.animation": "Animation Length",
|
||||
"dialog.create_gif.length_mode.seconds": "Sekund",
|
||||
"dialog.create_gif.length_mode.frames": "Klatki",
|
||||
"dialog.create_gif.length_mode.animation": "Długość animacji",
|
||||
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
|
||||
"dialog.save_angle.projection": "Projection",
|
||||
"dialog.save_angle.projection.perspective": "Perspective",
|
||||
"dialog.save_angle.projection.perspective": "Perspektywa",
|
||||
"dialog.save_angle.projection.orthographic": "Orthographic",
|
||||
"dialog.sketchfab_uploader.animations": "Animations",
|
||||
"dialog.settings.theme": "Theme",
|
||||
@ -1045,7 +1038,7 @@
|
||||
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
|
||||
"action.draw_shape_type.ellipse": "Ellipse",
|
||||
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
|
||||
"action.draw_shape_type.line": "Line",
|
||||
"action.draw_shape_type.line": "Linia",
|
||||
"action.mirror_painting": "Mirror Painting",
|
||||
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
|
||||
"action.lock_alpha": "Lock Alpha Channel",
|
||||
@ -1058,8 +1051,8 @@
|
||||
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
|
||||
"action.transform_space": "Transform Space",
|
||||
"action.transform_space.desc": "Default transform space for elements and bones",
|
||||
"action.transform_space.global": "Global",
|
||||
"action.transform_space.bone": "Bone",
|
||||
"action.transform_space.global": "Globalne",
|
||||
"action.transform_space.bone": "Kość",
|
||||
"action.transform_space.local": "Local",
|
||||
"action.toggle_camera_projection": "Toggle Camera Projection",
|
||||
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
|
||||
@ -1068,24 +1061,53 @@
|
||||
"action.slider_face_tint": "Tint Index",
|
||||
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
|
||||
"menu.help.quickstart": "Quickstart Wizard",
|
||||
"menu.help.developer": "Developer",
|
||||
"menu.help.developer": "Deweloper",
|
||||
"menu.help.developer.dev_tools": "Open Dev Tools",
|
||||
"menu.help.developer.reset_storage": "Factory Reset",
|
||||
"menu.help.developer.reset_storage.confirm": "Are you sure you want to reset Blockbench to factory settings? This will delete all custom settings, keybindings and installed plugins.",
|
||||
"menu.help.developer.cache_reload": "Cache Reload",
|
||||
"menu.texture.resize": "Resize...",
|
||||
"menu.texture.resize": "Zmień rozmiar...",
|
||||
"menu.preview.orthographic": "Orthographic",
|
||||
"menu.preview.save_angle": "Save Angle...",
|
||||
"menu.preview.angle": "Angles",
|
||||
"menu.preview.angle.initial": "Initial Angle",
|
||||
"menu.preview.angle.load": "Load",
|
||||
"menu.preview.maximize": "Maximize",
|
||||
"panel.color.both": "Both",
|
||||
"uv_editor.copy_selection": "Copy Selection",
|
||||
"uv_editor.paste_selection": "Paste Selection",
|
||||
"menu.preview.angle.load": "Wczytaj",
|
||||
"menu.preview.maximize": "Maksymalizuj",
|
||||
"panel.color.both": "Oba",
|
||||
"uv_editor.copy_selection": "Kopiuj zaznaczenie",
|
||||
"uv_editor.paste_selection": "Wklej zaznaczenie",
|
||||
"uv_editor.copy_paste_tool.place": "Place",
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
40
lang/pt.json
40
lang/pt.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Cancelar",
|
||||
"action.slider_inflate": "Aumentar",
|
||||
"action.slider_inflate.desc": "Aumentar cubos em todas as direções sem alterar o mapeamento.",
|
||||
"action.brush_mode": "Modo do pincel",
|
||||
"action.slider_brush_size": "Tamanho",
|
||||
"action.slider_brush_size.desc": "Tamanho do pincel (em pixels)",
|
||||
"action.slider_brush_opacity": "Opacidade",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Última Versão",
|
||||
"dialog.update.installed": "Versão Instalada",
|
||||
"dialog.update.update": "Atualização",
|
||||
"action.brush_mode.brush": "Redondo",
|
||||
"action.brush_mode.noise": "Ruído",
|
||||
"action.vertex_snap_mode.move": "Mover",
|
||||
"action.vertex_snap_mode.scale": "Redimensionar",
|
||||
"action.open_model_folder": "Abrir Pasta de Modelos",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Modifique o tamanho do pincel ao usar uma caneta",
|
||||
"settings.brush_modifier.pressure": "Pressão",
|
||||
"settings.brush_modifier.tilt": "Inclinar",
|
||||
"settings.class_export_version": "Versão de exportação de entidade modificada",
|
||||
"settings.class_export_version.desc": "A versão do formato para modelos de entidade modificados.",
|
||||
"category.color": "Cor",
|
||||
"action.import_theme": "Importar Tema",
|
||||
"action.export_theme": "Exportar Tema",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Gerar paleta a partir de uma textura",
|
||||
"action.sort_palette": "Classificar Paleta",
|
||||
"action.sort_palette.desc": "Classifique todas as cores da paleta por cor e brilho",
|
||||
"action.clear_palette": "Limpar Paleta",
|
||||
"action.clear_palette.desc": "Remove todas as cores da paleta",
|
||||
"action.timelapse": "Timelapse...",
|
||||
"action.timelapse.desc": "Grave um timelapse do seu progresso de modelagem",
|
||||
"action.add_keyframe": "Adicionar quadro-chave",
|
||||
@ -994,7 +987,7 @@
|
||||
"format.skin.desc": "Edit player and entity skins",
|
||||
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
|
||||
"dialog.skin.title": "Create Skin",
|
||||
"dialog.skin.model": "Skin",
|
||||
"dialog.skin.model": "Model",
|
||||
"dialog.skin.texture": "Texture (Optional)",
|
||||
"action.toggle_skin_layer": "Toggle Skin Layer",
|
||||
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
38
lang/ru.json
38
lang/ru.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Отменить",
|
||||
"action.slider_inflate": "Раздуть",
|
||||
"action.slider_inflate.desc": "Раздуть кубы во все направления без изменений в UV",
|
||||
"action.brush_mode": "Режим кисти",
|
||||
"action.slider_brush_size": "Размер",
|
||||
"action.slider_brush_size.desc": "Размер кисти в пикселях",
|
||||
"action.slider_brush_opacity": "Непрозрачность",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Новейшая версия",
|
||||
"dialog.update.installed": "Установленная версия",
|
||||
"dialog.update.update": "Обновление",
|
||||
"action.brush_mode.brush": "Кисть",
|
||||
"action.brush_mode.noise": "Шум",
|
||||
"action.vertex_snap_mode.move": "Перемещение",
|
||||
"action.vertex_snap_mode.scale": "Масштабирование",
|
||||
"action.open_model_folder": "Открыть расположение модели",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Модифицировать размер кисти при использовании стилуса",
|
||||
"settings.brush_modifier.pressure": "Давление",
|
||||
"settings.brush_modifier.tilt": "Наклон",
|
||||
"settings.class_export_version": "Модифицированная версия экспорта сущностей",
|
||||
"settings.class_export_version.desc": "Версия формата для модифицированных моделей сущностей",
|
||||
"category.color": "Цвет",
|
||||
"action.import_theme": "Импорт темы",
|
||||
"action.export_theme": "Экспорт темы",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Сгенерировать палитру из текстуры",
|
||||
"action.sort_palette": "Сортировка палитры",
|
||||
"action.sort_palette.desc": "Сортировать цвета на палитре по цвету и яркости",
|
||||
"action.clear_palette": "Очистка палитры",
|
||||
"action.clear_palette.desc": "Удалить все цвета из палитры",
|
||||
"action.timelapse": "Временная шкала",
|
||||
"action.timelapse.desc": "Записать процесс создания модели",
|
||||
"action.add_keyframe": "Добавить ключевой кадр",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
42
lang/sv.json
42
lang/sv.json
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "Avbryt",
|
||||
"action.slider_inflate": "Blåsa upp",
|
||||
"action.slider_inflate.desc": "Blås upp kuber i alla riktningar utan att ändra UV.",
|
||||
"action.brush_mode": "Penselläge",
|
||||
"action.slider_brush_size": "Storlek",
|
||||
"action.slider_brush_size.desc": "Penselns radie i pixlar",
|
||||
"action.slider_brush_opacity": "Opacitet",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "Senaste version",
|
||||
"dialog.update.installed": "Installerad version",
|
||||
"dialog.update.update": "Uppdatera",
|
||||
"action.brush_mode.brush": "Rund",
|
||||
"action.brush_mode.noise": "Brus",
|
||||
"action.vertex_snap_mode.move": "Flytta",
|
||||
"action.vertex_snap_mode.scale": "Skala",
|
||||
"action.open_model_folder": "Öppna modellmapp",
|
||||
@ -918,7 +915,7 @@
|
||||
"action.flip.desc": "Flip the selected cubes on the %0 axis",
|
||||
"action.center": "Center %0",
|
||||
"action.center.desc": "Center the selected cubes on the %0 axis",
|
||||
"action.bring_up_all_animations": "Bring Up All Animations",
|
||||
"action.bring_up_all_animations": "Bring Up All Animators",
|
||||
"panel.bone": "Ben",
|
||||
"data.color": "Färg",
|
||||
"generic.export": "Export",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
|
||||
"settings.brush_modifier.pressure": "Tryck",
|
||||
"settings.brush_modifier.tilt": "Tilt",
|
||||
"settings.class_export_version": "Modded Entity Export Version",
|
||||
"settings.class_export_version.desc": "The format version for modded entity models",
|
||||
"category.color": "Färg",
|
||||
"action.import_theme": "Import Theme",
|
||||
"action.export_theme": "Export Theme",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "Generate palette from a texture",
|
||||
"action.sort_palette": "Sort Palette",
|
||||
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
|
||||
"action.clear_palette": "Clear Palette",
|
||||
"action.clear_palette.desc": "Remove all colors from the palette",
|
||||
"action.timelapse": "Timelapse...",
|
||||
"action.timelapse.desc": "Record a timelapse of your modeling process",
|
||||
"action.add_keyframe": "Add Keyframe",
|
||||
@ -994,7 +987,7 @@
|
||||
"format.skin.desc": "Edit player and entity skins",
|
||||
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
|
||||
"dialog.skin.title": "Create Skin",
|
||||
"dialog.skin.model": "Skin",
|
||||
"dialog.skin.model": "Model",
|
||||
"dialog.skin.texture": "Texture (Optional)",
|
||||
"action.toggle_skin_layer": "Toggle Skin Layer",
|
||||
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "Cut",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
|
||||
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
40
lang/zh.json
40
lang/zh.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"dialog.ok": "好的",
|
||||
"dialog.cancel": "取消",
|
||||
"dialog.confirm": "确认",
|
||||
"dialog.confirm": "Confirm",
|
||||
"dialog.close": "关闭",
|
||||
"dialog.import": "导入",
|
||||
"dialog.save": "保存",
|
||||
@ -280,7 +280,6 @@
|
||||
"keybind.cancel": "取消",
|
||||
"action.slider_inflate": "缩放",
|
||||
"action.slider_inflate.desc": "在不改变 UV 的情况下放大所有立方体",
|
||||
"action.brush_mode": "笔刷模式",
|
||||
"action.slider_brush_size": "尺寸",
|
||||
"action.slider_brush_size.desc": "笔刷的半径(以像素为单位)",
|
||||
"action.slider_brush_opacity": "不透明度",
|
||||
@ -541,8 +540,6 @@
|
||||
"dialog.update.latest": "最新版本",
|
||||
"dialog.update.installed": "已安装的版本",
|
||||
"dialog.update.update": "更新",
|
||||
"action.brush_mode.brush": "笔刷",
|
||||
"action.brush_mode.noise": "噪点",
|
||||
"action.vertex_snap_mode.move": "移动",
|
||||
"action.vertex_snap_mode.scale": "缩放",
|
||||
"action.open_model_folder": "打开模型文件夹",
|
||||
@ -948,8 +945,6 @@
|
||||
"settings.brush_size_modifier.desc": "使用手写笔时修改画笔的大小",
|
||||
"settings.brush_modifier.pressure": "压感",
|
||||
"settings.brush_modifier.tilt": "倾斜",
|
||||
"settings.class_export_version": "模组实体导出版本",
|
||||
"settings.class_export_version.desc": "模组实体格式对应的版本",
|
||||
"category.color": "颜色",
|
||||
"action.import_theme": "导入主题",
|
||||
"action.export_theme": "导出主题",
|
||||
@ -969,8 +964,6 @@
|
||||
"action.generate_palette.desc": "从材质纹理贴图生成调色板",
|
||||
"action.sort_palette": "排列调色板",
|
||||
"action.sort_palette.desc": "按颜色和亮度对调色板上所有的颜色进行排序",
|
||||
"action.clear_palette": "清除调色板",
|
||||
"action.clear_palette.desc": "从调色板中删除所有颜色",
|
||||
"action.timelapse": "延时摄影……",
|
||||
"action.timelapse.desc": "拍摄你建模过程的延时摄影",
|
||||
"action.add_keyframe": "添加关键帧",
|
||||
@ -1087,5 +1080,34 @@
|
||||
"uv_editor.copy_paste_tool.cut": "剪切",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "镜像 X 轴",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "镜像 Y 轴",
|
||||
"uv_editor.copy_paste_tool.rotate": "旋转90度"
|
||||
"uv_editor.copy_paste_tool.rotate": "旋转90度",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"settings.large_grid_size": "Block Grid Size",
|
||||
"settings.large_grid_size.desc": "Size of the block grid",
|
||||
"action.load_plugin_from_url": "Load Plugin from URL",
|
||||
"action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock Everything",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.load_palette": "Load Palette",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
"action.apply_display_preset.desc": "Apply a default or custom display setting preset",
|
||||
"action.apply_display_preset.here": "Apply To This Slot",
|
||||
"action.apply_display_preset.everywhere": "Apply To All Slots",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.fold_all_animations": "Fold All Animators",
|
||||
"action.timeline_focus.used": "In Use",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Blockbench",
|
||||
"description": "Model editing and animation software",
|
||||
"version": "3.4.2",
|
||||
"version": "3.5.0",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "JannisX11",
|
||||
@ -73,6 +73,7 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "electron .",
|
||||
"dist": "electron-builder --publish=always",
|
||||
"win64": "electron-builder -w --ia32 --publish=always",
|
||||
"win32": "electron-builder -w --x64 --publish=always",
|
||||
@ -80,7 +81,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^2.4.1",
|
||||
"electron": "8.0.2",
|
||||
"electron": "8.2.1",
|
||||
"electron-builder": "^21.2.0"
|
||||
}
|
||||
}
|
||||
|
51
service_worker.js
Normal file
51
service_worker.js
Normal file
@ -0,0 +1,51 @@
|
||||
const cacheName = 'blockbench_3.2.0';
|
||||
const staticAssets = [
|
||||
'./',
|
||||
'./index.html',
|
||||
'./css/',
|
||||
'./js',
|
||||
'./lib',
|
||||
'./font',
|
||||
'./lang',
|
||||
'./assets',
|
||||
'./favicon.png',
|
||||
'./manifest.json',
|
||||
];
|
||||
|
||||
self.addEventListener('install', async (event) => {
|
||||
var cache = await caches.open(cacheName);
|
||||
await cache.addAll(staticAssets);
|
||||
return self.skipWaiting();
|
||||
})
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
self.clients.claim();
|
||||
})
|
||||
|
||||
self.addEventListener('fetch', async (event) => {
|
||||
var req = event.request;
|
||||
var url = new URL(req.url);
|
||||
|
||||
if (url.origin == 'location.origin') {
|
||||
event.respondWith(cacheFirst(req));
|
||||
} else {
|
||||
event.respondWith(networkAndCache(req));
|
||||
}
|
||||
})
|
||||
|
||||
async function cacheFirst(req) {
|
||||
var cache = await caches.open(cacheName);
|
||||
var cached = await cache.match(req);
|
||||
return cached || fetch(req);
|
||||
}
|
||||
async function networkAndCache(req) {
|
||||
var cache = await caches.open(cacheName);
|
||||
try {
|
||||
var fresh = await fetch(req);
|
||||
await cache.put(req, fresh.clone());
|
||||
return fresh;
|
||||
} catch (err) {
|
||||
var cached = await cache.match(req);
|
||||
return cached;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user