mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
v3.6.0
This commit is contained in:
parent
b2cd316ae7
commit
a7471f3753
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
/dist/
|
||||
index.php
|
||||
package-lock.json
|
||||
electron-builder.env
|
||||
node_modules/
|
23
.travis.yml
23
.travis.yml
@ -2,31 +2,29 @@ sudo: required
|
||||
dist: trusty
|
||||
|
||||
language: node_js
|
||||
node:
|
||||
- 12
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "macOS + Win Portable"
|
||||
- name: "macOS"
|
||||
os: osx
|
||||
osx_image: "xcode11.3"
|
||||
script:
|
||||
- electron-builder --publish=always
|
||||
- electron-builder --windows portable --x64 --publish=always -c.productName='Blockbench_portable'
|
||||
- electron-builder --publish=onTagOrDraft
|
||||
|
||||
- name: "Windows"
|
||||
os: osx
|
||||
osx_image: "xcode11.3"
|
||||
script:
|
||||
- electron-builder -w --x64 --publish=always
|
||||
- electron-builder -w --ia32 --publish=always -c.productName='Blockbench_32bit'
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file: dist/win-unpacked/resources/app.asar
|
||||
- electron-builder --windows portable --x64 --publish=onTagOrDraft -c.productName='Blockbench_portable'
|
||||
- electron-builder -w --ia32 --x64 --publish=onTagOrDraft
|
||||
|
||||
- name: "Linux"
|
||||
os: linux
|
||||
script:
|
||||
- sudo apt-get install rpm
|
||||
- electron-builder --publish=always
|
||||
- electron-builder --publish=onTagOrDraft
|
||||
|
||||
|
||||
cache:
|
||||
@ -34,8 +32,7 @@ cache:
|
||||
- node_modules
|
||||
|
||||
install:
|
||||
- nvm install 12.17.0
|
||||
- npm install electron-builder
|
||||
- npm install
|
||||
|
||||
notifications:
|
||||
email: false
|
687
LICENSE.MD
687
LICENSE.MD
@ -1,19 +1,674 @@
|
||||
Copyright (c) 2018 Jannis P.
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
Preamble
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
8
build/entitlements.mac.plist
Normal file
8
build/entitlements.mac.plist
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -32,7 +32,7 @@
|
||||
background-color: var(--color-ui);
|
||||
color: inherit;
|
||||
border: none;
|
||||
box-shadow: 0 0px 40px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 0px 8px rgba(0, 0, 0, 0.64);
|
||||
left: unset;
|
||||
right: unset;
|
||||
bottom: unset;
|
||||
@ -65,12 +65,19 @@
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.dialog_bar {
|
||||
position: relative;
|
||||
min-height: 30px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
height: auto;
|
||||
clear: both;
|
||||
}
|
||||
.dialog_bar.form_bar {
|
||||
display: flex;
|
||||
}
|
||||
.dialog_bar.form_bar .half {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.dialog_bar::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
@ -81,6 +88,7 @@
|
||||
}
|
||||
.dialog_bar.button_bar {
|
||||
text-align: right;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.dialog_bar button.large {
|
||||
margin-bottom: 0;
|
||||
@ -164,6 +172,7 @@
|
||||
margin-left: -28px;
|
||||
margin-top: 4px;
|
||||
opacity: 0.75;
|
||||
right: 42px;
|
||||
}
|
||||
dialog .form_bar_file:hover > .material-icons {
|
||||
opacity: 1;
|
||||
@ -427,14 +436,34 @@
|
||||
#import_texture_list li {
|
||||
height: 112px;
|
||||
width: 112px;
|
||||
margin: 4px;
|
||||
margin: 3px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
box-sizing: content-box;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
#import_texture_list li:hover {
|
||||
background-color: var(--color-selected);;
|
||||
}
|
||||
#import_texture_list li.selected {
|
||||
border-color: var(--color-accent);
|
||||
}
|
||||
#import_texture_list li.selected::after {
|
||||
position: absolute;
|
||||
content: "\f00c";
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-weight: 600;
|
||||
color: var(--color-accent);
|
||||
background-color: var(--color-ui);
|
||||
height: 19px;
|
||||
margin-right: 0;
|
||||
margin-left: 100px;
|
||||
margin-top: -10px;
|
||||
border-bottom-left-radius: 8px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
body.entity_mode button.entity_mode_uv_button {
|
||||
display: block;
|
||||
padding: 0;
|
||||
@ -507,6 +536,7 @@
|
||||
min-width: 155px;
|
||||
margin-left: 1px;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/*PE Import Dialog*/
|
||||
@ -709,9 +739,6 @@
|
||||
height: 42px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
#uv_dialog h2.dialog_handle.entity_mode_only {
|
||||
margin: 0;
|
||||
}
|
||||
#uv_dialog_all .UVEditor .uv_transform_info {
|
||||
top: 30px;
|
||||
}
|
||||
|
@ -100,9 +100,29 @@
|
||||
}
|
||||
|
||||
/*UI Elements*/
|
||||
canvas.preview {
|
||||
div.preview {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
cursor: inherit;
|
||||
}
|
||||
.preview > canvas {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.preview .preview_menu {
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
background-color: var(--color-dark);
|
||||
}
|
||||
.checkerboard .tool.preview_menu {
|
||||
background-color: var(--color-checkerboard);
|
||||
}
|
||||
.preview .preview_menu > i {
|
||||
width: 20px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
.text_padding {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
@ -138,7 +158,6 @@
|
||||
}
|
||||
.list {
|
||||
background-color: var(--color-back);
|
||||
height: calc(100% - 86px);
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
flex-grow: 1;
|
||||
|
@ -1,3 +1,6 @@
|
||||
.panel {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
/*Display*/
|
||||
|
||||
@ -276,6 +279,7 @@
|
||||
|
||||
/*Textures*/
|
||||
.texture {
|
||||
display: flex;
|
||||
height: 48px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
@ -289,7 +293,6 @@
|
||||
}
|
||||
.texture > i {
|
||||
margin-top: 12px;
|
||||
float: right;
|
||||
}
|
||||
.texture > i.clickable:hover {
|
||||
color: var(--color-light);
|
||||
@ -297,12 +300,14 @@
|
||||
.texture > i:not(.clickable) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.texture > * {
|
||||
float: left;
|
||||
.texture i.icon_off {
|
||||
opacity: 0.56;
|
||||
}
|
||||
div.texture_icon_wrapper {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
@ -317,11 +322,14 @@
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
.texture_description_wrapper {
|
||||
flex-grow: 1;
|
||||
|
||||
}
|
||||
.texture_name {
|
||||
margin-top: 2px;
|
||||
margin-left: 6px;
|
||||
margin-right: 4px;
|
||||
width: calc(100% - 82px);
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
}
|
||||
@ -332,16 +340,13 @@
|
||||
margin-top: -3px;
|
||||
margin-left: 6px;
|
||||
margin-right: 4px;
|
||||
width: calc(100% - 82px);
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
font-size: 0.9em;
|
||||
opacity: 0.6;
|
||||
cursor: default;
|
||||
}
|
||||
.texture.particle .texture_name, .texture.particle .texture_res {
|
||||
width: calc(100% - 106px);
|
||||
}
|
||||
.texture_error {
|
||||
position: absolute;
|
||||
color: red;
|
||||
@ -357,6 +362,33 @@
|
||||
margin-top: 24px;
|
||||
text-shadow: 0 0 5px #000;
|
||||
}
|
||||
.texture[order]::before {
|
||||
content: '';
|
||||
height: 2px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--color-accent);
|
||||
z-index: 3;
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
.texture[order] {
|
||||
position: relative;
|
||||
}
|
||||
.texture[order="-1"]::before {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.texture[order="1"]::before {
|
||||
bottom: 0px;
|
||||
}
|
||||
.texture[order="0"]::before {
|
||||
width: 5px;
|
||||
height: 30px;
|
||||
margin-left: 0;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
}
|
||||
|
||||
/*Animations*/
|
||||
.panel#animations #animations_list {
|
||||
@ -450,8 +482,8 @@
|
||||
}
|
||||
#timeline_playhead {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 3;
|
||||
cursor: ew-resize;
|
||||
|
||||
height: 26px;
|
||||
width: 18px;
|
||||
@ -472,22 +504,12 @@
|
||||
pointer-events: none;
|
||||
margin-left: -1px;
|
||||
margin-top: -2px;
|
||||
height: 17px;
|
||||
}
|
||||
#timeline_playhead_line {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 2px;
|
||||
z-index: 2;
|
||||
background-color: var(--color-accent);
|
||||
pointer-events: none;
|
||||
height: 5000px;
|
||||
}
|
||||
#timeline_endbracket {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
cursor: col-resize;
|
||||
|
||||
height: 26px;
|
||||
width: 8px;
|
||||
@ -498,6 +520,13 @@
|
||||
border-left-width: 0;
|
||||
border-right-width: 2px;
|
||||
}
|
||||
div#timeline_endbracket::after {
|
||||
content: "";
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
#timeline_body .keyframe {
|
||||
position: absolute;
|
||||
@ -881,8 +910,9 @@
|
||||
/*Chat*/
|
||||
#chat {
|
||||
z-index: 16;
|
||||
min-height: 180px;
|
||||
min-height: 86px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#chat_history {
|
||||
background: var(--color-back);
|
||||
|
@ -279,9 +279,10 @@
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
i.fa_big {
|
||||
font-size: 15pt;
|
||||
font-size: 14pt;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
padding-top: 1px;
|
||||
text-align: center;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
@ -314,6 +315,7 @@
|
||||
--color-checkerboard: #2f3339;
|
||||
|
||||
--color-close: #d62e3f;
|
||||
--color-stream: #6442A4;
|
||||
--color-axis-x: #d50a0a;
|
||||
--color-axis-y: #23d400;
|
||||
--color-axis-z: #0894ed;
|
||||
@ -482,8 +484,8 @@
|
||||
height: 30px;
|
||||
min-width: 50px;
|
||||
padding-top: 4px;
|
||||
padding-left: 10px;
|
||||
padding-right: 28px;
|
||||
padding-left: 8px;
|
||||
padding-right: 24px;
|
||||
color: var(--color-text);
|
||||
}
|
||||
bb-select:hover{
|
||||
@ -499,7 +501,7 @@
|
||||
height: 12px;
|
||||
width: 16px;
|
||||
pointer-events: none;
|
||||
right: 6px;
|
||||
right: 3px;
|
||||
top: 3px;
|
||||
}
|
||||
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
|
||||
|
@ -53,9 +53,6 @@
|
||||
flex-grow: 1;
|
||||
min-height: 133px;
|
||||
}
|
||||
.panel:not(:last-child) {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
h3.panel_handle {
|
||||
width: 100%;
|
||||
@ -63,6 +60,9 @@
|
||||
padding: 6px 12px;
|
||||
background: var(--color-ui);
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.6;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.panel p {
|
||||
margin-left: 12px;
|
||||
@ -217,6 +217,7 @@
|
||||
margin-left: auto;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
#web_download_button a {
|
||||
text-decoration: none !important;
|
||||
@ -378,6 +379,7 @@
|
||||
#start_screen .recent_project {
|
||||
margin: 2px 0;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
#start_screen .recent_project .icon_wrapper {
|
||||
flex-shrink: 0;
|
||||
@ -403,32 +405,65 @@
|
||||
background: linear-gradient(90deg, transparent, var(--color-ui));
|
||||
}
|
||||
|
||||
#start_screen .recent_project.thumbnail {
|
||||
width: 242px;
|
||||
height: 150px;
|
||||
#start_screen_list_type {
|
||||
height: 30px;
|
||||
position: absolute;
|
||||
top: 32px;
|
||||
right: 20px;
|
||||
}
|
||||
#start_screen_list_type li.selected {
|
||||
border-bottom: 3px solid var(--color-accent);
|
||||
}
|
||||
|
||||
width: 168px;
|
||||
height: 128px;
|
||||
#start_screen .recent_project.thumbnail {
|
||||
width: 180px;
|
||||
height: 130px;
|
||||
position: relative;
|
||||
float: left;
|
||||
margin: 2px;
|
||||
background-color: var(--color-back);
|
||||
margin: 1px;
|
||||
background-size: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#start_screen .recent_project.thumbnail .thumbnail_image {
|
||||
width: 180px;
|
||||
height: 100px;
|
||||
background-size: 180px;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
#start_screen .recent_project.thumbnail:hover {
|
||||
background-color: var(--color-ui);
|
||||
background-color: var(--color-accent);
|
||||
}
|
||||
#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;
|
||||
height: 30px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
padding-top: 4px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
background-color: var(--color-ui);
|
||||
}
|
||||
#start_screen .recent_project.thumbnail .icon_wrapper {
|
||||
position: absolute;
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
padding: 2px;
|
||||
color: var(--color-accent_text);
|
||||
background-color: var(--color-accent);
|
||||
}
|
||||
#start_screen .recent_project.thumbnail:hover .recent_project_name {
|
||||
color: var(--color-accent_text);
|
||||
background-color: transparent;
|
||||
}
|
||||
#start-files ul.redact li.recent_project.thumbnail .thumbnail_image {
|
||||
background: transparent !important;
|
||||
}
|
||||
#start_screen .recent_project.thumbnail:hover .icon_wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#start_screen > content {
|
||||
@ -513,20 +548,24 @@
|
||||
#start-files li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#start-files left {
|
||||
#start_screen section#start-files left {
|
||||
width: 38%;
|
||||
overflow-y: hidden;
|
||||
padding: 20px 24px 10px 24px
|
||||
}
|
||||
#start-files right {
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
#start_screen left > ul {
|
||||
margin-bottom: 16px;
|
||||
height: calc(100% - 46px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
#start_screen right i {
|
||||
vertical-align: sub;
|
||||
}
|
||||
#start-files left li {
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
#start-files left span.icon_wrapper {
|
||||
height: 22px;
|
||||
|
178
index.html
178
index.html
@ -24,7 +24,7 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '3.5.4';
|
||||
const appVersion = '3.6.0';
|
||||
</script>
|
||||
<div id="loading_error_message" style="display: none;">
|
||||
<div>An error occurred while loading Blockbench</div>
|
||||
@ -49,12 +49,14 @@
|
||||
<script src="lib/three.min.js"></script>
|
||||
<script src="lib/three_custom.js"></script>
|
||||
<script src="lib/GLTFExporter.js"></script>
|
||||
<script src="lib/CanvasFrame.js"></script>
|
||||
<!--script src="lib/fik.min.js"></script-->
|
||||
<script src="lib/molang.js"></script>
|
||||
<script src="js/preview/OrbitControls.js"></script>
|
||||
<script src="js/outliner/tree.vue.js"></script>
|
||||
|
||||
<script src="js/util.js"></script>
|
||||
<script src="js/property.js"></script>
|
||||
<script src="js/interface/language.js"></script>
|
||||
<script src="js/interface/menu.js"></script>
|
||||
<script src="js/interface/actions.js"></script>
|
||||
@ -87,6 +89,7 @@
|
||||
<script src="js/transform.js"></script>
|
||||
<script src="js/texturing/textures.js"></script>
|
||||
<script src="js/texturing/uv.js"></script>
|
||||
<script src="js/interface/panels.js"></script>
|
||||
<script src="js/interface/interface.js"></script>
|
||||
<script src="js/texturing/painter.js"></script>
|
||||
<script src="js/texturing/texture_generator.js"></script>
|
||||
@ -97,16 +100,16 @@
|
||||
|
||||
<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>
|
||||
<script src="js/io/bedrock.js"></script>
|
||||
<script src="js/io/bedrock_old.js"></script>
|
||||
<script src="js/io/obj.js"></script>
|
||||
<script src="js/io/gltf.js"></script>
|
||||
<script src="js/io/modded_entity.js"></script>
|
||||
<script src="js/io/optifine_jem.js"></script>
|
||||
<script src="js/io/optifine_jpm.js"></script>
|
||||
<script src="js/io/skin.js"></script>
|
||||
<script src="js/io/formats/bbmodel.js"></script>
|
||||
<script src="js/io/formats/java_block.js"></script>
|
||||
<script src="js/io/formats/bedrock.js"></script>
|
||||
<script src="js/io/formats/bedrock_old.js"></script>
|
||||
<script src="js/io/formats/obj.js"></script>
|
||||
<script src="js/io/formats/gltf.js"></script>
|
||||
<script src="js/io/formats/modded_entity.js"></script>
|
||||
<script src="js/io/formats/optifine_jem.js"></script>
|
||||
<script src="js/io/formats/optifine_jpm.js"></script>
|
||||
<script src="js/io/formats/skin.js"></script>
|
||||
|
||||
<script>if (window.module) module = window.module;</script>
|
||||
|
||||
@ -131,7 +134,7 @@
|
||||
<div class="progress_bar" id="update_bar">
|
||||
<div class="progress_bar_inner"></div>
|
||||
</div>
|
||||
<div class="dialog_bar" hidden>
|
||||
<div class="dialog_bar button_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>
|
||||
@ -177,7 +180,7 @@
|
||||
<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" hidden>
|
||||
<div class="dialog_bar button_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>
|
||||
@ -197,13 +200,12 @@
|
||||
</div>
|
||||
<div class="edit_session_inactive">
|
||||
<p class="tl">edit_session.about</p>
|
||||
<p>This feature is in BETA. Bugs may occur while using it. The connection server is currently unstable, please check <a href="https://github.com/JannisX11/blockbench/issues/641">Issue #641</a> for status updates.</p>
|
||||
</div>
|
||||
<div class="edit_session_active hidden">
|
||||
<p><b class="tl">edit_session.status</b>: <span class="tl" id="edit_session_status">edit_session.connected</span></p>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="edit_session_inactive confirm_btn tl" onclick="EditSession.join();">edit_session.join</button>
|
||||
<button type="button" class="edit_session_inactive tl" onclick="EditSession.start();">edit_session.create</button>
|
||||
<button type="button" class="edit_session_active tl" onclick="EditSession.quit();">edit_session.quit</button>
|
||||
@ -240,7 +242,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<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>
|
||||
@ -262,9 +264,11 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="tl confirm_btn" onclick="">dialog.import</button>
|
||||
<button type="button" class="cancel_btn tl" onclick="hideDialog();BarItems.close_project.click()">dialog.cancel</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="image_extruder">
|
||||
@ -291,7 +295,7 @@
|
||||
|
||||
<canvas height="256" width="256" id="extrusion_canvas"></canvas>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="confirm_btn tl" onclick="Extruder.startConversion()">Scan and Import</button>
|
||||
<button type="button" class="cancel_btn tl" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
@ -338,7 +342,7 @@
|
||||
|
||||
<div class="dialog_bar narrow" id="scaling_clipping_warning"></div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" onclick="scaleAll(true)" class="confirm_btn tl">dialog.scale.confirm</button>
|
||||
<button type="button" class="cancel_btn tl" onclick="cancelScaleAll()">dialog.cancel</button>
|
||||
<button type="button" class="minor hidden tl" id="scale_overflow_btn" onclick="scaleAllSelectOverflow()">dialog.scale.select_overflow</button>
|
||||
@ -387,7 +391,7 @@
|
||||
<div class="dialog_bar">
|
||||
<input type="text" id="preset_name" class="input_wide" id="new preset">
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="tl confirm_btn" onclick="DisplayMode.createPreset()">dialog.display_preset.create</button>
|
||||
<button type="button" class="tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
@ -422,7 +426,7 @@
|
||||
<input type="range" min="0" max="100" step="1" value="100" class="tool half" id="selgen_random">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="tl confirm_btn" onclick="createSelection()">dialog.select.select</button>
|
||||
<button type="button" class="tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
@ -571,9 +575,7 @@
|
||||
<i class="icon-blockbench_inverted"></i>
|
||||
<span>Blockbench</span>
|
||||
</div>
|
||||
<p><b class="tl">about.version</b> <span id="version_tag"><script>
|
||||
$('#version_tag').text(appVersion)
|
||||
</script></span></p>
|
||||
<p><b class="tl">about.version</b> <span id="version_tag"></span></p>
|
||||
<p><b class="tl">about.creator</b> JannisX11</p>
|
||||
<p><b class="tl">about.website</b> <a class="open-in-browser" href="http://blockbench.net">blockbench.net</a></p>
|
||||
<p><b class="tl">about.bugtracker</b> <a class="open-in-browser" href="https://github.com/JannisX11/blockbench/issues">github.com/JannisX11/blockbench</a></p>
|
||||
@ -597,7 +599,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar" hidden>
|
||||
<div class="dialog_bar button_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>
|
||||
@ -624,7 +626,9 @@
|
||||
<div class="toolbar_wrapper uv_dialog"></div>
|
||||
</div>
|
||||
|
||||
<button type="button" onclick="hideDialog()" class="confirm_btn cancel_btn hidden">dialog.close</button>
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" onclick="hideDialog()" class="confirm_btn cancel_btn hidden">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>
|
||||
@ -636,7 +640,7 @@
|
||||
<input type="text" id="text_input_field" class="dark_bordered input_wide">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<div class="dialog_bar button_bar">
|
||||
<button type="button" class="confirm_btn tl" onclick="hideDialog()">dialog.confirm</button>
|
||||
<button type="button" class="cancel_btn tl" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
@ -700,11 +704,12 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div id="left_bar" class="sidebar">
|
||||
|
||||
<div id="uv" class="panel selection_only">
|
||||
<div class="bar next_to_title" id="uv_title_bar">
|
||||
<div id="project_resolution_status" onclick="BarItems.project_window.trigger()">32x32</div>
|
||||
<div id="project_resolution_status" onclick="BarItems.project_window.trigger()"></div>
|
||||
</div>
|
||||
<div id="uv_panel_sides" onclick="main_uv.loadSelectedFace()" class="bar tabs_small block_mode_only">
|
||||
<div id="uv_panel_sides" onclick="main_uv.loadSelectedFace()" class="bar tabs_small">
|
||||
|
||||
<input type="radio" name="side" id="north_radio" checked>
|
||||
<label class="tl" for="north_radio">face.north</label>
|
||||
@ -725,6 +730,7 @@
|
||||
<label class="tl" for="down_radio">face.down</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="display" class="panel">
|
||||
<div class="toolbar_wrapper display"></div>
|
||||
<p class="tl">display.slot</p>
|
||||
@ -793,28 +799,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="animations" class="panel">
|
||||
<div class="toolbar_wrapper animations"></div>
|
||||
<ul id="animations_list" class="list" v-sortable="{onUpdate: sort, fallbackTolerance: 10, animation: 0, handle: ':not(.animation_play_toggle)'}">
|
||||
<li
|
||||
v-for="animation in animations"
|
||||
v-bind:class="{ selected: animation.selected }"
|
||||
v-bind:anim_id="animation.uuid"
|
||||
class="animation"
|
||||
v-on:click.stop="animation.select()"
|
||||
v-on:dblclick.stop="animation.rename()"
|
||||
:key="animation.uuid"
|
||||
@contextmenu.prevent.stop="animation.showContextMenu($event)"
|
||||
>
|
||||
<i class="material-icons">movie</i>
|
||||
<input class="animation_name" v-model="animation.name" disabled="true">
|
||||
<div class="animation_play_toggle" v-on:click.stop="animation.togglePlayingState()">
|
||||
<i v-if="animation.playing" class="fa_big far fa-play-circle"></i>
|
||||
<i v-else class="fa_big far fa-circle"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="keyframe" class="panel">
|
||||
<div class="toolbar_wrapper keyframe"></div>
|
||||
<p class="tl" id="keyframe_type_label"></p>
|
||||
@ -851,10 +837,12 @@
|
||||
<textarea id="keyframe_instructions" style="height: 90px;" class="code keyframe_input tab_target" axis="instructions" oninput="updateKeyframeValue(this)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="variable_placeholders" class="panel grow">
|
||||
<p class="tl">panel.variable_placeholders.info</p>
|
||||
<textarea id="var_placeholder_area" class="code tab_target" style="flex-grow: 1;" onkeyup="Animator.preview()"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="textures" class="panel grow">
|
||||
<div class="toolbar_wrapper texturelist"></div>
|
||||
<ul id="texture_list" class="list">
|
||||
@ -862,6 +850,7 @@
|
||||
v-for="texture in textures"
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.uuid"
|
||||
:key="texture.uuid"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@ -870,18 +859,28 @@
|
||||
<div class="texture_icon_wrapper">
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="" v-if="texture.show_icon" />
|
||||
<i class="material-icons texture_error" v-bind:title="texture.getErrorMessage()" v-if="texture.error">error_outline</i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1 && !Format.single_texture"></i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1"></i>
|
||||
</div>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" v-on:click="texture.save()">
|
||||
<div class="texture_description_wrapper">
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{ texture.error
|
||||
? texture.getErrorMessage()
|
||||
: texture.width + ' x ' + texture.height + 'px'
|
||||
}}</div>
|
||||
</div>
|
||||
<i class="material-icons texture_visibility_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<i class="material-icons texture_particle_icon clickable"
|
||||
v-bind:class="{icon_off: !texture.visible}"
|
||||
v-if="Project.layered_textures"
|
||||
@click="texture.toggleVisibility()"
|
||||
@dblclick.stop
|
||||
>
|
||||
{{ texture.visible ? 'visibility' : 'visibility_off' }}
|
||||
</i>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" @click="texture.save()">
|
||||
<template v-if="texture.saved">check_circle</template>
|
||||
<template v-else>save</template>
|
||||
</i>
|
||||
<i class="material-icons texture_particle_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{ texture.error
|
||||
? texture.getErrorMessage()
|
||||
: texture.width + ' x ' + texture.height + 'px'
|
||||
}}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -899,13 +898,6 @@
|
||||
<div class="toolbar_wrapper element_rotation"></div>
|
||||
</div>
|
||||
|
||||
<div id="bone" class="panel selection_only">
|
||||
<p class="tl">panel.element.origin</p>
|
||||
<div class="toolbar_wrapper bone_origin"></div>
|
||||
<!--p class="tl">panel.bone.ik</p>
|
||||
<div class="toolbar_wrapper bone_ik"></div-->
|
||||
</div>
|
||||
|
||||
<div id="color" class="panel">
|
||||
<div id="color_panel_wrapper">
|
||||
<div id="color_panel_head">
|
||||
@ -923,7 +915,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="uv_panel_sides" onclick="main_uv.loadSelectedFace()" class="bar tabs_small block_mode_only">
|
||||
<div id="uv_panel_sides" onclick="main_uv.loadSelectedFace()" class="bar tabs_small">
|
||||
|
||||
<input type="radio" name="tab" id="radio_color_picker" value="picker" v-model="open_tab">
|
||||
<label class="tl" for="radio_color_picker">panel.color.picker</label>
|
||||
@ -963,21 +955,6 @@
|
||||
<vue-tree :option="option"></vue-tree>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="chat" class="panel grow">
|
||||
<div class="bar next_to_title" id="chat_title_bar"></div>
|
||||
<ul id="chat_history" v-if="expanded">
|
||||
<li v-for="msg in history">
|
||||
<b v-if="msg.showAuthor()" v-bind:class="{self: msg.self}">{{ msg.author }}:</b>
|
||||
<span class="text" v-bind:style="{color: msg.hex || 'inherit'}" v-html="msg.html"></span>
|
||||
<span class="timestamp">{{ msg.timestamp }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="chat_bar">
|
||||
<input type="text" id="chat_input" class="dark_bordered f_left" maxlength="512">
|
||||
<i class="material-icons" onclick="Chat.send()">send</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="preview">
|
||||
@ -1013,9 +990,6 @@
|
||||
</div>
|
||||
<div id="timeline_body">
|
||||
<div id="timeline_body_inner" v-bind:style="{width: (size*length + head_width)+'px'}" @contextmenu.stop="Timeline.showMenu($event)">
|
||||
<div id="timeline_playhead_line"
|
||||
v-bind:style="{left: (8 + playhead * size + head_width) + 'px'}"
|
||||
></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'}" v-on:dblclick.stop="toggleAnimator(animator)">
|
||||
@ -1104,18 +1078,28 @@
|
||||
</left>
|
||||
<right>
|
||||
<h2 class="tl">mode.start.recent</h2>
|
||||
<ul v-if="true">
|
||||
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-bind:title="project.path" class="recent_project">
|
||||
<div id="start_screen_list_type" v-if="isApp && !redact_names">
|
||||
<li class="tool" v-bind:class="{selected: list_type == 'list'}" v-on:click="setListType('list')">
|
||||
<i class="material-icons">list</i>
|
||||
</li>
|
||||
<li class="tool" v-bind:class="{selected: list_type == 'grid'}" v-on:click="setListType('grid')">
|
||||
<i class="material-icons">view_module</i>
|
||||
</li>
|
||||
</div>
|
||||
<div v-if="redact_names">{{ '['+tl('generic.redacted')+']' }}</div>
|
||||
<ul v-else-if="list_type == 'list'">
|
||||
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-key="project.path" v-bind:title="redact_names ? '' : project.path" class="recent_project">
|
||||
<span class="icon_wrapper" v-html="Blockbench.getIconNode(project.icon).outerHTML"></span>
|
||||
<span class="recent_project_name">{{ project.name }}</span>
|
||||
<span class="recent_project_name">{{ redact_names ? `[${tl('generic.redacted')}]` : project.name }}</span>
|
||||
<span class="recent_project_date">{{ getDate(project) }}</span>
|
||||
</li>
|
||||
<div v-if="recent.length == 0">{{ tl('mode.start.no_recents') }}</div>
|
||||
</ul>
|
||||
<ul v-else>
|
||||
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-bind:title="project.path" class="recent_project thumbnail" :style="{'background-image': `url('${project.thumbnail}')`}">
|
||||
|
||||
<span class="recent_project_name">{{ project.name }}</span>
|
||||
<ul :class="{redact: redact_names}" v-else>
|
||||
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-key="project.path" v-bind:title="redact_names ? '' : project.path" class="recent_project thumbnail">
|
||||
<div class="thumbnail_image" :style="{'background-image': getThumbnail(project.path)}"></div>
|
||||
<span class="recent_project_name">{{ redact_names ? `[${tl('generic.redacted')}]` : project.name }}</span>
|
||||
<span class="icon_wrapper" v-html="Blockbench.getIconNode(project.icon).outerHTML"></span>
|
||||
</li>
|
||||
<div v-if="recent.length == 0">{{ tl('mode.start.no_recents') }}</div>
|
||||
</ul>
|
||||
@ -1126,12 +1110,22 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="status_bar" @contextmenu="Interface.status_bar.menu.show(event)">
|
||||
|
||||
<div class="f_left" v-if="settings.streamer_mode.value"
|
||||
style="background-color: var(--color-stream); color: var(--color-light);"
|
||||
@click="Settings.open({search: 'streamer_mode'})"
|
||||
v-bind:title="tl('interface.streamer_mode_on')"
|
||||
>
|
||||
<i class="material-icons">live_tv</i>
|
||||
</div>
|
||||
<div id="status_saved">
|
||||
<i class="material-icons" v-if="Prop.project_saved" v-bind:title="tl('status_bar.saved')">check</i>
|
||||
<i class="material-icons" v-else v-bind:title="tl('status_bar.unsaved')">close</i>
|
||||
</div>
|
||||
<div v-html="Blockbench.getIconNode(Format.icon).outerHTML" v-bind:title="Format.name"></div>
|
||||
<div v-if="Prop.recording" v-html="Blockbench.getIconNode('fiber_manual_record').outerHTML" style="color: var(--color-close)" v-bind:title="tl('status_bar.recording')"></div>
|
||||
|
||||
|
||||
<div id="status_name">
|
||||
{{ Prop.file_name }}
|
||||
</div>
|
||||
|
126
js/animations.js
126
js/animations.js
@ -2,7 +2,7 @@ class Animation {
|
||||
constructor(data) {
|
||||
this.name = '';
|
||||
this.uuid = guid()
|
||||
this.loop = false;
|
||||
this.loop = 'once';
|
||||
this.playing = false;
|
||||
this.override = false;
|
||||
this.selected = false;
|
||||
@ -16,7 +16,7 @@ class Animation {
|
||||
}
|
||||
extend(data) {
|
||||
Merge.string(this, data, 'name')
|
||||
Merge.boolean(this, data, 'loop')
|
||||
Merge.string(this, data, 'loop', val => ['once', 'loop', 'hold'].includes(val))
|
||||
Merge.boolean(this, data, 'override')
|
||||
Merge.string(this, data, 'anim_time_update')
|
||||
Merge.number(this, data, 'length')
|
||||
@ -235,11 +235,20 @@ class Animation {
|
||||
}
|
||||
return len
|
||||
}
|
||||
setLoop(value, undo) {
|
||||
if ((value == 'once' || value == 'loop' || value == 'hold') && value !== this.loop) {
|
||||
if (undo) Undo.initEdit({animations: [this]})
|
||||
this.loop = value;
|
||||
if (undo) Undo.finishEdit('change animation loop mode')
|
||||
}
|
||||
}
|
||||
}
|
||||
Animation.prototype.menu = new Menu([
|
||||
{name: 'menu.animation.loop', icon: (a) => (a.loop?'check_box':'check_box_outline_blank'), click: function(animation) {
|
||||
animation.loop = !animation.loop
|
||||
}},
|
||||
{name: 'menu.animation.loop', icon: 'loop', children: [
|
||||
{name: 'menu.animation.loop.once', icon: animation => (animation.loop == 'once' ? 'radio_button_checked' : 'radio_button_unchecked'), click(animation) {animation.setLoop('once', true)}},
|
||||
{name: 'menu.animation.loop.hold', icon: animation => (animation.loop == 'hold' ? 'radio_button_checked' : 'radio_button_unchecked'), click(animation) {animation.setLoop('hold', true)}},
|
||||
{name: 'menu.animation.loop.loop', icon: animation => (animation.loop == 'loop' ? 'radio_button_checked' : 'radio_button_unchecked'), click(animation) {animation.setLoop('loop', true)}},
|
||||
]},
|
||||
{name: 'menu.animation.override', icon: (a) => (a.override?'check_box':'check_box_outline_blank'), click: function(animation) {
|
||||
animation.override = !animation.override
|
||||
}},
|
||||
@ -250,14 +259,6 @@ class Animation {
|
||||
'duplicate',
|
||||
'rename',
|
||||
'delete',
|
||||
/*
|
||||
rename
|
||||
Loop: checkbox
|
||||
Override: checkbox
|
||||
anim_time_update:
|
||||
WalkPosition
|
||||
delete
|
||||
*/
|
||||
])
|
||||
class TimelineMarker {
|
||||
constructor(data) {
|
||||
@ -773,8 +774,8 @@ class Keyframe {
|
||||
|
||||
var end = value.match(/(\+|-)\s*\d*(\.\d+)?\s*$/)
|
||||
if (end) {
|
||||
var number = (parseFloat( end[0] ) + amount)+''
|
||||
value = value.substr(0, end.index) + (number.substr(0,1)=='-'?'':'+') + trimFloatNumber(number)
|
||||
var number = (parseFloat( end[0] ) + amount)
|
||||
value = value.substr(0, end.index) + ((number.toString()).substr(0,1)=='-'?'':'+') + trimFloatNumber(number)
|
||||
} else {
|
||||
value = trimFloatNumber(amount) +(value.substr(0,1)=='-'?'':'+')+ value
|
||||
}
|
||||
@ -1263,7 +1264,7 @@ const Animator = {
|
||||
var a = json.animations[ani_name]
|
||||
var animation = new Animation({
|
||||
name: ani_name,
|
||||
loop: a.loop,
|
||||
loop: a.loop && (a.loop == 'hold_on_last_frame' ? 'hold' : 'loop'),
|
||||
override: a.override_previous_animation,
|
||||
anim_time_update: a.anim_time_update,
|
||||
length: a.animation_length,
|
||||
@ -1275,7 +1276,8 @@ const Animator = {
|
||||
if (a.bones) {
|
||||
for (var bone_name in a.bones) {
|
||||
var b = a.bones[bone_name]
|
||||
var group = Group.all.findInArray('name', bone_name)
|
||||
bone_name = bone_name.toLowerCase();
|
||||
var group = Group.all.find(group => group.name.toLowerCase() == bone_name)
|
||||
if (group) {
|
||||
var ba = new BoneAnimator(group.uuid, animation);
|
||||
animation.animators[group.uuid] = ba;
|
||||
@ -1362,7 +1364,13 @@ const Animator = {
|
||||
var animations = {}
|
||||
Animator.animations.forEach(function(a) {
|
||||
var ani_tag = animations[a.name] = {};
|
||||
if (a.getMaxLength() == 0 || a.loop) ani_tag.loop = true;
|
||||
|
||||
if (a.loop == 'hold') {
|
||||
ani_tag.loop = 'hold_on_last_frame';
|
||||
} else if (a.loop == 'loop' || a.getMaxLength() == 0) {
|
||||
ani_tag.loop = true;
|
||||
}
|
||||
|
||||
if (a.length) ani_tag.animation_length = a.length;
|
||||
if (a.override) ani_tag.override_previous_animation = true;
|
||||
if (a.anim_time_update) ani_tag.anim_time_update = a.anim_time_update;
|
||||
@ -1561,10 +1569,12 @@ const Timeline = {
|
||||
var lef = mouse_pos.x - R.panel_offset[0] - body.scrollLeft - Timeline.vue._data.head_width;
|
||||
var rig = body.clientWidth - (mouse_pos.x - R.panel_offset[0] - body.scrollLeft);
|
||||
|
||||
if (top < 0) body.scrollTop = body.scrollTop - 5;
|
||||
if (bot < 0) body.scrollTop = Math.clamp(body.scrollTop + 5, 0, body_inner.clientHeight - body.clientHeight + 3);
|
||||
if (lef < 0) body.scrollLeft = body.scrollLeft - 5;
|
||||
if (rig < 0) body.scrollLeft = Math.clamp(body.scrollLeft + 5, 0, body_inner.clientWidth - body.clientWidth);
|
||||
let speed = 15;
|
||||
|
||||
if (top < 0) body.scrollTop = body.scrollTop - speed;
|
||||
if (bot < 0) body.scrollTop = Math.clamp(body.scrollTop + speed, 0, body_inner.clientHeight - body.clientHeight + 3);
|
||||
if (lef < 0) body.scrollLeft = body.scrollLeft - speed;
|
||||
if (rig < 0) body.scrollLeft = Math.clamp(body.scrollLeft + speed, 0, body_inner.clientWidth - body.clientWidth);
|
||||
},
|
||||
end(e) {
|
||||
if (!Timeline.selector.selecting) return false;
|
||||
@ -1629,16 +1639,22 @@ const Timeline = {
|
||||
|
||||
if (e.target.id == 'timeline_endbracket') {
|
||||
|
||||
Timeline.dragging_endbracket = true;
|
||||
Undo.initEdit({animations: [Animator.selected]});
|
||||
if (Animator.selected) {
|
||||
Timeline.dragging_endbracket = true;
|
||||
Undo.initEdit({animations: [Animator.selected]});
|
||||
} else {
|
||||
Blockbench.showQuickMessage('message.no_animation_selected');
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
convertTouchEvent(e);
|
||||
Timeline.dragging_playhead = true;
|
||||
let time = (e.offsetX) / Timeline.vue._data.size
|
||||
Timeline.setTime(Timeline.snapTime(time))
|
||||
Animator.preview()
|
||||
|
||||
let offset = e.clientX - $('#timeline_time').offset().left;
|
||||
let time = Timeline.snapTime(offset / Timeline.vue._data.size);
|
||||
Timeline.setTime(time);
|
||||
Animator.preview();
|
||||
}
|
||||
})
|
||||
$(document).on('mousemove touchmove', e => {
|
||||
@ -1803,8 +1819,6 @@ const Timeline = {
|
||||
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)
|
||||
@ -1899,30 +1913,33 @@ const Timeline = {
|
||||
Timeline.pause()
|
||||
Timeline.playing = true
|
||||
BarItems.play_animation.setIcon('pause')
|
||||
Timeline.interval = setInterval(Timeline.loop, 100/6)
|
||||
Timeline.loop()
|
||||
},
|
||||
loop() {
|
||||
Animator.preview()
|
||||
if (Animator.selected && Timeline.time < (Animator.selected.length||1e3)) {
|
||||
|
||||
Animator.interval = setTimeout(Timeline.loop, 100/6)
|
||||
Timeline.setTime(Timeline.time + (1/60) * (Timeline.playback_speed/100))
|
||||
} else {
|
||||
Timeline.setTime(0)
|
||||
if (Animator.selected && Animator.selected.loop) {
|
||||
Timeline.start()
|
||||
} else {
|
||||
if (Animator.selected.loop == 'once') {
|
||||
Timeline.setTime(0)
|
||||
Timeline.pause()
|
||||
Animator.preview()
|
||||
} else if (Animator.selected.loop == 'hold') {
|
||||
Timeline.pause()
|
||||
} else {
|
||||
Timeline.setTime(0)
|
||||
Timeline.start()
|
||||
}
|
||||
}
|
||||
},
|
||||
pause() {
|
||||
Timeline.playing = false;
|
||||
BarItems.play_animation.setIcon('play_arrow')
|
||||
if (Animator.interval) {
|
||||
clearInterval(Animator.interval)
|
||||
Animator.interval = false
|
||||
if (Timeline.interval) {
|
||||
clearInterval(Timeline.interval)
|
||||
Timeline.interval = false
|
||||
}
|
||||
Timeline.playing_sounds.forEach(media => {
|
||||
if (!media.paused) {
|
||||
@ -2191,14 +2208,6 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('move keyframes')
|
||||
}
|
||||
})
|
||||
/*
|
||||
new BarSlider('volume', {
|
||||
category: 'animation',
|
||||
min: 0, max: 100, step: 5, width: 80,
|
||||
onChange: function(slider) {
|
||||
Animator.volume = slider.get();
|
||||
}
|
||||
})*/
|
||||
new Action('reset_keyframe', {
|
||||
icon: 'replay',
|
||||
category: 'animation',
|
||||
@ -2206,7 +2215,7 @@ BARS.defineActions(function() {
|
||||
click: function () {
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
Timeline.selected.forEach((kf) => {
|
||||
var n = kf.channel === 'scale' ? 1 : 0;
|
||||
var n = kf.channel === 'scale' ? '1' : '0';
|
||||
kf.extend({
|
||||
x: n,
|
||||
y: n,
|
||||
@ -2225,11 +2234,14 @@ BARS.defineActions(function() {
|
||||
condition: () => Animator.open && Timeline.selected.length,
|
||||
click: function () {
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
let time_before = Timeline.time;
|
||||
Timeline.selected.forEach((kf) => {
|
||||
if (kf.animator.fillValues) {
|
||||
Timeline.time = kf.time;
|
||||
kf.animator.fillValues(kf, null, false);
|
||||
}
|
||||
})
|
||||
Timeline.time = time_before;
|
||||
Undo.finishEdit('reset keyframes')
|
||||
updateKeyframeSelection()
|
||||
}
|
||||
@ -2351,6 +2363,28 @@ BARS.defineActions(function() {
|
||||
}
|
||||
})
|
||||
|
||||
new Action('jump_to_timeline_start', {
|
||||
icon: 'skip_previous',
|
||||
category: 'animation',
|
||||
condition: {modes: ['animate']},
|
||||
keybind: new Keybind({key: 36}),
|
||||
click: function () {
|
||||
Timeline.setTime(0)
|
||||
Animator.preview()
|
||||
}
|
||||
})
|
||||
|
||||
new Action('jump_to_timeline_end', {
|
||||
icon: 'skip_next',
|
||||
category: 'animation',
|
||||
condition: {modes: ['animate']},
|
||||
keybind: new Keybind({key: 35}),
|
||||
click: function () {
|
||||
Timeline.setTime(Animator.selected ? Animator.selected.length : 0)
|
||||
Animator.preview()
|
||||
}
|
||||
})
|
||||
|
||||
new Action('move_keyframe_back', {
|
||||
icon: 'arrow_back',
|
||||
category: 'transform',
|
||||
|
14
js/api.js
14
js/api.js
@ -28,7 +28,7 @@ const Blockbench = {
|
||||
localStorage.removeItem('backup_model')
|
||||
if (isApp) {
|
||||
Blockbench.addFlag('allow_closing')
|
||||
Blockbench.flags.push('allow_reload')
|
||||
Blockbench.addFlag('allow_reload')
|
||||
currentwindow.reload()
|
||||
} else {
|
||||
location.reload()
|
||||
@ -287,7 +287,9 @@ const Blockbench = {
|
||||
extensions: options.extensions
|
||||
}],
|
||||
properties: (properties.length && Blockbench.platform !== 'darwin')?properties:undefined,
|
||||
defaultPath: options.startpath
|
||||
defaultPath: settings.streamer_mode.value
|
||||
? app.getPath('desktop')
|
||||
: options.startpath
|
||||
},
|
||||
function (fileNames) {
|
||||
if (!fileNames) return;
|
||||
@ -489,9 +491,11 @@ const Blockbench = {
|
||||
name: options.type,
|
||||
extensions: options.extensions
|
||||
} ],
|
||||
defaultPath: (options.startpath && options.startpath !== 'Unknown')
|
||||
? options.startpath.replace(/\.\w+$/, '')
|
||||
: options.name
|
||||
defaultPath: settings.streamer_mode.value
|
||||
? app.getPath('desktop')
|
||||
: ((options.startpath && options.startpath !== 'Unknown')
|
||||
? options.startpath.replace(/\.\w+$/, '')
|
||||
: options.name)
|
||||
}, function (file_path) {
|
||||
if (!file_path) return;
|
||||
if (options.resource_id) {
|
||||
|
@ -194,7 +194,7 @@ function updateSelection() {
|
||||
Canvas.updateOrigin();
|
||||
Transformer.updateSelection();
|
||||
Transformer.update();
|
||||
previews.forEach(preview => {
|
||||
Preview.all.forEach(preview => {
|
||||
preview.updateAnnotations();
|
||||
})
|
||||
|
||||
@ -311,6 +311,12 @@ const TickUpdates = {
|
||||
}
|
||||
}
|
||||
|
||||
const documentReady = new Promise((resolve, reject) => {
|
||||
$(document).ready(function() {
|
||||
resolve()
|
||||
})
|
||||
});
|
||||
|
||||
const entityMode = {
|
||||
hardcodes: JSON.parse('{"geometry.chicken":{"body":{"rotation":[90,0,0]}},"geometry.llama":{"chest1":{"rotation":[0,90,0]},"chest2":{"rotation":[0,90,0]},"body":{"rotation":[90,0,0]}},"geometry.cow":{"body":{"rotation":[90,0,0]}},"geometry.sheep.sheared":{"body":{"rotation":[90,0,0]}},"geometry.sheep":{"body":{"rotation":[90,0,0]}},"geometry.phantom":{"body":{"rotation":[0,0,0]},"wing0":{"rotation":[0,0,5.7]},"wingtip0":{"rotation":[0,0,5.7]},"wing1":{"rotation":[0,0,-5.7]},"wingtip1":{"rotation":[0,0,-5.7]},"head":{"rotation":[11.5,0,0]},"tail":{"rotation":[0,0,0]},"tailtip":{"rotation":[0,0,0]}},"geometry.pig":{"body":{"rotation":[90,0,0]}},"geometry.ocelot":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.cat":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.turtle":{"eggbelly":{"rotation":[90,0,0]},"body":{"rotation":[90,0,0]}},"geometry.villager.witch":{"hat2":{"rotation":[-3,0,1.5]},"hat3":{"rotation":[-6,0,3]},"hat4":{"rotation":[-12,0,6]}},"geometry.pufferfish.mid":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.pufferfish.large":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.tropicalfish_a":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}},"geometry.tropicalfish_b":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}}}')
|
||||
}
|
||||
|
@ -66,12 +66,11 @@ if (!isApp) {
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Blockbench.on('before_closing', (event) => {
|
||||
if (!Blockbench.hasFlag('no_localstorage_saving')) {
|
||||
Settings.saveLocalStorages()
|
||||
}
|
||||
})
|
||||
|
||||
setInterval(function() {
|
||||
Prop.fps = framespersecond;
|
||||
@ -106,6 +105,8 @@ $('#texture_list').contextmenu(function(event) {
|
||||
Interface.Panels.textures.menu.show(event)
|
||||
})
|
||||
|
||||
updateProjectResolution()
|
||||
|
||||
setupInterface()
|
||||
setupDragHandlers()
|
||||
|
||||
|
@ -36,7 +36,7 @@ const Clipbench = {
|
||||
if ((p == 'uv' || p == 'preview') && Modes.edit) {
|
||||
return Clipbench.types.face;
|
||||
}
|
||||
if (p == 'textures' && isApp && (textures.selected || mode === 2)) {
|
||||
if (p == 'textures' && isApp && (Texture.selected || mode === 2)) {
|
||||
return Clipbench.types.texture;
|
||||
}
|
||||
if (p == 'outliner' && Modes.edit) {
|
||||
@ -66,7 +66,7 @@ const Clipbench = {
|
||||
main_uv.copy(event);
|
||||
break;
|
||||
case 'texture':
|
||||
Clipbench.setTexture(textures.selected);
|
||||
Clipbench.setTexture(Texture.selected);
|
||||
if (cut) {
|
||||
BarItems.delete.trigger();
|
||||
}
|
||||
|
253
js/desktop.js
253
js/desktop.js
@ -1,5 +1,5 @@
|
||||
const electron = require('electron').remote;
|
||||
const {clipboard, shell, nativeImage} = require('electron');
|
||||
const {clipboard, shell, nativeImage, ipcRenderer} = require('electron');
|
||||
const app = electron.app;
|
||||
const fs = require('fs');
|
||||
const NodeBuffer = require('buffer');
|
||||
@ -7,7 +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 PathModule = require('path');
|
||||
|
||||
const currentwindow = electron.getCurrentWindow();
|
||||
const ElecDialogs = {};
|
||||
@ -57,10 +57,15 @@ function initializeDesktopApp() {
|
||||
} else {
|
||||
Prop.zoom = 100 + currentwindow.webContents.getZoomLevel()*12
|
||||
}
|
||||
if (fs.existsSync(app.getPath('userData')+osfs+'backups') === false) {
|
||||
fs.mkdirSync( app.getPath('userData')+osfs+'backups')
|
||||
|
||||
function makeUtilFolder(name) {
|
||||
let path = PathModule.join(app.getPath('userData'), name)
|
||||
if (!fs.existsSync(path)) fs.mkdirSync(path)
|
||||
}
|
||||
['backups', 'thumbnails'].forEach(makeUtilFolder)
|
||||
|
||||
createBackup(true)
|
||||
|
||||
$('.web_only').remove()
|
||||
if (__dirname.includes('C:\\xampp\\htdocs\\blockbench')) {
|
||||
Blockbench.addFlag('dev')
|
||||
@ -124,10 +129,6 @@ function addRecentProject(data) {
|
||||
icon: data.icon,
|
||||
day: new Date().dayOfYear()
|
||||
}
|
||||
// main_preview.screenshot({width: 200, height: 120}, url => {
|
||||
// project.thumbnail = url;
|
||||
// updateRecentProjects()
|
||||
// })
|
||||
recent_projects.splice(0, 0, project)
|
||||
app.addRecentDocument(data.path)
|
||||
if (recent_projects.length > Math.clamp(settings.recent_projects.value, 0, 256)) {
|
||||
@ -135,6 +136,55 @@ function addRecentProject(data) {
|
||||
}
|
||||
updateRecentProjects()
|
||||
}
|
||||
function updateRecentProjectThumbnail() {
|
||||
if (elements.length == 0) return;
|
||||
let path = ModelMeta.export_path || ModelMeta.save_path;
|
||||
let project = recent_projects.find(p => p.path == path);
|
||||
if (!project) return;
|
||||
|
||||
MediaPreview.resize(180, 100)
|
||||
MediaPreview.loadAnglePreset(DefaultCameraPresets[0])
|
||||
let center = getSelectionCenter(true);
|
||||
MediaPreview.controls.target.fromArray(center);
|
||||
MediaPreview.controls.target.add(scene.position);
|
||||
|
||||
let box = Canvas.getModelSize();
|
||||
let size = Math.max(box[0], box[1]*2)
|
||||
MediaPreview.camera.position.multiplyScalar(size/50)
|
||||
|
||||
MediaPreview.screenshot({crop: false}, url => {
|
||||
let hash = project.path.hashCode().toString().replace(/^-/, '0');
|
||||
let path = PathModule.join(app.getPath('userData'), 'thumbnails', `${hash}.png`)
|
||||
Blockbench.writeFile(path, {
|
||||
savetype: 'image',
|
||||
content: url
|
||||
})
|
||||
let store_path = project.path;
|
||||
project.path = '';
|
||||
project.path = store_path;
|
||||
})
|
||||
|
||||
// Clean old files
|
||||
if (Math.random() < 0.2) {
|
||||
let folder_path = PathModule.join(app.getPath('userData'), 'thumbnails')
|
||||
let existing_names = [];
|
||||
recent_projects.forEach(project => {
|
||||
let hash = project.path.hashCode().toString().replace(/^-/, '0');
|
||||
existing_names.safePush(hash)
|
||||
})
|
||||
fs.readdir(folder_path, (err, files) => {
|
||||
if (!err) {
|
||||
files.forEach((name, i) => {
|
||||
if (existing_names.includes(name.replace(/\..+$/, '')) == false) {
|
||||
try {
|
||||
fs.unlinkSync(folder_path +osfs+ name)
|
||||
} catch (err) {console.log(err)}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//Window Controls
|
||||
function updateWindowState(e, type) {
|
||||
@ -146,107 +196,6 @@ currentwindow.on('enter-full-screen', e => updateWindowState(e, 'screen'));
|
||||
currentwindow.on('leave-full-screen', e => updateWindowState(e, 'screen'));
|
||||
currentwindow.on('ready-to-show', e => updateWindowState(e, 'load'));
|
||||
|
||||
//Updates
|
||||
//Called on start to show message
|
||||
function getLatestVersion() {
|
||||
if (process.platform == 'linux') return;
|
||||
$.getJSON('https://raw.githubusercontent.com/JannisX11/blockbench/master/package.json', (data) => {
|
||||
if (data.version) {
|
||||
latest_version = data.version
|
||||
checkForUpdates()
|
||||
}
|
||||
}).fail(function() {
|
||||
latest_version = false
|
||||
})
|
||||
}
|
||||
function checkForUpdates(instant) {
|
||||
showDialog('updater')
|
||||
setProgressBar('update_bar', 0, 1)
|
||||
var data;
|
||||
if (latest_version === false) {
|
||||
|
||||
data = `<div class="tool" onclick="refreshUpdateDialog()">
|
||||
<i class="material-icons">refresh</i>
|
||||
<div class="tooltip">${tl('dialog.update.refresh')}</div>
|
||||
</div>
|
||||
<div class="dialog_bar narrow">
|
||||
<i class="material-icons blue_icon">cloud_off</i>${tl('dialog.update.no_connection')}
|
||||
</div>`;
|
||||
|
||||
} else if (latest_version !== appVersion) {
|
||||
data =
|
||||
`<div class="dialog_bar narrow">${tl('dialog.update.latest')}: ${latest_version}</div>
|
||||
<div class="dialog_bar narrow">${tl('dialog.update.installed')}: ${appVersion}</div>
|
||||
<div class=""><button type="button" class="uc_btn" id="update_button" onclick="installUpdate()">${tl('dialog.update.update')}</button></div>`;
|
||||
|
||||
if (instant) {
|
||||
setTimeout(function() {
|
||||
installUpdate()
|
||||
}, 60)
|
||||
}
|
||||
} else {
|
||||
data =
|
||||
`<div class="tool" onclick="refreshUpdateDialog()">
|
||||
<i class="material-icons">refresh</i>
|
||||
<div class="tooltip">${tl('dialog.update.refresh')}</div>
|
||||
</div>
|
||||
<div class="dialog_bar narrow">
|
||||
<i class="material-icons blue_icon">check</i>
|
||||
${tl('dialog.update.up_to_date')}
|
||||
</div>`;
|
||||
}
|
||||
$('#updater_content').html(data)
|
||||
}
|
||||
function refreshUpdateDialog() {
|
||||
currentwindow.webContents.session.clearCache(function() {
|
||||
data = '<div class="dialog_bar narrow"><i class="material-icons blue_icon spinning">refresh</i>'+tl('dialog.update.connecting')+'</div>'
|
||||
$('#updater_content').html(data)
|
||||
getLatestVersion()
|
||||
})
|
||||
}
|
||||
function installUpdate() {
|
||||
|
||||
Blockbench.showMessageBox({
|
||||
title: 'Updater',
|
||||
icon: 'update',
|
||||
message: 'The built-in updater is currently unavailable. Please download updates from https://blockbench.net/downloads for now!',
|
||||
})
|
||||
return;
|
||||
|
||||
console.log('Starting Update')
|
||||
var received_bytes = 0;
|
||||
var total_bytes = 0;
|
||||
|
||||
$('.uc_btn').css('visibility', 'hidden')
|
||||
|
||||
var asar_path = __dirname;
|
||||
if (asar_path.includes('.asar') === false) {
|
||||
asar_path = asar_path + osfs+'resources'+osfs+'app.asar';
|
||||
}
|
||||
|
||||
var file = originalFs.createWriteStream(asar_path);
|
||||
|
||||
https.get("https://blockbench.net/api/app.asar", function(response) {
|
||||
response.pipe(file);
|
||||
|
||||
total_bytes = parseInt(response.headers['content-length']);
|
||||
|
||||
response.on('end', updateInstallationEnd)
|
||||
response.on('data', function(chunk) {
|
||||
received_bytes += chunk.length;
|
||||
setProgressBar('update_bar', received_bytes / total_bytes, 1);
|
||||
})
|
||||
});
|
||||
}
|
||||
function updateInstallationEnd() {
|
||||
hideDialog();
|
||||
if (showSaveDialog()) {
|
||||
app.relaunch()
|
||||
app.exit()
|
||||
} else {
|
||||
Blockbench.showQuickMessage('message.restart_to_update');
|
||||
}
|
||||
}
|
||||
//Image Editor
|
||||
function changeImageEditor(texture, from_settings) {
|
||||
var dialog = new Dialog({
|
||||
@ -389,7 +338,12 @@ function createBackup(init) {
|
||||
})
|
||||
}
|
||||
//Close
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
try {
|
||||
updateRecentProjectThumbnail()
|
||||
} catch(err) {}
|
||||
|
||||
if (!Blockbench.hasFlag('allow_closing')) {
|
||||
setTimeout(function() {
|
||||
showSaveDialog(true)
|
||||
@ -397,6 +351,7 @@ window.onbeforeunload = function() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function showSaveDialog(close) {
|
||||
if (Blockbench.hasFlag('allow_reload')) {
|
||||
close = false
|
||||
@ -443,4 +398,82 @@ function closeBlockbenchWindow() {
|
||||
EditSession.quit()
|
||||
|
||||
return currentwindow.close();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
let update_available_promise = new Promise((resolve, reject) => {
|
||||
ipcRenderer.on('update-available', (event, arg) => {
|
||||
resolve({event, arg})
|
||||
})
|
||||
})
|
||||
|
||||
Promise.all([update_available_promise, documentReady]).then(results => {
|
||||
if (settings.automatic_updates.value) {
|
||||
ipcRenderer.send('allow-auto-update');
|
||||
|
||||
let icon_node = Blockbench.getIconNode('donut_large');
|
||||
icon_node.classList.add('spinning');
|
||||
let click_action;
|
||||
|
||||
let update_status = {
|
||||
name: tl('menu.help.updating', [0]),
|
||||
id: 'update_status',
|
||||
icon: icon_node,
|
||||
click() {
|
||||
if (click_action) click_action()
|
||||
}
|
||||
};
|
||||
MenuBar.menus.help.addAction('_');
|
||||
MenuBar.menus.help.addAction(update_status);
|
||||
function updateText(text) {
|
||||
update_status.name = text;
|
||||
$('li[menu_item=update_status]').each((i, node) => {
|
||||
node.childNodes.forEach(child => {
|
||||
if (child.nodeName == '#text') {
|
||||
child.textContent = text;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
ipcRenderer.on('update-progress', (event, status) => {
|
||||
updateText(tl('menu.help.updating', [Math.round(status.percent)]));
|
||||
})
|
||||
ipcRenderer.on('update-error', (event, err) => {
|
||||
updateText(tl('menu.help.update_failed'));
|
||||
icon_node.textContent = 'warning';
|
||||
icon_node.classList.remove('spinning')
|
||||
click_action = function() {
|
||||
currentwindow.openDevTools()
|
||||
}
|
||||
console.error(err);
|
||||
})
|
||||
ipcRenderer.on('update-downloaded', (event) => {
|
||||
updateText(tl('menu.help.update_ready'));
|
||||
icon_node.textContent = 'system_update_alt';
|
||||
icon_node.classList.remove('spinning')
|
||||
click_action = function() {
|
||||
app.relaunch();
|
||||
app.quit();
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
addStartScreenSection({
|
||||
color: 'var(--color-back)',
|
||||
graphic: {type: 'icon', icon: 'update'},
|
||||
text: [
|
||||
{type: 'h1', text: tl('message.update_notification.title')},
|
||||
{text: tl('message.update_notification.message')},
|
||||
{type: 'button', text: tl('generic.enable'), click: (e) => {
|
||||
Settings.open({search: 'automatic_updates'})
|
||||
}}
|
||||
]
|
||||
})
|
||||
}
|
||||
})
|
||||
})()
|
||||
|
||||
|
||||
|
@ -313,7 +313,7 @@ class refModel {
|
||||
transparent: true,
|
||||
vertexColors: THREE.FaceColors,
|
||||
side: 2,
|
||||
alphaTest: 0.2
|
||||
alphaTest: 0.05
|
||||
});
|
||||
}
|
||||
|
||||
@ -1390,7 +1390,6 @@ window.displayReferenceObjects = {
|
||||
clear: function() {
|
||||
display_scene.remove(displayReferenceObjects.active.model)
|
||||
displayReferenceObjects.active = false
|
||||
$('#donation_hint').hide()
|
||||
},
|
||||
ref_indexes: {
|
||||
thirdperson_righthand: 0,
|
||||
@ -1444,7 +1443,7 @@ enterDisplaySettings = function() { //Enterung Display Setting Mode, changes th
|
||||
|
||||
|
||||
buildGrid()
|
||||
setShading()
|
||||
updateShading()
|
||||
DisplayMode.loadThirdRight()
|
||||
|
||||
display_area.updateMatrixWorld()
|
||||
@ -1475,7 +1474,7 @@ exitDisplaySettings = function() { //Enterung Display Setting Mode, changes the
|
||||
}
|
||||
scene.add(Transformer)
|
||||
buildGrid()
|
||||
setShading()
|
||||
updateShading()
|
||||
Canvas.updateRenderSides()
|
||||
}
|
||||
function axisIndex(index) {
|
||||
@ -1823,23 +1822,13 @@ function updateDisplaySkin() {
|
||||
}
|
||||
var mat = displayReferenceObjects.refmodels.player.material
|
||||
|
||||
|
||||
var img = new Image()
|
||||
try {
|
||||
img.src = skin
|
||||
} catch(err) {
|
||||
}
|
||||
img.onload = function() {
|
||||
mat.map.dispose()
|
||||
var tex = new THREE.Texture(img)
|
||||
img.tex = tex;
|
||||
img.tex.magFilter = THREE.NearestFilter
|
||||
img.tex.minFilter = THREE.NearestFilter
|
||||
this.tex.needsUpdate = true;
|
||||
mat.map = tex;
|
||||
|
||||
mat.map.image.src = skin;
|
||||
mat.map.needsUpdate = true;
|
||||
mat.map.onUpdate = function() {
|
||||
mat.map.onUpdate = null;
|
||||
displayReferenceObjects.refmodels.player.setModelVariant(slim ? 'alex' : 'steve')
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
if (!val || typeof val !== 'string') {
|
||||
setPSkin('assets/player_skin.png')
|
||||
|
@ -2,12 +2,19 @@ const EditSession = {
|
||||
active: false,
|
||||
hosting: false,
|
||||
BBKey: '1h3sq3hoj6vfkh',
|
||||
ip: '104.248.38.177',
|
||||
clients: {},
|
||||
placeholder_names: ['R2D2', 'Tin Man', 'C3PO', 'WALL-E', 'EVE', 'BB-8', 'B1 Battle Droid', 'ASIMO', 'Atlas'],
|
||||
start() {
|
||||
if (EditSession.active) return;
|
||||
|
||||
var peer = EditSession.peer = new Peer({key: '1h3sq3hoj6vfkh'});
|
||||
var peer = EditSession.peer = new Peer({
|
||||
key: 'edit_session',
|
||||
host: EditSession.ip,
|
||||
port: 9000,
|
||||
path: '/sessions',
|
||||
secure: true
|
||||
});
|
||||
EditSession.username = $('#edit_session_username').val() || EditSession.placeholder_names.random();
|
||||
settings.username.value = EditSession.username;
|
||||
|
||||
@ -53,45 +60,58 @@ const EditSession = {
|
||||
})
|
||||
})
|
||||
peer.on('error', error => {
|
||||
console.log('Error creating edit session:', error)
|
||||
console.error('Error in edit session:', error)
|
||||
})
|
||||
},
|
||||
join() {
|
||||
if (EditSession.active) return;
|
||||
|
||||
EditSession.hosting = false;
|
||||
EditSession.peer = new Peer({key: '1h3sq3hoj6vfkh'});
|
||||
var token = $('#edit_session_token').val()
|
||||
EditSession.username = $('#edit_session_username').val() || EditSession.placeholder_names.random();
|
||||
settings.username.value = EditSession.username;
|
||||
if (!token || !EditSession._matchToken(token)) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_session',
|
||||
icon: 'cloud_off',
|
||||
buttons: [tl('dialog.ok')],
|
||||
}, result => {
|
||||
showDialog('edit_sessions');
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
EditSession.token = token;
|
||||
var conn = EditSession.peer.connect(token, {metadata: {username: EditSession.username}});
|
||||
EditSession.hosting = false;
|
||||
EditSession.peer = new Peer({
|
||||
key: 'edit_session',
|
||||
host: EditSession.ip,
|
||||
port: 9000,
|
||||
path: '/sessions',
|
||||
secure: true
|
||||
});
|
||||
EditSession.peer.on('open', function() {
|
||||
|
||||
conn.on('error', (e) => {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_session',
|
||||
icon: 'cloud_off',
|
||||
buttons: [tl('dialog.ok')],
|
||||
EditSession.username = $('#edit_session_username').val() || EditSession.placeholder_names.random();
|
||||
settings.username.value = EditSession.username;
|
||||
if (!token || !EditSession._matchToken(token)) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_session',
|
||||
icon: 'cloud_off',
|
||||
buttons: [tl('dialog.ok')],
|
||||
}, result => {
|
||||
showDialog('edit_sessions');
|
||||
})
|
||||
return;
|
||||
}
|
||||
EditSession.token = token;
|
||||
var conn = EditSession.peer.connect(token, {metadata: {username: EditSession.username}});
|
||||
|
||||
conn.on('error', (err) => {
|
||||
console.error('peer join error', err)
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_session',
|
||||
icon: 'cloud_off',
|
||||
buttons: [tl('dialog.ok')],
|
||||
})
|
||||
EditSession.quit()
|
||||
})
|
||||
conn.on('open', () => {
|
||||
hideDialog()
|
||||
EditSession.host = conn;
|
||||
EditSession.setState(true);
|
||||
EditSession.initConnection(conn)
|
||||
Blockbench.dispatchEvent('join_session', {conn})
|
||||
})
|
||||
EditSession.quit()
|
||||
})
|
||||
conn.on('open', () => {
|
||||
hideDialog()
|
||||
EditSession.host = conn;
|
||||
EditSession.setState(true);
|
||||
EditSession.initConnection(conn)
|
||||
Blockbench.dispatchEvent('join_session', {conn})
|
||||
EditSession.peer.on('error', error => {
|
||||
console.error('Error in edit session:', error)
|
||||
})
|
||||
},
|
||||
quit() {
|
||||
@ -393,12 +413,6 @@ Chat.Message = class {
|
||||
return (!prev) || (prev.author !== this.author);
|
||||
}
|
||||
}
|
||||
onVueSetup(function() {
|
||||
Chat.vue = new Vue({
|
||||
el: '#chat_history',
|
||||
data: Chat
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action('edit_session', {
|
||||
|
@ -705,6 +705,9 @@ class BarSelect extends Widget {
|
||||
if (data.width) {
|
||||
select.css('width', data.width+'px')
|
||||
}
|
||||
if (data.min_width) {
|
||||
select.css('min-width', data.min_width+'px')
|
||||
}
|
||||
select.click(event => {
|
||||
scope.open(event)
|
||||
});
|
||||
@ -925,10 +928,10 @@ class Toolbar {
|
||||
this.default_children = data.children.slice()
|
||||
}
|
||||
var jq = $(`<div class="toolbar">
|
||||
<div class="content"></div>
|
||||
<div class="tool toolbar_menu">
|
||||
<i class="material-icons">${this.vertical ? 'more_horiz' : 'more_vert'}</i>
|
||||
</div>
|
||||
<div class="content"></div>
|
||||
</div>`)
|
||||
this.node = jq.get(0)
|
||||
BarItem.prototype.addLabel(false, {
|
||||
@ -1251,12 +1254,6 @@ const BARS = {
|
||||
keybind: new Keybind({key: 69, ctrl: true}),
|
||||
click: function () {Settings.open()}
|
||||
})
|
||||
new Action('update_window', {
|
||||
icon: 'update',
|
||||
category: 'blockbench',
|
||||
condition: isApp,
|
||||
click: function () {checkForUpdates()}
|
||||
})
|
||||
new Action('reload', {
|
||||
icon: 'refresh',
|
||||
category: 'file',
|
||||
@ -1287,8 +1284,8 @@ const BARS = {
|
||||
//condition: () => (Modes.edit && (selected.length || Group.selected)),
|
||||
keybind: new Keybind({key: 46}),
|
||||
click: function () {
|
||||
if (Prop.active_panel == 'textures' && textures.selected) {
|
||||
textures.selected.remove()
|
||||
if (Prop.active_panel == 'textures' && Texture.selected) {
|
||||
Texture.selected.remove()
|
||||
} else if (Prop.active_panel == 'color' && ['palette', 'both'].includes(ColorPanel.vue._data.open_tab)) {
|
||||
if (ColorPanel.vue._data.palette.includes(ColorPanel.vue._data.main_color)) {
|
||||
ColorPanel.vue._data.palette.remove(ColorPanel.vue._data.main_color)
|
||||
@ -1425,8 +1422,7 @@ const BARS = {
|
||||
'outliner_toggle',
|
||||
'toggle_skin_layer',
|
||||
'cube_counter'
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
|
||||
Toolbars.texturelist = new Toolbar({
|
||||
@ -1436,8 +1432,7 @@ const BARS = {
|
||||
'create_texture',
|
||||
'reload_textures',
|
||||
'animated_textures'
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
Toolbars.tools = new Toolbar({
|
||||
id: 'tools',
|
||||
@ -1454,7 +1449,7 @@ const BARS = {
|
||||
'draw_shape_tool',
|
||||
'copy_paste_tool'
|
||||
],
|
||||
vertical: Blockbench.isMobile,
|
||||
vertical: Blockbench.isMobile == true,
|
||||
default_place: true
|
||||
})
|
||||
|
||||
@ -1472,8 +1467,7 @@ const BARS = {
|
||||
'slider_pos_x',
|
||||
'slider_pos_y',
|
||||
'slider_pos_z'
|
||||
],
|
||||
default_place: !Blockbench.isMobile
|
||||
]
|
||||
})
|
||||
Toolbars.element_size = new Toolbar({
|
||||
id: 'element_size',
|
||||
@ -1482,8 +1476,7 @@ const BARS = {
|
||||
'slider_size_y',
|
||||
'slider_size_z',
|
||||
'slider_inflate'
|
||||
],
|
||||
default_place: !Blockbench.isMobile
|
||||
]
|
||||
})
|
||||
Toolbars.element_origin = new Toolbar({
|
||||
id: 'element_origin',
|
||||
@ -1492,8 +1485,7 @@ const BARS = {
|
||||
'slider_origin_y',
|
||||
'slider_origin_z',
|
||||
'origin_to_geometry'
|
||||
],
|
||||
default_place: !Blockbench.isMobile
|
||||
]
|
||||
})
|
||||
Toolbars.element_rotation = new Toolbar({
|
||||
id: 'element_rotation',
|
||||
@ -1502,8 +1494,7 @@ const BARS = {
|
||||
'slider_rotation_y',
|
||||
'slider_rotation_z',
|
||||
'rescale_toggle'
|
||||
],
|
||||
default_place: !Blockbench.isMobile
|
||||
]
|
||||
})
|
||||
/*
|
||||
Toolbars.bone_ik = new Toolbar({
|
||||
@ -1550,8 +1541,7 @@ const BARS = {
|
||||
'add_display_preset',
|
||||
'apply_display_preset',
|
||||
'gui_light'
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
//UV
|
||||
Toolbars.main_uv = new Toolbar({
|
||||
@ -1566,8 +1556,7 @@ const BARS = {
|
||||
//Box
|
||||
'toggle_uv_overlay',
|
||||
'toggle_mirror_uv',
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
Toolbars.uv_dialog = new Toolbar({
|
||||
id: 'uv_dialog',
|
||||
@ -1605,8 +1594,7 @@ const BARS = {
|
||||
children: [
|
||||
'add_animation',
|
||||
'slider_animation_length',
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
Toolbars.keyframe = new Toolbar({
|
||||
id: 'keyframe',
|
||||
@ -1614,8 +1602,7 @@ const BARS = {
|
||||
'slider_keyframe_time',
|
||||
'change_keyframe_file',
|
||||
'reset_keyframe'
|
||||
],
|
||||
default_place: true
|
||||
]
|
||||
})
|
||||
Toolbars.timeline = new Toolbar({
|
||||
id: 'timeline',
|
||||
@ -1636,12 +1623,13 @@ const BARS = {
|
||||
Toolbars.main_tools = new Toolbar({
|
||||
id: 'main_tools',
|
||||
children: [
|
||||
'transform_space'
|
||||
'transform_space',
|
||||
'rotation_space'
|
||||
]
|
||||
})
|
||||
// update 3.4.1
|
||||
if (!Toolbars.main_tools.children.includes(BarItems.transform_space)) {
|
||||
Toolbars.main_tools.add(BarItems.transform_space, -1)
|
||||
// update 3.6
|
||||
if (!Toolbars.main_tools.children.includes(BarItems.rotation_space)) {
|
||||
Toolbars.main_tools.add(BarItems.rotation_space, -1)
|
||||
}
|
||||
Toolbars.brush = new Toolbar({
|
||||
id: 'brush',
|
||||
@ -1692,7 +1680,6 @@ const BARS = {
|
||||
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')
|
||||
},
|
||||
setupVue() {
|
||||
BARS.list = new Vue({
|
||||
|
@ -30,6 +30,7 @@ function Dialog(settings) {
|
||||
this.cancelEnabled = settings.cancelEnabled === false ? false : true
|
||||
this.onConfirm = settings.onConfirm ? settings.onConfirm : this.hide
|
||||
this.onCancel = settings.onCancel ? settings.onCancel : this.hide
|
||||
this.onButton = settings.onButton;
|
||||
|
||||
this.object;
|
||||
|
||||
@ -77,7 +78,7 @@ function Dialog(settings) {
|
||||
jq_dialog.append('<hr />')
|
||||
|
||||
} else if (data && Condition(data.condition)) {
|
||||
var bar = $(`<div class="dialog_bar form_bar_${form_id}"></div>`)
|
||||
var bar = $(`<div class="dialog_bar form_bar form_bar_${form_id}"></div>`)
|
||||
if (data.label) {
|
||||
bar.append(`<label class="name_space_left" for="${form_id}">${tl(data.label)+(data.nocolon?'':':')}</label>`)
|
||||
max_label_width = Math.max(getStringWidth(tl(data.label)), max_label_width)
|
||||
@ -118,7 +119,7 @@ function Dialog(settings) {
|
||||
var sel = el.find('select')
|
||||
for (var key in data.options) {
|
||||
var name = tl(data.options[key])
|
||||
sel.append(`<option id="${key}" ${data.default === key ? 'selected' : ''}>${name}</option>`)
|
||||
sel.append(`<option id="${key}" ${(data.value === key || data.default === key) ? 'selected' : ''}>${name}</option>`)
|
||||
}
|
||||
bar.append(el)
|
||||
break;
|
||||
@ -247,28 +248,35 @@ function Dialog(settings) {
|
||||
}
|
||||
if (this.buttons) {
|
||||
|
||||
|
||||
var buttons = []
|
||||
|
||||
scope.buttons.forEach(function(b, i) {
|
||||
var btn = $('<button type="button">'+tl(b)+'</button> ')
|
||||
buttons.push(btn)
|
||||
if (typeof scope.onButton == 'function') {
|
||||
btn.click((event) => {
|
||||
scope.onButton(i);
|
||||
})
|
||||
}
|
||||
})
|
||||
buttons[scope.confirmIndex] && buttons[scope.confirmIndex].addClass('confirm_btn')
|
||||
buttons[scope.cancelIndex] && buttons[scope.cancelIndex].addClass('cancel_btn')
|
||||
jq_dialog.append($('<div class="dialog_bar button_bar"></div>').append(buttons))
|
||||
|
||||
|
||||
let bar = $('<div class="dialog_bar button_bar"></div>');
|
||||
jq_dialog.append(bar);
|
||||
buttons.forEach((button, i) => {
|
||||
if (i) bar.append(' ')
|
||||
bar.append(button)
|
||||
})
|
||||
|
||||
} else if (this.singleButton) {
|
||||
|
||||
jq_dialog.append('<div class="dialog_bar" hidden>' +
|
||||
jq_dialog.append('<div class="dialog_bar button_bar" hidden>' +
|
||||
'<button type="button" class="cancel_btn confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>'+tl('dialog.close')+'</button>' +
|
||||
'</div>')
|
||||
|
||||
} else {
|
||||
|
||||
jq_dialog.append(`<div class="dialog_bar">
|
||||
jq_dialog.append(`<div class="dialog_bar button_bar">
|
||||
<button type="button" class="confirm_btn${this.confirmEnabled ? '' : ' disabled'}">${tl('dialog.confirm')}</button>
|
||||
<button type="button" class="cancel_btn${this.cancelEnabled ? '' : ' disabled'}">${tl('dialog.cancel')}</button>
|
||||
</div>`)
|
||||
|
@ -2,109 +2,7 @@ const StartScreen = {};
|
||||
var ColorPanel;
|
||||
|
||||
//Panels
|
||||
class Panel {
|
||||
constructor(data) {
|
||||
var scope = this;
|
||||
this.type = 'panel'
|
||||
this.id = data.id || 'new_panel'
|
||||
this.menu = data.menu
|
||||
this.title = data.title || tl('panel.'+this.id)
|
||||
this.condition = data.condition
|
||||
this.onResize = data.onResize
|
||||
this.node = $('.panel#'+this.id).get(0)// || $('<div class="panel" id="'+this.id+'"></div>')[0]
|
||||
if (data.toolbars) {
|
||||
this.toolbars = data.toolbars
|
||||
}
|
||||
this.handle = $('<h3 class="panel_handle">'+this.title+'</h3>').get(0)
|
||||
if (!Blockbench.isMobile) {
|
||||
$(this.handle).draggable({
|
||||
revertDuration: 0,
|
||||
cursorAt: { left: 24, top: 24 },
|
||||
helper: 'clone',
|
||||
revert: true,
|
||||
appendTo: 'body',
|
||||
zIndex: 19,
|
||||
scope: 'panel',
|
||||
start: function() {
|
||||
Interface.panel = scope;
|
||||
},
|
||||
stop: function(e, ui) {
|
||||
if (!ui) return;
|
||||
if (Math.abs(ui.position.top - ui.originalPosition.top) + Math.abs(ui.position.left - ui.originalPosition.left) < 180) return;
|
||||
var target = Interface.panel
|
||||
if (typeof target === 'string') {
|
||||
scope.moveTo(target)
|
||||
} else if (target.type === 'panel') {
|
||||
var target_pos = $(target.node).offset().top
|
||||
var target_height = $(target.node).height()
|
||||
var before = ui.position.top < target_pos + target_height / 2
|
||||
if (target && target !== scope) {
|
||||
scope.moveTo(target, before)
|
||||
} else {
|
||||
if (e.clientX > window.innerWidth - 200) {
|
||||
scope.moveTo('right_bar')
|
||||
} else if (e.clientX < 200) {
|
||||
scope.moveTo('left_bar')
|
||||
}
|
||||
}
|
||||
}
|
||||
saveInterfaceRearrangement()
|
||||
updateInterface()
|
||||
}
|
||||
})
|
||||
}
|
||||
$(this.node)
|
||||
.droppable({
|
||||
accept: 'h3',
|
||||
scope: 'panel',
|
||||
tolerance: 'pointer',
|
||||
drop: function(e, ui) {
|
||||
Interface.panel = scope;
|
||||
}
|
||||
})
|
||||
.click((event) => {
|
||||
setActivePanel(this.id)
|
||||
})
|
||||
.contextmenu((event) => {
|
||||
setActivePanel(this.id)
|
||||
})
|
||||
.prepend(this.handle)
|
||||
}
|
||||
moveTo(ref_panel, before) {
|
||||
var scope = this
|
||||
if (typeof ref_panel === 'string') {
|
||||
if (ref_panel === 'left_bar') {
|
||||
$('#left_bar').append(scope.node)
|
||||
} else {
|
||||
$('#right_bar').append(scope.node)
|
||||
}
|
||||
} else {
|
||||
if (before) {
|
||||
$(ref_panel.node).before(scope.node)
|
||||
} else {
|
||||
$(ref_panel.node).after(scope.node)
|
||||
}
|
||||
}
|
||||
if (this.onResize) {
|
||||
this.onResize()
|
||||
}
|
||||
updateInterface()
|
||||
}
|
||||
update() {
|
||||
var show = BARS.condition(this.condition)
|
||||
if (show) {
|
||||
$(this.node).show()
|
||||
if (Interface.data.left_bar.includes(this.id)) {
|
||||
this.width = Interface.data.left_bar_width
|
||||
} else if (Interface.data.right_bar.includes(this.id)) {
|
||||
this.width = Interface.data.right_bar_width
|
||||
}
|
||||
if (this.onResize) this.onResize()
|
||||
} else {
|
||||
$(this.node).hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResizeLine {
|
||||
constructor(data) {
|
||||
var scope = this;
|
||||
@ -168,7 +66,7 @@ class ResizeLine {
|
||||
}
|
||||
}
|
||||
|
||||
var Interface = {
|
||||
const Interface = {
|
||||
default_data: {
|
||||
left_bar_width: 332,
|
||||
right_bar_width: 314,
|
||||
@ -182,11 +80,11 @@ var Interface = {
|
||||
left: new ResizeLine({
|
||||
id: 'left',
|
||||
condition: function() {
|
||||
var i = 0;
|
||||
Interface.data.left_bar.forEach(p => {
|
||||
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {i++;}
|
||||
})
|
||||
return i;
|
||||
for (let p of Interface.data.left_bar) {
|
||||
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
get: function() {return Interface.data.left_bar_width},
|
||||
set: function(o, diff) {
|
||||
@ -204,11 +102,11 @@ var Interface = {
|
||||
right: new ResizeLine({
|
||||
id: 'right',
|
||||
condition: function() {
|
||||
var i = 0;
|
||||
Interface.data.right_bar.forEach(p => {
|
||||
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {i++;}
|
||||
})
|
||||
return i;
|
||||
for (let p of Interface.data.right_bar) {
|
||||
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
get: function() {return Interface.data.right_bar_width},
|
||||
set: function(o, diff) {
|
||||
@ -290,15 +188,6 @@ function setupInterface() {
|
||||
var old_data = Interface.data
|
||||
if (interface_data.left_bar) Interface.data.left_bar = interface_data.left_bar;
|
||||
if (interface_data.right_bar) Interface.data.right_bar = interface_data.right_bar;
|
||||
for (key in Interface.Panels) {
|
||||
if (!Interface.data.left_bar.includes(key) && !Interface.data.right_bar.includes(key)) {
|
||||
if (old_data.left_bar.includes(key)) {
|
||||
Interface.data.left_bar.push(key)
|
||||
} else {
|
||||
Interface.data.right_bar.push(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
$.extend(true, Interface.data, interface_data)
|
||||
} catch (err) {}
|
||||
|
||||
@ -311,135 +200,7 @@ function setupInterface() {
|
||||
|
||||
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
|
||||
|
||||
$('.sidebar').droppable({
|
||||
accept: 'h3',
|
||||
scope: 'panel',
|
||||
tolerance: 'pointer',
|
||||
drop: function(e, ui) {
|
||||
Interface.panel = $(this).attr('id');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//Panels
|
||||
Interface.Panels.uv = new Panel({
|
||||
id: 'uv',
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'paint',
|
||||
toolbars: {
|
||||
bottom: Toolbars.main_uv
|
||||
},
|
||||
onResize: function() {
|
||||
var size = limitNumber($(this.node).width()-10, 64, 1200)
|
||||
size = Math.floor(size/16)*16
|
||||
main_uv.setSize(size)
|
||||
}
|
||||
})
|
||||
Interface.Panels.textures = new Panel({
|
||||
id: 'textures',
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'paint',
|
||||
toolbars: {
|
||||
head: Toolbars.textures
|
||||
},
|
||||
menu: new Menu([
|
||||
'import_texture',
|
||||
'create_texture',
|
||||
'reload_textures',
|
||||
'change_textures_folder',
|
||||
'save_textures'
|
||||
])
|
||||
})
|
||||
Interface.Panels.element = new Panel({
|
||||
id: 'element',
|
||||
condition: () => Modes.edit,
|
||||
toolbars: {
|
||||
element_position: Toolbars.element_position,
|
||||
element_size: Toolbars.element_size,
|
||||
element_origin: Toolbars.element_origin,
|
||||
element_rotation: Toolbars.element_rotation,
|
||||
}
|
||||
})
|
||||
Interface.Panels.bone = new Panel({
|
||||
id: 'bone',
|
||||
condition: () => Modes.animate,
|
||||
toolbars: {
|
||||
//bone_ik: Toolbars.bone_ik,
|
||||
}
|
||||
})
|
||||
Interface.Panels.outliner = new Panel({
|
||||
id: 'outliner',
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'paint' || Modes.id === 'animate',
|
||||
toolbars: {
|
||||
head: Toolbars.outliner
|
||||
},
|
||||
onResize: t => {
|
||||
getAllOutlinerObjects().forEach(o => o.updateElement())
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'_',
|
||||
'sort_outliner',
|
||||
'select_all',
|
||||
'collapse_groups',
|
||||
'element_colors',
|
||||
'outliner_toggle'
|
||||
])
|
||||
})
|
||||
Interface.Panels.chat = new Panel({
|
||||
id: 'chat',
|
||||
condition: function() {return EditSession.active},
|
||||
toolbars: {},
|
||||
onResize: t => {
|
||||
},
|
||||
menu: new Menu([
|
||||
])
|
||||
})
|
||||
Interface.Panels.animations = new Panel({
|
||||
id: 'animations',
|
||||
condition: () => Animator.open,
|
||||
toolbars: {
|
||||
head: Toolbars.animations
|
||||
}
|
||||
})
|
||||
Interface.Panels.keyframe = new Panel({
|
||||
id: 'keyframe',
|
||||
condition: () => Animator.open,
|
||||
toolbars: {
|
||||
head: Toolbars.keyframe
|
||||
}
|
||||
})
|
||||
Interface.Panels.variable_placeholders = new Panel({
|
||||
id: 'variable_placeholders',
|
||||
condition: () => Animator.open,
|
||||
toolbars: {
|
||||
}
|
||||
})
|
||||
Interface.Panels.display = new Panel({
|
||||
id: 'display',
|
||||
condition: function() {return display_mode},
|
||||
toolbars: {
|
||||
head: Toolbars.textures
|
||||
}
|
||||
})
|
||||
Interface.data.left_bar.forEach((id) => {
|
||||
if (Interface.Panels[id]) {
|
||||
$('#left_bar').append(Interface.Panels[id].node)
|
||||
}
|
||||
})
|
||||
Interface.data.right_bar.forEach((id) => {
|
||||
if (Interface.Panels[id]) {
|
||||
$('#right_bar').append(Interface.Panels[id].node)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Interface.status_bar.menu = new Menu([
|
||||
'project_window',
|
||||
'open_model_folder',
|
||||
'open_backup_folder',
|
||||
'save',
|
||||
'timelapse',
|
||||
])
|
||||
setupPanels()
|
||||
|
||||
for (var key in Interface.Resizers) {
|
||||
var resizer = Interface.Resizers[key]
|
||||
@ -531,19 +292,6 @@ function setupInterface() {
|
||||
})
|
||||
updateInterface()
|
||||
}
|
||||
function saveInterfaceRearrangement() {
|
||||
Interface.data.left_bar.length = 0
|
||||
$('#left_bar > .panel').each((i, obj) => {
|
||||
let id = $(obj).attr('id');
|
||||
Interface.data.left_bar.push(id);
|
||||
})
|
||||
Interface.data.right_bar.length = 0
|
||||
$('#right_bar > .panel').each((i, obj) => {
|
||||
let id = $(obj).attr('id');
|
||||
Interface.data.right_bar.push(id);
|
||||
})
|
||||
localStorage.setItem('interface_data', JSON.stringify(Interface.data))
|
||||
}
|
||||
|
||||
function updateInterface() {
|
||||
BARS.updateConditions()
|
||||
@ -581,7 +329,7 @@ function updateInterfacePanels() {
|
||||
}
|
||||
|
||||
function resizeWindow(event) {
|
||||
if (!previews || (event && event.target && event.target !== window)) {
|
||||
if (!Preview.all || (event && event.target && event.target !== window)) {
|
||||
return;
|
||||
}
|
||||
if (Animator.open) {
|
||||
@ -591,7 +339,7 @@ function resizeWindow(event) {
|
||||
if (Interface.data) {
|
||||
updateInterfacePanels()
|
||||
}
|
||||
previews.forEach(function(prev) {
|
||||
Preview.all.forEach(function(prev) {
|
||||
if (prev.canvas.isConnected) {
|
||||
prev.resize()
|
||||
}
|
||||
@ -609,9 +357,6 @@ function resizeWindow(event) {
|
||||
}
|
||||
$(window).on('resize orientationchange', resizeWindow)
|
||||
|
||||
function setActivePanel(panel) {
|
||||
Prop.active_panel = panel
|
||||
}
|
||||
function setProjectTitle(title) {
|
||||
if (Format.bone_rig && Project.geometry_name) {
|
||||
title = Project.geometry_name
|
||||
@ -705,6 +450,30 @@ function setSettingsTab(tab) {
|
||||
//Layout
|
||||
|
||||
$('#theme_editor').css('max-height', ($(window).height() - 420) +'px')
|
||||
} else if (tab == 'credits') {
|
||||
// About
|
||||
|
||||
$('#version_tag').text(appVersion)
|
||||
if (isApp) {
|
||||
jQuery.ajax({
|
||||
url: 'https://api.github.com/repos/JannisX11/blockbench/releases/latest',
|
||||
cache: false,
|
||||
type: 'GET',
|
||||
success(release) {
|
||||
let v = release.tag_name.replace(/^v/, '');
|
||||
if (compareVersions(v, appVersion)) {
|
||||
$('#version_tag').text(`${appVersion} (${tl('about.version.update_available', [v])})`)
|
||||
} else if (compareVersions(appVersion, v)) {
|
||||
$('#version_tag').text(`${appVersion} (Pre-release)`)
|
||||
} else {
|
||||
$('#version_tag').text(`${appVersion} (${tl('about.version.up_to_date')}😄)`)
|
||||
}
|
||||
},
|
||||
error(err) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,8 +500,12 @@ $(document).keyup(function(event) {
|
||||
})
|
||||
|
||||
//Start Screen
|
||||
function addStartScreenSection(data) {
|
||||
var obj = $('<section></section>')
|
||||
function addStartScreenSection(id, data) {
|
||||
if (typeof id == 'object') {
|
||||
data = id;
|
||||
id = '';
|
||||
}
|
||||
var obj = $(`<section id="${id}"></section>`)
|
||||
if (typeof data.graphic === 'object') {
|
||||
var left = $('<left class="graphic"></left>')
|
||||
obj.append(left)
|
||||
@ -802,16 +575,10 @@ function addStartScreenSection(data) {
|
||||
}
|
||||
}
|
||||
|
||||
var documentReady = new Promise((resolve, reject) => {
|
||||
$(document).ready(function() {
|
||||
resolve()
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
(function() {
|
||||
var news_call = $.getJSON('https://blockbench.net/api/news/news.json')
|
||||
var version_call = $.getJSON('https://raw.githubusercontent.com/JannisX11/blockbench/master/package.json')
|
||||
Promise.all([news_call, documentReady]).then((data) => {
|
||||
if (!data || !data[0]) return;
|
||||
data = data[0];
|
||||
@ -845,6 +612,9 @@ var documentReady = new Promise((resolve, reject) => {
|
||||
]
|
||||
})
|
||||
}
|
||||
if (settings.streamer_mode.value) {
|
||||
updateStreamerModeNotification()
|
||||
}
|
||||
|
||||
|
||||
//Electron
|
||||
@ -884,49 +654,21 @@ var documentReady = new Promise((resolve, reject) => {
|
||||
last: true
|
||||
})
|
||||
}
|
||||
//Donation reminder
|
||||
if (Blockbench.startup_count % 20 === 19) {
|
||||
addStartScreenSection({
|
||||
graphic: {type: 'icon', icon: 'fas.fa-heart'},
|
||||
text: [
|
||||
{type: 'h1', text: 'Donation'},
|
||||
{text: 'Are you enjoying Blockbench? Consider donating to the project. Blockbench is 100% donation funded.'},
|
||||
{text: '[Donate](https://blockbench.net/donate)'}
|
||||
],
|
||||
last: true
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Promise.all([version_call, documentReady]).then((data) => {
|
||||
if (data[0] && data[0].version) {
|
||||
latest_version = data[0].version;
|
||||
if (isApp && compareVersions(latest_version, appVersion)) {
|
||||
|
||||
addStartScreenSection({
|
||||
color: 'var(--color-back)',
|
||||
graphic: {type: 'icon', icon: 'update'},
|
||||
text: [
|
||||
{type: 'h1', text: tl('message.update_notification.title')},
|
||||
{text: tl('message.update_notification.message', [latest_version])},
|
||||
{type: 'button', text: tl('message.update_notification.install'), click: (e) => {
|
||||
checkForUpdates(true)
|
||||
}}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
})()
|
||||
|
||||
onVueSetup(function() {
|
||||
|
||||
StateMemory.init('start_screen_list_type', 'string')
|
||||
StartScreen.vue = new Vue({
|
||||
el: '#start_screen',
|
||||
data: {
|
||||
formats: Formats,
|
||||
recent: isApp ? recent_projects : []
|
||||
recent: isApp ? recent_projects : [],
|
||||
list_type: StateMemory.start_screen_list_type || 'list',
|
||||
redact_names: settings.streamer_mode.value,
|
||||
isApp
|
||||
},
|
||||
methods: {
|
||||
getDate(p) {
|
||||
@ -950,6 +692,18 @@ onVueSetup(function() {
|
||||
loadModelFile(files[0]);
|
||||
})
|
||||
//readFile(p.path, !event.shiftKey)
|
||||
},
|
||||
getThumbnail(model_path) {
|
||||
let hash = model_path.hashCode().toString().replace(/^-/, '0');
|
||||
let path = PathModule.join(app.getPath('userData'), 'thumbnails', `${hash}.png`);
|
||||
if (!fs.existsSync(path)) return 'none'
|
||||
path = `url('${path.replace(/\\/g, '/')}?${Math.round(Math.random()*255)}')`;
|
||||
return path;
|
||||
},
|
||||
setListType(type) {
|
||||
this.list_type = type;
|
||||
StateMemory.start_screen_list_type = type;
|
||||
StateMemory.save('start_screen_list_type')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -181,7 +181,7 @@ class Menu {
|
||||
} else {
|
||||
var icon = Blockbench.getIconNode(s.icon, s.color)
|
||||
}
|
||||
entry = $(`<li title="${s.description||''}">${tl(s.name)}</li>`)
|
||||
entry = $(`<li title="${s.description||''}" menu_item="${s.id}">${tl(s.name)}</li>`)
|
||||
entry.prepend(icon)
|
||||
if (typeof s.click === 'function') {
|
||||
entry.click(e => {
|
||||
@ -418,11 +418,12 @@ const MenuBar = {
|
||||
condition: function() {return isApp && recent_projects.length && (!EditSession.active || EditSession.hosting)},
|
||||
children: function() {
|
||||
var arr = []
|
||||
let redact = settings.streamer_mode.value;
|
||||
recent_projects.forEach(function(p) {
|
||||
arr.push({
|
||||
name: p.name,
|
||||
name: redact ? `[${tl('generic.redacted')}]` : p.name,
|
||||
path: p.path,
|
||||
description: p.path,
|
||||
description: redact ? '' : p.path,
|
||||
icon: p.icon,
|
||||
click: function(c, event) {
|
||||
Blockbench.read([p.path], {}, files => {
|
||||
@ -434,8 +435,8 @@ const MenuBar = {
|
||||
return arr
|
||||
}
|
||||
},
|
||||
|
||||
'open_model',
|
||||
'_',
|
||||
'save_project',
|
||||
'save_project_as',
|
||||
'convert_project',
|
||||
@ -581,6 +582,7 @@ const MenuBar = {
|
||||
'preview_checkerboard',
|
||||
'painting_grid',
|
||||
'toggle_quad_view',
|
||||
'focus_on_selection',
|
||||
{name: 'menu.view.screenshot', id: 'screenshot', icon: 'camera_alt', children: [
|
||||
'screenshot_model',
|
||||
'screenshot_app',
|
||||
@ -589,6 +591,8 @@ const MenuBar = {
|
||||
]},
|
||||
])
|
||||
new BarMenu('help', [
|
||||
{name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select},
|
||||
'_',
|
||||
{name: 'menu.help.discord', id: 'discord', icon: 'fab.fa-discord', click: () => {
|
||||
Blockbench.openLink('http://discord.blockbench.net');
|
||||
}},
|
||||
@ -599,9 +603,8 @@ const MenuBar = {
|
||||
Blockbench.openLink('https://github.com/JannisX11/blockbench/issues');
|
||||
}},
|
||||
'_',
|
||||
{name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select},
|
||||
'open_backup_folder',
|
||||
'_',
|
||||
'update_window',
|
||||
{name: 'menu.help.developer', id: 'developer', icon: 'fas.fa-wrench', children: [
|
||||
'reload_plugins',
|
||||
{name: 'menu.help.plugin_documentation', id: 'plugin_documentation', icon: 'fa-book', click: () => {
|
||||
@ -627,8 +630,7 @@ const MenuBar = {
|
||||
Blockbench.openLink('https://blockbench.net/donate/');
|
||||
}},
|
||||
{name: 'menu.help.about', id: 'about', icon: 'info', click: () => {
|
||||
Settings.open();
|
||||
setSettingsTab('credits');
|
||||
Settings.open({tab: 'credits'});
|
||||
}}
|
||||
])
|
||||
MenuBar.update()
|
||||
|
404
js/interface/panels.js
Normal file
404
js/interface/panels.js
Normal file
@ -0,0 +1,404 @@
|
||||
class Panel {
|
||||
constructor(data) {
|
||||
let scope = this;
|
||||
this.type = 'panel';
|
||||
this.id = data.id || 'new_panel';
|
||||
this.icon = data.icon;
|
||||
this.menu = data.menu;
|
||||
this.name = tl(data.name ? data.name : `panel.${this.id}`);
|
||||
this.selection_only = data.selection_only == true;
|
||||
this.condition = data.condition;
|
||||
this.onResize = data.onResize;
|
||||
if (data.toolbars) {
|
||||
this.toolbars = data.toolbars;
|
||||
} else {
|
||||
this.toolbars = {};
|
||||
}
|
||||
// Vue
|
||||
if (data.component) {
|
||||
data.component.name = 'inside-vue'
|
||||
$(`.sidebar#${data.default_side||'left'}_bar`).append(`<div id="mount-panel-${this.id}"></div>`)
|
||||
|
||||
this.vue = new Vue({
|
||||
components: {
|
||||
'inside-vue': data.component
|
||||
},
|
||||
template: `<div class="panel ${this.selection_only ? 'selection_only' : ''} ${this.growable ? 'grow' : ''}" id="${this.id}">
|
||||
<h3 class="panel_handle">${this.name}</h3>
|
||||
<inside-vue class="panel_inside" ref="inside"></inside-vue>
|
||||
</div>`,
|
||||
mounted() {
|
||||
Vue.nextTick(() => {
|
||||
updateInterfacePanels()
|
||||
})
|
||||
}
|
||||
}).$mount(`#mount-panel-${this.id}`)
|
||||
|
||||
this.inside_vue = this.vue.$refs.inside;
|
||||
|
||||
this.node = $('.panel#'+this.id).get(0)
|
||||
this.handle = $(this.node).find('h3.panel_handle').get(0)
|
||||
|
||||
} else {
|
||||
this.node = $('.panel#'+this.id).get(0)
|
||||
this.handle = $('<h3 class="panel_handle">'+this.name+'</h3>').get(0)
|
||||
$(this.node).prepend(this.handle)
|
||||
}
|
||||
|
||||
|
||||
if (!Blockbench.isMobile) {
|
||||
$(this.handle).draggable({
|
||||
revertDuration: 0,
|
||||
cursorAt: { left: 24, top: 24 },
|
||||
helper: 'clone',
|
||||
revert: true,
|
||||
appendTo: 'body',
|
||||
zIndex: 19,
|
||||
scope: 'panel',
|
||||
start: function() {
|
||||
Interface.panel = scope;
|
||||
},
|
||||
stop: function(e, ui) {
|
||||
if (!ui) return;
|
||||
if (Math.abs(ui.position.top - ui.originalPosition.top) + Math.abs(ui.position.left - ui.originalPosition.left) < 180) return;
|
||||
let target = Interface.panel
|
||||
if (typeof target === 'string') {
|
||||
scope.moveTo(target)
|
||||
} else if (target.type === 'panel') {
|
||||
let target_pos = $(target.node).offset().top
|
||||
let target_height = $(target.node).height()
|
||||
let before = ui.position.top < target_pos + target_height / 2
|
||||
if (target && target !== scope) {
|
||||
scope.moveTo(target, before)
|
||||
} else {
|
||||
if (e.clientX > window.innerWidth - 200) {
|
||||
scope.moveTo('right_bar')
|
||||
} else if (e.clientX < 200) {
|
||||
scope.moveTo('left_bar')
|
||||
}
|
||||
}
|
||||
}
|
||||
saveInterfaceRearrangement()
|
||||
updateInterface()
|
||||
}
|
||||
})
|
||||
}
|
||||
$(this.node)
|
||||
.droppable({
|
||||
accept: 'h3',
|
||||
scope: 'panel',
|
||||
tolerance: 'pointer',
|
||||
drop: function(e, ui) {
|
||||
Interface.panel = scope;
|
||||
}
|
||||
})
|
||||
.click((event) => {
|
||||
setActivePanel(this.id)
|
||||
})
|
||||
.contextmenu((event) => {
|
||||
setActivePanel(this.id)
|
||||
})
|
||||
|
||||
// Sort
|
||||
if (Blockbench.setup_successful) {
|
||||
if (Interface.data.right_bar.includes(this.id)) {
|
||||
let index = Interface.data.right_bar.indexOf(this.id);
|
||||
if (index == 0) {
|
||||
this.moveTo(Interface.Panels[Interface.data.right_bar[1]], true)
|
||||
} else {
|
||||
this.moveTo(Interface.Panels[Interface.data.right_bar[index-1]], false)
|
||||
}
|
||||
} else if (Interface.data.left_bar.includes(this.id)) {
|
||||
let index = Interface.data.left_bar.indexOf(this.id);
|
||||
if (index == 0) {
|
||||
this.moveTo(Interface.Panels[Interface.data.left_bar[1]], true)
|
||||
} else {
|
||||
this.moveTo(Interface.Panels[Interface.data.left_bar[index-1]], false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Toolbars
|
||||
for (let key in this.toolbars) {
|
||||
let toolbar = this.toolbars[key]
|
||||
if (toolbar instanceof Toolbar) {
|
||||
toolbar.toPlace(toolbar.id)
|
||||
}
|
||||
}
|
||||
|
||||
Interface.Panels[this.id] = this;
|
||||
}
|
||||
moveTo(ref_panel, before) {
|
||||
let scope = this
|
||||
if (typeof ref_panel === 'string') {
|
||||
if (ref_panel === 'left_bar') {
|
||||
$('#left_bar').append(scope.node)
|
||||
} else {
|
||||
$('#right_bar').append(scope.node)
|
||||
}
|
||||
} else {
|
||||
if (before) {
|
||||
$(ref_panel.node).before(scope.node)
|
||||
} else {
|
||||
$(ref_panel.node).after(scope.node)
|
||||
}
|
||||
}
|
||||
if (this.onResize) {
|
||||
this.onResize()
|
||||
}
|
||||
updateInterface()
|
||||
}
|
||||
update() {
|
||||
let show = BARS.condition(this.condition)
|
||||
if (show) {
|
||||
$(this.node).show()
|
||||
if (Interface.data.left_bar.includes(this.id)) {
|
||||
this.width = Interface.data.left_bar_width
|
||||
} else if (Interface.data.right_bar.includes(this.id)) {
|
||||
this.width = Interface.data.right_bar_width
|
||||
}
|
||||
if (this.onResize) this.onResize()
|
||||
} else {
|
||||
$(this.node).hide()
|
||||
}
|
||||
}
|
||||
delete() {
|
||||
delete Interface.Panels[this.id];
|
||||
$(this.node).detach()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setupPanels() {
|
||||
|
||||
$('.sidebar').droppable({
|
||||
accept: 'h3',
|
||||
scope: 'panel',
|
||||
tolerance: 'pointer',
|
||||
drop: function(e, ui) {
|
||||
Interface.panel = $(this).attr('id');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//Panels
|
||||
Interface.Panels.uv = new Panel({
|
||||
id: 'uv',
|
||||
icon: 'photo_size_select_large',
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
bottom: Toolbars.main_uv
|
||||
},
|
||||
onResize: function() {
|
||||
let size = limitNumber($(this.node).width()-10, 64, 1200)
|
||||
size = Math.floor(size/16)*16
|
||||
main_uv.setSize(size)
|
||||
}
|
||||
})
|
||||
Interface.Panels.textures = new Panel({
|
||||
id: 'textures',
|
||||
icon: 'fas.fa-images',
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
head: Toolbars.texturelist
|
||||
},
|
||||
menu: new Menu([
|
||||
'import_texture',
|
||||
'create_texture',
|
||||
'reload_textures',
|
||||
'change_textures_folder',
|
||||
'save_textures'
|
||||
])
|
||||
})
|
||||
Interface.Panels.element = new Panel({
|
||||
id: 'element',
|
||||
icon: 'fas.fa-cube',
|
||||
condition: {modes: ['edit']},
|
||||
selection_only: true,
|
||||
toolbars: {
|
||||
element_position: !Blockbench.isMobile && Toolbars.element_position,
|
||||
element_size: !Blockbench.isMobile && Toolbars.element_size,
|
||||
element_origin: !Blockbench.isMobile && Toolbars.element_origin,
|
||||
element_rotation: !Blockbench.isMobile && Toolbars.element_rotation,
|
||||
}
|
||||
})
|
||||
Interface.Panels.bone = new Panel({
|
||||
id: 'bone',
|
||||
icon: 'fas.fa-bone',
|
||||
condition: {modes: ['animate']},
|
||||
selection_only: true,
|
||||
toolbars: {
|
||||
//bone_ik: Toolbars.bone_ik,
|
||||
},
|
||||
component: {
|
||||
template: `
|
||||
<div>
|
||||
<p>${ tl('panel.element.origin') }</p>
|
||||
<div class="toolbar_wrapper bone_origin"></div>
|
||||
<!--p>${ tl('panel.bone.ik') }</p>
|
||||
<div class="toolbar_wrapper bone_ik"></div-->
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
Interface.Panels.outliner = new Panel({
|
||||
id: 'outliner',
|
||||
icon: 'list_alt',
|
||||
condition: {modes: ['edit', 'paint', 'animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.outliner
|
||||
},
|
||||
onResize: t => {
|
||||
getAllOutlinerObjects().forEach(o => o.updateElement())
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'_',
|
||||
'sort_outliner',
|
||||
'select_all',
|
||||
'collapse_groups',
|
||||
'element_colors',
|
||||
'outliner_toggle'
|
||||
])
|
||||
})
|
||||
Interface.Panels.chat = new Panel({
|
||||
id: 'chat',
|
||||
icon: 'chat',
|
||||
condition: {method() {return EditSession.active}},
|
||||
toolbars: {},
|
||||
onResize: t => {
|
||||
},
|
||||
menu: new Menu([
|
||||
'toggle_chat'
|
||||
]),
|
||||
component: {
|
||||
data() {return Chat},
|
||||
template: `
|
||||
<div>
|
||||
<div class="bar next_to_title" id="chat_title_bar"></div>
|
||||
<ul id="chat_history" v-if="expanded">
|
||||
<li v-for="msg in history">
|
||||
<b v-if="msg.showAuthor()" v-bind:class="{self: msg.self}">{{ msg.author }}:</b>
|
||||
<span class="text" v-bind:style="{color: msg.hex || 'inherit'}" v-html="msg.html"></span>
|
||||
<span class="timestamp">{{ msg.timestamp }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="chat_bar">
|
||||
<input type="text" id="chat_input" class="dark_bordered f_left" maxlength="512">
|
||||
<i class="material-icons" onclick="Chat.send()">send</i>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
BarItems.toggle_chat.toElement('#chat_title_bar')
|
||||
|
||||
Interface.Panels.animations = new Panel({
|
||||
id: 'animations',
|
||||
icon: 'movie',
|
||||
condition: {modes: ['animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.animations
|
||||
},
|
||||
component: {
|
||||
name: 'panel-animations',
|
||||
data() { return {
|
||||
animations: Animator.animations
|
||||
}},
|
||||
methods: {
|
||||
sort(event) {
|
||||
let item = Animator.animations.splice(event.oldIndex, 1)[0];
|
||||
Animator.animations.splice(event.newIndex, 0, item);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper animations"></div>
|
||||
<ul id="animations_list" class="list" v-sortable="{onUpdate: sort, fallbackTolerance: 10, animation: 0, handle: ':not(.animation_play_toggle)'}">
|
||||
<li
|
||||
v-for="animation in animations"
|
||||
v-bind:class="{ selected: animation.selected }"
|
||||
v-bind:anim_id="animation.uuid"
|
||||
class="animation"
|
||||
v-on:click.stop="animation.select()"
|
||||
v-on:dblclick.stop="animation.rename()"
|
||||
:key="animation.uuid"
|
||||
@contextmenu.prevent.stop="animation.showContextMenu($event)"
|
||||
>
|
||||
<i class="material-icons">movie</i>
|
||||
<input class="animation_name" v-model="animation.name" disabled="true">
|
||||
<div class="animation_play_toggle" v-on:click.stop="animation.togglePlayingState()">
|
||||
<i v-if="animation.playing" class="fa_big far fa-play-circle"></i>
|
||||
<i v-else class="fa_big far fa-circle"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
Interface.Panels.keyframe = new Panel({
|
||||
id: 'keyframe',
|
||||
icon: 'timeline',
|
||||
condition: {modes: ['animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.keyframe
|
||||
}
|
||||
})
|
||||
Interface.Panels.variable_placeholders = new Panel({
|
||||
id: 'variable_placeholders',
|
||||
icon: 'fas.fa-stream',
|
||||
condition: {modes: ['animate']},
|
||||
toolbars: {
|
||||
}
|
||||
})
|
||||
Interface.Panels.display = new Panel({
|
||||
id: 'display',
|
||||
icon: 'tune',
|
||||
condition: {modes: ['display']},
|
||||
toolbars: {
|
||||
head: Toolbars.display
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Interface.data.left_bar.forEach((id) => {
|
||||
if (Interface.Panels[id]) {
|
||||
$('#left_bar').append(Interface.Panels[id].node)
|
||||
}
|
||||
})
|
||||
Interface.data.right_bar.forEach((id) => {
|
||||
if (Interface.Panels[id]) {
|
||||
$('#right_bar').append(Interface.Panels[id].node)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Interface.status_bar.menu = new Menu([
|
||||
'project_window',
|
||||
'open_model_folder',
|
||||
'open_backup_folder',
|
||||
'save',
|
||||
'timelapse',
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
function setActivePanel(panel) {
|
||||
Prop.active_panel = panel
|
||||
}
|
||||
|
||||
function saveInterfaceRearrangement() {
|
||||
Interface.data.left_bar.empty();
|
||||
$('#left_bar > .panel').each((i, obj) => {
|
||||
let id = $(obj).attr('id');
|
||||
Interface.data.left_bar.push(id);
|
||||
})
|
||||
Interface.data.right_bar.empty();
|
||||
$('#right_bar > .panel').each((i, obj) => {
|
||||
let id = $(obj).attr('id');
|
||||
Interface.data.right_bar.push(id);
|
||||
})
|
||||
localStorage.setItem('interface_data', JSON.stringify(Interface.data))
|
||||
}
|
@ -79,9 +79,10 @@ const Settings = {
|
||||
//General
|
||||
new Setting('language', {value: 'en', type: 'select', options: Language.options});
|
||||
new Setting('username', {value: '', type: 'text'});
|
||||
new Setting('recent_projects', {value: 12, max: 128, min: 0, type: 'number', condition: isApp});
|
||||
new Setting('backup_interval', {value: 10, type: 'number', condition: isApp});
|
||||
new Setting('backup_retain', {value: 30, type: 'number', condition: isApp});
|
||||
new Setting('streamer_mode', {value: false, onChange() {
|
||||
StartScreen.vue._data.redact_names = settings.streamer_mode.value;
|
||||
updateStreamerModeNotification();
|
||||
}});
|
||||
|
||||
//Interface
|
||||
new Setting('origin_size', {category: 'interface', value: 10, type: 'number'});
|
||||
@ -98,7 +99,7 @@ const Settings = {
|
||||
//Preview
|
||||
new Setting('brightness', {category: 'preview', value: 50, type: 'number'});
|
||||
new Setting('shading', {category: 'preview', value: true, onChange() {
|
||||
setShading()
|
||||
updateShading()
|
||||
}});
|
||||
new Setting('render_sides', {category: 'preview', value: 'auto', type: 'select', options: {
|
||||
'auto': tl('settings.render_sides.auto'),
|
||||
@ -139,9 +140,7 @@ const Settings = {
|
||||
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)
|
||||
})
|
||||
Canvas.updatePaintingGrid();
|
||||
}});
|
||||
|
||||
//Snapping
|
||||
@ -175,11 +174,18 @@ const Settings = {
|
||||
new Setting('dialog_larger_cubes', {category: 'dialogs', value: true});
|
||||
new Setting('dialog_rotation_limit', {category: 'dialogs', value: true});
|
||||
|
||||
//Application
|
||||
new Setting('recent_projects', {category: 'application', value: 12, max: 128, min: 0, type: 'number', condition: isApp});
|
||||
new Setting('backup_interval', {category: 'application', value: 10, type: 'number', condition: isApp});
|
||||
new Setting('backup_retain', {category: 'application', value: 30, type: 'number', condition: isApp});
|
||||
new Setting('automatic_updates', {category: 'application', value: true, condition: isApp});
|
||||
|
||||
//Export
|
||||
new Setting('minifiedout', {category: 'export', value: false});
|
||||
new Setting('export_groups', {category: 'export', value: true});
|
||||
new Setting('sketchfab_token', {category: 'export', value: '', type: 'password'});
|
||||
new Setting('credit', {category: 'export', value: 'Made with Blockbench', type: 'text'});
|
||||
|
||||
},
|
||||
addCategory(id, data) {
|
||||
if (!data) data = 0;
|
||||
@ -189,14 +195,24 @@ const Settings = {
|
||||
items: {}
|
||||
}
|
||||
},
|
||||
open() {
|
||||
open(options = 0) {
|
||||
for (var sett in settings) {
|
||||
if (settings.hasOwnProperty(sett)) {
|
||||
Settings.old[sett] = settings[sett].value
|
||||
}
|
||||
}
|
||||
showDialog('settings')
|
||||
setSettingsTab('setting')
|
||||
|
||||
setSettingsTab(options.tab || 'setting');
|
||||
|
||||
if (options.search) {
|
||||
$('dialog#settings div.search_bar input').val(options.search);
|
||||
if (options.tab == 'keybindings') {
|
||||
Keybinds.updateSearch()
|
||||
} else {
|
||||
Settings.updateSearch()
|
||||
}
|
||||
}
|
||||
},
|
||||
saveLocalStorages() {
|
||||
var settings_copy = {}
|
||||
@ -231,7 +247,7 @@ const Settings = {
|
||||
}
|
||||
Canvas.outlineMaterial.depthTest = !settings.seethrough_outline.value
|
||||
if (hasSettingChanged('brightness')) {
|
||||
setShading()
|
||||
updateShading()
|
||||
}
|
||||
for (var id in settings) {
|
||||
var setting = settings[id];
|
||||
@ -286,9 +302,20 @@ const Settings = {
|
||||
}
|
||||
Settings.setup()
|
||||
|
||||
window.onunload = function() {
|
||||
if (!Blockbench.hasFlag('no_localstorage_saving')) {
|
||||
Settings.saveLocalStorages()
|
||||
function updateStreamerModeNotification() {
|
||||
$('#start_screen section#streamer_mode').detach()
|
||||
|
||||
if (settings.streamer_mode.value) {
|
||||
addStartScreenSection('streamer_mode', {
|
||||
graphic: {type: 'icon', icon: 'live_tv'},
|
||||
color: 'var(--color-stream)',
|
||||
text_color: 'var(--color-light)',
|
||||
text: [
|
||||
{type: 'h1', text: tl('interface.streamer_mode_on'), click() {
|
||||
Settings.open({search: 'streamer_mode'})
|
||||
}}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
(function() {
|
||||
|
||||
let FORMATV = '3.6';
|
||||
|
||||
var codec = new Codec('project', {
|
||||
name: 'Blockbench Project',
|
||||
extension: 'bbmodel',
|
||||
@ -22,27 +24,18 @@ var codec = new Codec('project', {
|
||||
if (!options) options = 0;
|
||||
var model = {
|
||||
meta: {
|
||||
format_version: '3.2',
|
||||
format_version: FORMATV,
|
||||
model_format: Format.id,
|
||||
box_uv: Project.box_uv
|
||||
},
|
||||
name: Project.name,
|
||||
}
|
||||
}
|
||||
if (Format.bone_rig) {
|
||||
model.geo_name = Project.geometry_name
|
||||
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].copy(Project, model)
|
||||
}
|
||||
if (Project.parent) {
|
||||
model.parent = Project.parent;
|
||||
}
|
||||
if (Format.id == 'java_block') {
|
||||
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
|
||||
|
||||
if (Project.overrides) {
|
||||
model.overrides = Project.overrides;
|
||||
}
|
||||
model.resolution = {
|
||||
width: Project.texture_width || 16,
|
||||
@ -128,7 +121,7 @@ var codec = new Codec('project', {
|
||||
if (!model.meta.format_version) {
|
||||
model.meta.format_version = model.meta.format;
|
||||
}
|
||||
if (compareVersions(model.meta.format_version, '3.2')) {
|
||||
if (compareVersions(model.meta.format_version, FORMATV)) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'outdated_client',
|
||||
icon: 'error',
|
||||
@ -143,30 +136,20 @@ var codec = new Codec('project', {
|
||||
} else {
|
||||
Formats.java_block.select()
|
||||
}
|
||||
if (model.meta.box_uv !== undefined && Format.optional_box_uv) {
|
||||
Project.box_uv = model.meta.box_uv
|
||||
}
|
||||
|
||||
Blockbench.dispatchEvent('load_project', {model, path});
|
||||
this.dispatchEvent('parse', {model})
|
||||
|
||||
Project.name = model.name;
|
||||
if (model.geo_name) {
|
||||
Project.geometry_name = model.geo_name;
|
||||
} else if (model.parent) {
|
||||
Project.parent = model.parent;
|
||||
if (model.meta.box_uv !== undefined && Format.optional_box_uv) {
|
||||
Project.box_uv = model.meta.box_uv
|
||||
}
|
||||
if (model.ambientocclusion !== undefined) {
|
||||
Project.ambientocclusion = !!model.ambientocclusion;
|
||||
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].merge(Project, model)
|
||||
}
|
||||
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.overrides) {
|
||||
Project.overrides = model.overrides;
|
||||
}
|
||||
if (model.resolution !== undefined) {
|
||||
Project.texture_width = model.resolution.width;
|
||||
@ -176,10 +159,10 @@ var codec = new Codec('project', {
|
||||
if (model.textures) {
|
||||
model.textures.forEach(tex => {
|
||||
var tex_copy = new Texture(tex, tex.uuid).add(false);
|
||||
if (isApp && tex.path && fs.existsSync(tex.path)) {
|
||||
tex_copy.fromPath(tex.path)
|
||||
} else {
|
||||
if (tex.source && tex.source.substr(0, 5) == 'data:') {
|
||||
tex_copy.fromDataURL(tex.source)
|
||||
} else if (isApp && tex.path && fs.existsSync(tex.path)) {
|
||||
tex_copy.fromPath(tex.path)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -196,8 +179,8 @@ var codec = new Codec('project', {
|
||||
if (texture) {
|
||||
copy.faces[face].texture = texture.uuid
|
||||
}
|
||||
} else if (textures[0] && copy.faces && copy.faces[face].texture !== null) {
|
||||
copy.faces[face].texture = textures[0].uuid
|
||||
} else if (Texture.getDefault() && copy.faces && copy.faces[face].texture !== null) {
|
||||
copy.faces[face].texture = Texture.getDefault().uuid
|
||||
}
|
||||
}
|
||||
copy.init()
|
||||
@ -238,6 +221,7 @@ var codec = new Codec('project', {
|
||||
Undo.history = model.history.slice()
|
||||
Undo.index = model.history_index;
|
||||
}
|
||||
this.dispatchEvent('parsed', {model})
|
||||
Canvas.updateAll()
|
||||
}
|
||||
})
|
@ -84,23 +84,48 @@ window.BedrockEntityManager = {
|
||||
new Texture({keep_size: true}).fromPath(valid_textures_list[0]).add()
|
||||
|
||||
} else if (valid_textures_list.length > 1) {
|
||||
var dialog_list = '';
|
||||
valid_textures_list.forEach((path, i) => {
|
||||
dialog_list += `<li title="${pathToName(path, true)}" arr_index="${i}"></li>`;
|
||||
})
|
||||
var dialog = new Dialog({
|
||||
title: tl('data.texture'),
|
||||
id: 'select_texture',
|
||||
lines: [`<ul id="import_texture_list" class="y_scrollable">${dialog_list}</ul>`],
|
||||
singleButton: true
|
||||
}).show()
|
||||
$('#import_texture_list li').each((i, el) => {
|
||||
$(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }?${Math.round(Math.random()*1e6)}")`)
|
||||
.click(() => {
|
||||
dialog.hide();
|
||||
new Texture({keep_size: true}).fromPath(valid_textures_list[i]).add()
|
||||
});
|
||||
})
|
||||
setTimeout(() => {
|
||||
var dialog_list = '';
|
||||
valid_textures_list.forEach((path, i) => {
|
||||
dialog_list += `<li title="${pathToName(path, true)}" arr_index="${i}"></li>`;
|
||||
})
|
||||
let selected_textures = [];
|
||||
var dialog = new Dialog({
|
||||
title: tl('data.texture'),
|
||||
id: 'select_texture',
|
||||
lines: [`<ul id="import_texture_list" class="y_scrollable">${dialog_list}</ul>`],
|
||||
buttons: ['dialog.import', 'dialog.select_texture.import_all', 'dialog.cancel'],
|
||||
confirmIndex: 0,
|
||||
cancelIndex: 2,
|
||||
onButton(index) {
|
||||
dialog.hide();
|
||||
if (index == 1) {
|
||||
valid_textures_list.forEach(path => {
|
||||
new Texture({keep_size: true}).fromPath(path).add()
|
||||
})
|
||||
} else if (index == 0) {
|
||||
selected_textures.forEach(i => {
|
||||
new Texture({keep_size: true}).fromPath(valid_textures_list[i]).add()
|
||||
})
|
||||
}
|
||||
}
|
||||
}).show()
|
||||
$('#import_texture_list li').each((i, el) => {
|
||||
$(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }?${Math.round(Math.random()*1e6)}")`)
|
||||
.click(function() {
|
||||
if (selected_textures.includes(i)) {
|
||||
selected_textures.remove(i)
|
||||
} else {
|
||||
selected_textures.push(i)
|
||||
}
|
||||
$(this).toggleClass('selected')
|
||||
})
|
||||
.dblclick(function() {
|
||||
selected_textures.replace([i])
|
||||
dialog.confirm()
|
||||
})
|
||||
})
|
||||
}, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,10 +234,12 @@ window.BedrockEntityManager = {
|
||||
|
||||
function calculateVisibleBox() {
|
||||
var visible_box = new THREE.Box3()
|
||||
Cube.all.forEach(cube => {
|
||||
if (cube.export && cube.mesh) {
|
||||
visible_box.expandByObject(cube.mesh);
|
||||
}
|
||||
Canvas.withoutGizmos(() => {
|
||||
Cube.all.forEach(cube => {
|
||||
if (cube.export && cube.mesh) {
|
||||
visible_box.expandByObject(cube.mesh);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
var offset = new THREE.Vector3(8,8,8);
|
||||
@ -249,175 +276,288 @@ function calculateVisibleBox() {
|
||||
|
||||
(function() {
|
||||
|
||||
function parseGeometry(data) {
|
||||
if (data === undefined) {
|
||||
pe_list_data.forEach(function(s) {
|
||||
if (s.selected === true) {
|
||||
data = s
|
||||
}
|
||||
// Parse
|
||||
|
||||
function parseCube(s, group) {
|
||||
var base_cube = new Cube({
|
||||
name: s.name || group.name,
|
||||
autouv: 0,
|
||||
color: Group.all.indexOf(group)%8,
|
||||
rotation: s.rotation,
|
||||
origin: s.pivot
|
||||
})
|
||||
if (data == undefined) {
|
||||
data = pe_list_data[0]
|
||||
}
|
||||
}
|
||||
codec.dispatchEvent('parse', {model: data.object});
|
||||
let {description} = data.object;
|
||||
|
||||
Project.geometry_name = (description.identifier && description.identifier.replace(/^geometry\./, '')) || '';
|
||||
Project.texture_width = 16;
|
||||
Project.texture_height = 16;
|
||||
|
||||
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 (description.texture_width !== undefined) {
|
||||
Project.texture_width = description.texture_width;
|
||||
}
|
||||
if (description.texture_height !== undefined) {
|
||||
Project.texture_height = description.texture_height;
|
||||
}
|
||||
|
||||
var bones = {}
|
||||
|
||||
if (data.object.bones) {
|
||||
var included_bones = []
|
||||
data.object.bones.forEach(function(b) {
|
||||
included_bones.push(b.name)
|
||||
base_cube.rotation.forEach(function(br, axis) {
|
||||
if (axis != 2) base_cube.rotation[axis] *= -1
|
||||
})
|
||||
data.object.bones.forEach(function(b, bi) {
|
||||
var group = new Group({
|
||||
name: b.name,
|
||||
origin: b.pivot,
|
||||
rotation: b.rotation,
|
||||
material: b.material
|
||||
}).init()
|
||||
group.createUniqueName();
|
||||
bones[b.name] = group
|
||||
if (b.pivot) {
|
||||
group.origin[0] *= -1
|
||||
base_cube.origin[0] *= -1;
|
||||
if (s.origin) {
|
||||
base_cube.from.V3_set(s.origin)
|
||||
base_cube.from[0] = -(base_cube.from[0] + s.size[0])
|
||||
if (s.size) {
|
||||
base_cube.to[0] = s.size[0] + base_cube.from[0]
|
||||
base_cube.to[1] = s.size[1] + base_cube.from[1]
|
||||
base_cube.to[2] = s.size[2] + base_cube.from[2]
|
||||
}
|
||||
group.rotation.forEach(function(br, axis) {
|
||||
if (axis !== 2) group.rotation[axis] *= -1
|
||||
})
|
||||
|
||||
group.mirror_uv = b.mirror === true
|
||||
group.reset = b.reset === true
|
||||
|
||||
if (b.cubes) {
|
||||
b.cubes.forEach(function(s) {
|
||||
var base_cube = new Cube({
|
||||
name: s.name || b.name,
|
||||
autouv: 0,
|
||||
color: bi%8,
|
||||
rotation: s.rotation,
|
||||
origin: s.pivot
|
||||
}
|
||||
if (s.uv instanceof Array) {
|
||||
base_cube.uv_offset[0] = s.uv[0]
|
||||
base_cube.uv_offset[1] = s.uv[1]
|
||||
Project.box_uv = true;
|
||||
} else if (s.uv) {
|
||||
Project.box_uv = false;
|
||||
for (var key in base_cube.faces) {
|
||||
var face = base_cube.faces[key]
|
||||
if (s.uv[key]) {
|
||||
face.extend({
|
||||
uv: [
|
||||
s.uv[key].uv[0],
|
||||
s.uv[key].uv[1]
|
||||
]
|
||||
})
|
||||
base_cube.rotation.forEach(function(br, axis) {
|
||||
if (axis != 2) base_cube.rotation[axis] *= -1
|
||||
})
|
||||
base_cube.origin[0] *= -1;
|
||||
if (s.origin) {
|
||||
base_cube.from.V3_set(s.origin)
|
||||
base_cube.from[0] = -(base_cube.from[0] + s.size[0])
|
||||
if (s.size) {
|
||||
base_cube.to[0] = s.size[0] + base_cube.from[0]
|
||||
base_cube.to[1] = s.size[1] + base_cube.from[1]
|
||||
base_cube.to[2] = s.size[2] + base_cube.from[2]
|
||||
}
|
||||
}
|
||||
if (s.uv instanceof Array) {
|
||||
base_cube.uv_offset[0] = s.uv[0]
|
||||
base_cube.uv_offset[1] = s.uv[1]
|
||||
Project.box_uv = true;
|
||||
} else if (s.uv) {
|
||||
Project.box_uv = false;
|
||||
for (var key in base_cube.faces) {
|
||||
var face = base_cube.faces[key]
|
||||
if (s.uv[key]) {
|
||||
face.extend({
|
||||
uv: [
|
||||
s.uv[key].uv[0],
|
||||
s.uv[key].uv[1]
|
||||
]
|
||||
})
|
||||
if (s.uv[key].uv_size) {
|
||||
face.uv_size = [
|
||||
s.uv[key].uv_size[0],
|
||||
s.uv[key].uv_size[1]
|
||||
]
|
||||
} else {
|
||||
base_cube.autouv = 1;
|
||||
base_cube.mapAutoUV();
|
||||
}
|
||||
if (key == 'up') {
|
||||
face.uv = [face.uv[2], face.uv[3], face.uv[0], face.uv[1]]
|
||||
}
|
||||
if (key == 'down') {
|
||||
face.uv = [face.uv[0], face.uv[3], face.uv[2], face.uv[1]]
|
||||
}
|
||||
} else {
|
||||
face.texture = null;
|
||||
face.uv = [0, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (s.inflate && typeof s.inflate === 'number') {
|
||||
base_cube.inflate = s.inflate;
|
||||
}
|
||||
if (s.mirror === undefined) {
|
||||
base_cube.mirror_uv = group.mirror_uv;
|
||||
if (s.uv[key].uv_size) {
|
||||
face.uv_size = [
|
||||
s.uv[key].uv_size[0],
|
||||
s.uv[key].uv_size[1]
|
||||
]
|
||||
} else {
|
||||
base_cube.mirror_uv = s.mirror === true;
|
||||
base_cube.autouv = 1;
|
||||
base_cube.mapAutoUV();
|
||||
}
|
||||
if (key == 'up' || key == 'down') {
|
||||
face.uv = [face.uv[2], face.uv[3], face.uv[0], face.uv[1]]
|
||||
}
|
||||
base_cube.addTo(group).init()
|
||||
})
|
||||
}
|
||||
if (b.locators) {
|
||||
for (var key in b.locators) {
|
||||
var coords = b.locators[key];
|
||||
coords[0] *= -1
|
||||
var locator = new Locator({from: coords, name: key}).addTo(group).init();
|
||||
}
|
||||
}
|
||||
if (b.children) {
|
||||
b.children.forEach(function(cg) {
|
||||
cg.addTo(group);
|
||||
})
|
||||
}
|
||||
var parent_group = 'root';
|
||||
if (b.parent) {
|
||||
if (bones[b.parent]) {
|
||||
parent_group = bones[b.parent]
|
||||
} else {
|
||||
data.object.bones.forEach(function(ib) {
|
||||
if (ib.name === b.parent) {
|
||||
ib.children && ib.children.length ? ib.children.push(group) : ib.children = [group]
|
||||
}
|
||||
})
|
||||
face.texture = null;
|
||||
face.uv = [0, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
group.addTo(parent_group)
|
||||
|
||||
}
|
||||
if (s.inflate && typeof s.inflate === 'number') {
|
||||
base_cube.inflate = s.inflate;
|
||||
}
|
||||
if (s.mirror === undefined) {
|
||||
base_cube.mirror_uv = group.mirror_uv;
|
||||
} else {
|
||||
base_cube.mirror_uv = s.mirror === true;
|
||||
}
|
||||
base_cube.addTo(group).init()
|
||||
}
|
||||
function parseBone(b, bones) {
|
||||
var group = new Group({
|
||||
name: b.name,
|
||||
origin: b.pivot,
|
||||
rotation: b.rotation,
|
||||
material: b.material
|
||||
}).init()
|
||||
group.createUniqueName();
|
||||
bones[b.name] = group
|
||||
if (b.pivot) {
|
||||
group.origin[0] *= -1
|
||||
}
|
||||
group.rotation.forEach(function(br, axis) {
|
||||
if (axis !== 2) group.rotation[axis] *= -1
|
||||
})
|
||||
}
|
||||
pe_list_data.length = 0;
|
||||
hideDialog()
|
||||
|
||||
group.mirror_uv = b.mirror === true
|
||||
group.reset = b.reset === true
|
||||
|
||||
loadTextureDraggable()
|
||||
Canvas.updateAllBones()
|
||||
setProjectTitle()
|
||||
if (isApp && Project.geometry_name) {
|
||||
BedrockEntityManager.initEntity()
|
||||
if (b.cubes) {
|
||||
b.cubes.forEach(function(s) {
|
||||
parseCube(s, group)
|
||||
})
|
||||
}
|
||||
if (b.locators) {
|
||||
for (var key in b.locators) {
|
||||
var coords = b.locators[key];
|
||||
coords[0] *= -1
|
||||
new Locator({from: coords, name: key}).addTo(group).init();
|
||||
}
|
||||
}
|
||||
if (b.children) {
|
||||
b.children.forEach(function(cg) {
|
||||
cg.addTo(group);
|
||||
})
|
||||
}
|
||||
var parent_group = 'root';
|
||||
if (b.parent) {
|
||||
if (bones[b.parent]) {
|
||||
parent_group = bones[b.parent]
|
||||
} else {
|
||||
data.object.bones.forEach(function(ib) {
|
||||
if (ib.name === b.parent) {
|
||||
ib.children && ib.children.length ? ib.children.push(group) : ib.children = [group]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
group.addTo(parent_group)
|
||||
}
|
||||
updateSelection()
|
||||
EditSession.initNewModel()
|
||||
}
|
||||
function parseGeometry(data) {
|
||||
if (data === undefined) {
|
||||
pe_list_data.forEach(function(s) {
|
||||
if (s.selected === true) {
|
||||
data = s
|
||||
}
|
||||
})
|
||||
if (data == undefined) {
|
||||
data = pe_list_data[0]
|
||||
}
|
||||
}
|
||||
codec.dispatchEvent('parse', {model: data.object});
|
||||
let {description} = data.object;
|
||||
|
||||
Project.geometry_name = (description.identifier && description.identifier.replace(/^geometry\./, '')) || '';
|
||||
Project.texture_width = 16;
|
||||
Project.texture_height = 16;
|
||||
|
||||
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 (description.texture_width !== undefined) {
|
||||
Project.texture_width = description.texture_width;
|
||||
}
|
||||
if (description.texture_height !== undefined) {
|
||||
Project.texture_height = description.texture_height;
|
||||
}
|
||||
|
||||
var bones = {}
|
||||
|
||||
if (data.object.bones) {
|
||||
var included_bones = []
|
||||
data.object.bones.forEach(function(b) {
|
||||
included_bones.push(b.name)
|
||||
})
|
||||
data.object.bones.forEach(function(b) {
|
||||
parseBone(b, bones)
|
||||
})
|
||||
}
|
||||
|
||||
codec.dispatchEvent('parsed', {model: data.object});
|
||||
|
||||
pe_list_data.length = 0;
|
||||
hideDialog()
|
||||
|
||||
loadTextureDraggable()
|
||||
Canvas.updateAllBones()
|
||||
setProjectTitle()
|
||||
if (isApp && Project.geometry_name) {
|
||||
BedrockEntityManager.initEntity()
|
||||
}
|
||||
updateSelection()
|
||||
EditSession.initNewModel()
|
||||
}
|
||||
|
||||
// Compile
|
||||
|
||||
function compileCube(obj, bone) {
|
||||
var template = {
|
||||
origin: obj.from.slice(),
|
||||
size: obj.size(),
|
||||
inflate: obj.inflate||undefined,
|
||||
}
|
||||
if (Project.box_uv) {
|
||||
template = new oneLiner(template);
|
||||
}
|
||||
template.origin[0] = -(template.origin[0] + template.size[0])
|
||||
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
template.pivot = obj.origin.slice();
|
||||
template.pivot[0] *= -1;
|
||||
|
||||
template.rotation = obj.rotation.slice();
|
||||
template.rotation.forEach(function(br, axis) {
|
||||
if (axis != 2) template.rotation[axis] *= -1
|
||||
})
|
||||
}
|
||||
|
||||
if (Project.box_uv) {
|
||||
template.uv = obj.uv_offset;
|
||||
if (obj.mirror_uv === !bone.mirror) {
|
||||
template.mirror = obj.mirror_uv
|
||||
}
|
||||
} else {
|
||||
template.uv = {};
|
||||
for (var key in obj.faces) {
|
||||
var face = obj.faces[key];
|
||||
if (face.texture !== null) {
|
||||
template.uv[key] = new oneLiner({
|
||||
uv: [
|
||||
face.uv[0],
|
||||
face.uv[1],
|
||||
],
|
||||
uv_size: [
|
||||
face.uv_size[0],
|
||||
face.uv_size[1],
|
||||
]
|
||||
});
|
||||
if (key == 'up' || key == 'down') {
|
||||
template.uv[key].uv[0] += template.uv[key].uv_size[0];
|
||||
template.uv[key].uv[1] += template.uv[key].uv_size[1];
|
||||
template.uv[key].uv_size[0] *= -1;
|
||||
template.uv[key].uv_size[1] *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return template;
|
||||
}
|
||||
function compileGroup(g) {
|
||||
if (g.type !== 'group') return;
|
||||
//Bone
|
||||
var bone = {}
|
||||
bone.name = g.name
|
||||
if (g.parent.type === 'group') {
|
||||
bone.parent = g.parent.name
|
||||
}
|
||||
bone.pivot = g.origin.slice()
|
||||
bone.pivot[0] *= -1
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.rotation = g.rotation.slice()
|
||||
bone.rotation[0] *= -1;
|
||||
bone.rotation[1] *= -1;
|
||||
}
|
||||
if (g.reset) {
|
||||
bone.reset = true
|
||||
}
|
||||
if (g.mirror_uv) {
|
||||
bone.mirror = true
|
||||
}
|
||||
if (g.material) {
|
||||
bone.material = g.material
|
||||
}
|
||||
//Cubes
|
||||
var cubes = []
|
||||
var locators = {};
|
||||
|
||||
for (var obj of g.children) {
|
||||
if (obj.export) {
|
||||
if (obj instanceof Cube) {
|
||||
|
||||
let template = compileCube(obj, bone);
|
||||
cubes.push(template);
|
||||
|
||||
} else if (obj instanceof Locator) {
|
||||
|
||||
locators[obj.name] = obj.from.slice();
|
||||
locators[obj.name][0] *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cubes.length) {
|
||||
bone.cubes = cubes
|
||||
}
|
||||
if (Object.keys(locators).length) {
|
||||
bone.locators = locators
|
||||
}
|
||||
return bone;
|
||||
}
|
||||
|
||||
|
||||
var codec = new Codec('bedrock', {
|
||||
@ -457,106 +597,7 @@ var codec = new Codec('bedrock', {
|
||||
})
|
||||
}
|
||||
groups.forEach(function(g) {
|
||||
if (g.type !== 'group') return;
|
||||
//Bone
|
||||
var bone = {}
|
||||
bone.name = g.name
|
||||
if (g.parent.type === 'group') {
|
||||
bone.parent = g.parent.name
|
||||
}
|
||||
bone.pivot = g.origin.slice()
|
||||
bone.pivot[0] *= -1
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.rotation = g.rotation.slice()
|
||||
bone.rotation[0] *= -1;
|
||||
bone.rotation[1] *= -1;
|
||||
}
|
||||
if (g.reset) {
|
||||
bone.reset = true
|
||||
}
|
||||
if (g.mirror_uv) {
|
||||
bone.mirror = true
|
||||
}
|
||||
if (g.material) {
|
||||
bone.material = g.material
|
||||
}
|
||||
//Cubes
|
||||
var cubes = []
|
||||
var locators = {};
|
||||
|
||||
for (var obj of g.children) {
|
||||
if (obj.export) {
|
||||
if (obj instanceof Cube) {
|
||||
var template = {
|
||||
origin: obj.from.slice(),
|
||||
size: obj.size(),
|
||||
inflate: obj.inflate||undefined,
|
||||
}
|
||||
if (Project.box_uv) {
|
||||
template = new oneLiner(template);
|
||||
}
|
||||
template.origin[0] = -(template.origin[0] + template.size[0])
|
||||
|
||||
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
template.pivot = obj.origin.slice();
|
||||
template.pivot[0] *= -1;
|
||||
|
||||
template.rotation = obj.rotation.slice();
|
||||
template.rotation.forEach(function(br, axis) {
|
||||
if (axis != 2) template.rotation[axis] *= -1
|
||||
})
|
||||
}
|
||||
|
||||
if (Project.box_uv) {
|
||||
template.uv = obj.uv_offset;
|
||||
if (obj.mirror_uv === !bone.mirror) {
|
||||
template.mirror = obj.mirror_uv
|
||||
}
|
||||
} else {
|
||||
template.uv = {};
|
||||
for (var key in obj.faces) {
|
||||
var face = obj.faces[key];
|
||||
if (face.texture !== null) {
|
||||
template.uv[key] = new oneLiner({
|
||||
uv: [
|
||||
face.uv[0],
|
||||
face.uv[1],
|
||||
],
|
||||
uv_size: [
|
||||
face.uv_size[0],
|
||||
face.uv_size[1],
|
||||
]
|
||||
});
|
||||
if (key == 'up') {
|
||||
template.uv[key].uv[0] += template.uv[key].uv_size[0];
|
||||
template.uv[key].uv[1] += template.uv[key].uv_size[1];
|
||||
template.uv[key].uv_size[0] *= -1;
|
||||
template.uv[key].uv_size[1] *= -1;
|
||||
}
|
||||
if (key == 'down') {
|
||||
template.uv[key].uv[1] += template.uv[key].uv_size[1];
|
||||
template.uv[key].uv_size[1] *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cubes.push(template)
|
||||
|
||||
} else if (obj instanceof Locator) {
|
||||
|
||||
locators[obj.name] = obj.from.slice();
|
||||
locators[obj.name][0] *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cubes.length) {
|
||||
bone.cubes = cubes
|
||||
}
|
||||
if (Object.keys(locators).length) {
|
||||
bone.locators = locators
|
||||
}
|
||||
let bone = compileGroup(g);
|
||||
bones.push(bone)
|
||||
})
|
||||
|
||||
@ -653,15 +694,6 @@ var codec = new Codec('bedrock', {
|
||||
})
|
||||
var thumbnail = new Jimp(48, 48, 0x00000000, function(err, image) {
|
||||
model_entry.object.bones.forEach(function(b) {
|
||||
//var rotate_bone = false;
|
||||
//if (b.name === 'body' &&
|
||||
// (included_bones.includes('leg3') || model_entry.name.includes('chicken') || model_entry.name.includes('ocelot')) &&
|
||||
// included_bones.includes('leg4') === false &&
|
||||
// !model_entry.name.includes('creeper') &&
|
||||
// ( b.rotation === undefined ||b.rotation.join('_') === '0_0_0')
|
||||
//) {
|
||||
// rotate_bone = true;
|
||||
//}
|
||||
var rotation = b.rotation
|
||||
if (!rotation || rotation[0] === undefined) {
|
||||
if (entityMode.hardcodes[model_entry.name] && entityMode.hardcodes[model_entry.name][b.name]) {
|
||||
@ -796,6 +828,13 @@ var codec = new Codec('bedrock', {
|
||||
}
|
||||
})
|
||||
|
||||
codec.parseCube = parseCube;
|
||||
codec.parseBone = parseBone;
|
||||
codec.parseGeometry = parseGeometry;
|
||||
codec.compileCube = compileCube;
|
||||
codec.compileGroup = compileGroup;
|
||||
|
||||
|
||||
var format = new ModelFormat({
|
||||
id: 'bedrock',
|
||||
extension: 'json',
|
||||
@ -806,6 +845,7 @@ var format = new ModelFormat({
|
||||
single_texture: true,
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
animated_textures: true,
|
||||
animation_mode: true,
|
||||
locators: true,
|
||||
codec,
|
@ -102,6 +102,9 @@ function parseGeometry(data) {
|
||||
group.addTo(parent_group)
|
||||
})
|
||||
}
|
||||
|
||||
codec.dispatchEvent('parsed', {model: data.object});
|
||||
|
||||
pe_list_data.length = 0;
|
||||
hideDialog()
|
||||
|
||||
@ -258,15 +261,6 @@ var codec = new Codec('bedrock_old', {
|
||||
})
|
||||
new Jimp(48, 48, 0x00000000, function(err, image) {
|
||||
model_entry.object.bones.forEach(function(b) {
|
||||
//var rotate_bone = false;
|
||||
//if (b.name === 'body' &&
|
||||
// (included_bones.includes('leg3') || model_entry.name.includes('chicken') || model_entry.name.includes('ocelot')) &&
|
||||
// included_bones.includes('leg4') === false &&
|
||||
// !model_entry.name.includes('creeper') &&
|
||||
// ( b.rotation === undefined ||b.rotation.join('_') === '0_0_0')
|
||||
//) {
|
||||
// rotate_bone = true;
|
||||
//}
|
||||
var rotation = b.rotation
|
||||
if (!rotation || rotation[0] === undefined) {
|
||||
if (entityMode.hardcodes[model_entry.name] && entityMode.hardcodes[model_entry.name][b.name]) {
|
||||
@ -473,6 +467,7 @@ var format = new ModelFormat({
|
||||
single_texture: true,
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
animated_textures: true,
|
||||
animation_mode: true,
|
||||
locators: true,
|
||||
codec,
|
@ -199,6 +199,9 @@ var codec = new Codec('java_block', {
|
||||
if (checkExport('front_gui_light', Project.front_gui_light)) {
|
||||
blockmodel.gui_light = 'front';
|
||||
}
|
||||
if (checkExport('overrides', Project.overrides)) {
|
||||
blockmodel.overrides = Project.overrides;
|
||||
}
|
||||
if (checkExport('display', Object.keys(display).length >= 1)) {
|
||||
var new_display = {}
|
||||
var entries = 0;
|
||||
@ -263,6 +266,10 @@ var codec = new Codec('java_block', {
|
||||
if (model.display !== undefined) {
|
||||
DisplayMode.loadJSON(model.display)
|
||||
}
|
||||
if (model.overrides instanceof Array) {
|
||||
Project.overrides = model.overrides.slice();
|
||||
}
|
||||
|
||||
var texture_ids = {}
|
||||
var texture_paths = {}
|
||||
if (model.textures) {
|
||||
@ -398,8 +405,8 @@ var codec = new Codec('java_block', {
|
||||
from: [0, 0, 7.5],
|
||||
to: [16, 16, 7.8],
|
||||
faces: {
|
||||
north: {uv: [16,0,0,16], texture: textures[0].uuid || null},
|
||||
south: {uv: [0,0,16,16], texture: textures[0].uuid || null},
|
||||
north: {uv: [16,0,0,16], texture: Texture.getDefault().uuid || null},
|
||||
south: {uv: [0,0,16,16], texture: Texture.getDefault().uuid || null},
|
||||
east: {uv: [0,0,0,0], texture: null},
|
||||
west: {uv: [0,0,0,0], texture: null},
|
||||
up: {uv: [0,0,0,0], texture: null},
|
||||
@ -429,6 +436,7 @@ var codec = new Codec('java_block', {
|
||||
if (model.gui_light === 'front') {
|
||||
Project.front_gui_light = true;
|
||||
}
|
||||
this.dispatchEvent('parsed', {model});
|
||||
if (add) {
|
||||
Undo.finishEdit('add block model')
|
||||
}
|
@ -12,7 +12,7 @@ function I(num) {
|
||||
}
|
||||
const Templates = {
|
||||
'1.12': {
|
||||
name: '1.12',
|
||||
name: 'Forge 1.12',
|
||||
flip_y: true,
|
||||
integer_size: true,
|
||||
file:
|
||||
@ -54,7 +54,7 @@ const Templates = {
|
||||
},
|
||||
|
||||
'1.14': {
|
||||
name: '1.14',
|
||||
name: 'Forge 1.14',
|
||||
flip_y: true,
|
||||
integer_size: true,
|
||||
file:
|
||||
@ -96,7 +96,7 @@ const Templates = {
|
||||
},
|
||||
|
||||
'1.15': {
|
||||
name: '1.15',
|
||||
name: 'Forge 1.15',
|
||||
flip_y: true,
|
||||
integer_size: false,
|
||||
file:
|
||||
@ -174,11 +174,12 @@ var codec = new Codec('modded_entity', {
|
||||
if (cube.parent == 'root') loose_cubes.push(cube)
|
||||
})
|
||||
if (loose_cubes.length) {
|
||||
all_groups.push(new Group({
|
||||
let group = new Group({
|
||||
name: 'bb_main',
|
||||
children: loose_cubes,
|
||||
is_catch_bone: true
|
||||
}))
|
||||
});
|
||||
all_groups.push(group)
|
||||
group.children.replace(loose_cubes)
|
||||
}
|
||||
|
||||
let model = Templates.get('file');
|
||||
@ -302,8 +303,9 @@ var codec = new Codec('modded_entity', {
|
||||
return group_snippets.join('\n\t\t')
|
||||
});
|
||||
|
||||
this.dispatchEvent('compile', {model, options});
|
||||
return model;
|
||||
let event = {model, options};
|
||||
this.dispatchEvent('compile', event);
|
||||
return event.model;
|
||||
},
|
||||
parse(model, path, add) {
|
||||
this.dispatchEvent('parse', {model});
|
||||
@ -612,6 +614,7 @@ var codec = new Codec('modded_entity', {
|
||||
}
|
||||
})
|
||||
Project.geometry_name = geo_name;
|
||||
this.dispatchEvent('parsed', {model});
|
||||
Canvas.updateAll();
|
||||
},
|
||||
fileName() {
|
@ -19,7 +19,7 @@ function getMtlFace(obj, index) {
|
||||
} else if (!tex || typeof tex === 'string') {
|
||||
return 'usemtl none\n'
|
||||
} else {
|
||||
return 'usemtl ' + tex.id + '\n';
|
||||
return 'usemtl m_' + tex.id + '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ var codec = new Codec('obj', {
|
||||
for (var key in materials) {
|
||||
if (materials.hasOwnProperty(key) && materials[key]) {
|
||||
var tex = materials[key];
|
||||
mtlOutput += 'newmtl ' +key+ '\n'
|
||||
mtlOutput += 'newmtl m_' +key+ '\n'
|
||||
mtlOutput += `map_Kd ${tex.name} \n`;
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,6 @@ var codec = new Codec('obj', {
|
||||
type: this.name,
|
||||
extensions: [this.extension],
|
||||
name: this.fileName(),
|
||||
startpath: this.startPath(),
|
||||
custom_writer: (a, b) => scope.write(a, b),
|
||||
})
|
||||
|
@ -8,8 +8,8 @@ var codec = new Codec('optifine_entity', {
|
||||
if (options === undefined) options = {}
|
||||
var entitymodel = {}
|
||||
var geo_code = 'geometry.'+Project.geometry_name
|
||||
if (textures[0]) {
|
||||
entitymodel.texture = textures[0].name
|
||||
if (Texture.getDefault()) {
|
||||
entitymodel.texture = Texture.getDefault().name
|
||||
}
|
||||
entitymodel.textureSize = [Project.texture_width, Project.texture_height];
|
||||
entitymodel.models = []
|
||||
@ -127,6 +127,11 @@ var codec = new Codec('optifine_entity', {
|
||||
})
|
||||
}
|
||||
populate(bone, g, 0)
|
||||
|
||||
if (g.cem_animations.length) {
|
||||
bone.animations = g.cem_animations;
|
||||
}
|
||||
|
||||
entitymodel.models.push(bone)
|
||||
})
|
||||
|
||||
@ -155,7 +160,8 @@ var codec = new Codec('optifine_entity', {
|
||||
name: b.part,
|
||||
origin: b.translate,
|
||||
rotation: b.rotate,
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u'))
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u')),
|
||||
cem_animations: b.animations
|
||||
})
|
||||
group.origin[1] *= -1;
|
||||
group.origin[2] *= -1;
|
||||
@ -238,11 +244,12 @@ var codec = new Codec('optifine_entity', {
|
||||
})
|
||||
}
|
||||
loadOutlinerDraggable()
|
||||
Canvas.updateAll()
|
||||
if (model.texture) {
|
||||
var path = path.replace(/\\[\w .-]+$/, '\\'+model.texture)
|
||||
new Texture().fromPath(path).add(false)
|
||||
}
|
||||
this.dispatchEvent('parsed', {model});
|
||||
Canvas.updateAll()
|
||||
}
|
||||
})
|
||||
|
@ -7,8 +7,8 @@ var part_codec = new Codec('optifine_part', {
|
||||
compile(options) {
|
||||
if (options === undefined) options = {}
|
||||
var jpm = {}
|
||||
if (textures[0]) {
|
||||
jpm.texture = pathToName(textures[0].name, false)
|
||||
if (Texture.getDefault()) {
|
||||
jpm.texture = pathToName(Texture.getDefault().name, false)
|
||||
}
|
||||
jpm.textureSize = [Project.texture_width, Project.texture_height]
|
||||
|
||||
@ -203,6 +203,7 @@ var part_codec = new Codec('optifine_part', {
|
||||
Undo.finishEdit('add jpm model')
|
||||
}
|
||||
addSubmodel(model)
|
||||
this.dispatchEvent('parsed', {model});
|
||||
Canvas.updateAll()
|
||||
}
|
||||
})
|
@ -74,13 +74,14 @@ const codec = new Codec('skin_model', {
|
||||
this.dispatchEvent('compile', {model: entitymodel, options});
|
||||
return entitymodel
|
||||
},
|
||||
parse(data, resolution, texture_path, pose = true) {
|
||||
parse(data, resolution, texture_path, pose = true, layer_template) {
|
||||
this.dispatchEvent('parse', {model: data});
|
||||
Project.geometry_name = data.name;
|
||||
Project.texture_width = data.texturewidth || 64;
|
||||
Project.texture_height = data.textureheight || 64;
|
||||
|
||||
var bones = {}
|
||||
var template_cubes = {};
|
||||
|
||||
if (data.bones) {
|
||||
var included_bones = []
|
||||
@ -129,6 +130,7 @@ const codec = new Codec('skin_model', {
|
||||
base_cube.mirror_uv = s.mirror === true
|
||||
}
|
||||
base_cube.addTo(group).init()
|
||||
template_cubes[Cube.all.indexOf(base_cube)] = s;
|
||||
})
|
||||
}
|
||||
if (b.children) {
|
||||
@ -161,7 +163,14 @@ const codec = new Codec('skin_model', {
|
||||
if (texture_path) {
|
||||
var texture = new Texture().fromPath(texture_path).add(false);
|
||||
} else {
|
||||
var texture = generateTemplate(Project.texture_width*resolution, Project.texture_height*resolution, data.name, data.eyes)
|
||||
var texture = generateTemplate(
|
||||
Project.texture_width*resolution,
|
||||
Project.texture_height*resolution,
|
||||
template_cubes,
|
||||
data.name,
|
||||
data.eyes,
|
||||
layer_template
|
||||
)
|
||||
}
|
||||
texture.load_callback = function() {
|
||||
Modes.options.paint.select();
|
||||
@ -199,7 +208,7 @@ format.new = function() {
|
||||
}
|
||||
}
|
||||
|
||||
function generateTemplate(width = 64, height = 64, name = 'name', eyes) {
|
||||
function generateTemplate(width = 64, height = 64, cubes, name = 'name', eyes, layer_template) {
|
||||
|
||||
var texture = new Texture({
|
||||
mode: 'bitmap',
|
||||
@ -210,8 +219,11 @@ function generateTemplate(width = 64, height = 64, name = 'name', eyes) {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
Cube.all.forEach(cube => {
|
||||
TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas, null, !!cube.inflate);
|
||||
Cube.all.forEach((cube, i) => {
|
||||
let template_cube = cubes[i];
|
||||
if (layer_template || !template_cube.layer) {
|
||||
TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas, null, template_cube.layer);
|
||||
}
|
||||
})
|
||||
if (eyes) {
|
||||
var res_multiple = canvas.width/Project.texture_width;
|
||||
@ -322,13 +334,14 @@ const skin_dialog = new Dialog({
|
||||
extensions: ['png'],
|
||||
filetype: 'PNG',
|
||||
},
|
||||
pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true}
|
||||
pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true},
|
||||
layer_template: {type: 'checkbox', label: 'dialog.skin.layer_template', 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, result.pose);
|
||||
codec.parse(model, result.resolution/16, result.texture, result.pose, result.layer_template);
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
@ -344,7 +357,7 @@ BARS.defineActions(function() {
|
||||
new Action('toggle_skin_layer', {
|
||||
icon: 'layers_clear',
|
||||
category: 'edit',
|
||||
condition: () => Format.id == 'skin',
|
||||
condition: {formats: ['skin']},
|
||||
click: function () {
|
||||
var edited = [];
|
||||
Cube.all.forEach(cube => {
|
||||
@ -380,7 +393,7 @@ skin_presets.steve = `{
|
||||
"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}
|
||||
{"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -389,7 +402,7 @@ skin_presets.steve = `{
|
||||
"pivot": [0, 24, 0],
|
||||
"cubes": [
|
||||
{"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]},
|
||||
{"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25}
|
||||
{"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -399,7 +412,7 @@ skin_presets.steve = `{
|
||||
"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}
|
||||
{"name": "Right Arm Layer", "visibility": false, "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -409,7 +422,7 @@ skin_presets.steve = `{
|
||||
"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}
|
||||
{"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [48, 48], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -419,7 +432,7 @@ skin_presets.steve = `{
|
||||
"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}
|
||||
{"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -429,7 +442,7 @@ skin_presets.steve = `{
|
||||
"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}
|
||||
{"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -450,7 +463,7 @@ skin_presets.alex = `{
|
||||
"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}
|
||||
{"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -459,7 +472,7 @@ skin_presets.alex = `{
|
||||
"pivot": [0, 24, 0],
|
||||
"cubes": [
|
||||
{"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]},
|
||||
{"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25}
|
||||
{"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -469,7 +482,7 @@ skin_presets.alex = `{
|
||||
"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}
|
||||
{"name": "Right Arm Layer", "visibility": false, "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -479,7 +492,7 @@ skin_presets.alex = `{
|
||||
"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}
|
||||
{"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [48, 48], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -489,7 +502,7 @@ skin_presets.alex = `{
|
||||
"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}
|
||||
{"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -499,7 +512,7 @@ skin_presets.alex = `{
|
||||
"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}
|
||||
{"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25, "layer": true}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -1804,7 +1817,7 @@ skin_presets.enderman = `{
|
||||
"pivot": [0, 24, 0],
|
||||
"cubes": [
|
||||
{"name": "head", "origin": [-4, 40, -4], "size": [8, 8, 8], "uv": [0, 0], "inflate": -0.5},
|
||||
{"name": "head layer", "origin": [-4, 38, -4], "size": [8, 8, 8], "uv": [0, 16], "inflate": -0.5}
|
||||
{"name": "head layer", "origin": [-4, 38, -4], "size": [8, 8, 8], "uv": [0, 16], "inflate": -0.5, "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -4002,7 +4015,7 @@ skin_presets.silverfish = `{
|
||||
"parent": "bodyPart_1",
|
||||
"pivot": [0, 5, -1.5],
|
||||
"cubes": [
|
||||
{"name": "bodyLayer_2", "origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18]}
|
||||
{"name": "bodyLayer_2", "origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18], "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -4026,7 +4039,7 @@ skin_presets.silverfish = `{
|
||||
"parent": "bodyPart_4",
|
||||
"pivot": [0, 4, 7],
|
||||
"cubes": [
|
||||
{"name": "bodyLayer_1", "origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11]}
|
||||
{"name": "bodyLayer_1", "origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11], "layer": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -4050,7 +4063,7 @@ skin_presets.silverfish = `{
|
||||
"parent": "bodyPart_2",
|
||||
"pivot": [0, 8, 1],
|
||||
"cubes": [
|
||||
{"name": "bodyLayer_0", "origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0]}
|
||||
{"name": "bodyLayer_0", "origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0], "layer": true}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -4157,10 +4170,10 @@ skin_presets.slime = `{
|
||||
"name": "outer",
|
||||
"pivot": [0, 24, 0],
|
||||
"cubes": [
|
||||
{"name": "cube layer", "visibility": false, "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]},
|
||||
{"name": "eye0 layer", "visibility": false, "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]},
|
||||
{"name": "eye1 layer", "visibility": false, "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]},
|
||||
{"name": "mouth layer", "visibility": false, "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]}
|
||||
{"name": "cube layer", "visibility": false, "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0], "layer": true},
|
||||
{"name": "eye0 layer", "visibility": false, "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0], "layer": true},
|
||||
{"name": "eye1 layer", "visibility": false, "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4], "layer": true},
|
||||
{"name": "mouth layer", "visibility": false, "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8], "layer": true}
|
||||
]
|
||||
}
|
||||
]
|
20
js/io/io.js
20
js/io/io.js
@ -36,7 +36,7 @@ class ModelFormat {
|
||||
this.canvas_limit = false;
|
||||
this.rotation_limit = false;
|
||||
this.uv_rotation = false;
|
||||
this.display_mode = false;
|
||||
this.ro_mode = false;
|
||||
this.animation_mode = false;
|
||||
|
||||
this.codec = data.codec;
|
||||
@ -77,8 +77,7 @@ class ModelFormat {
|
||||
} else {
|
||||
scene.position.set(-8, -8, -8);
|
||||
}
|
||||
var center = Format.centered_grid ? 8 : 0;
|
||||
previews.forEach(preview => {
|
||||
Preview.all.forEach(preview => {
|
||||
if (preview.isOrtho && typeof preview.angle == 'number') {
|
||||
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
|
||||
}
|
||||
@ -88,6 +87,7 @@ class ModelFormat {
|
||||
})
|
||||
updateSelection()
|
||||
Modes.vue.$forceUpdate()
|
||||
updateShading();
|
||||
Canvas.updateRenderSides()
|
||||
return this;
|
||||
}
|
||||
@ -107,19 +107,6 @@ class ModelFormat {
|
||||
var old_format = Format
|
||||
this.select(true)
|
||||
Modes.options.edit.select()
|
||||
//Single Texture
|
||||
if (Format.single_texture && !old_format.single_texture) {
|
||||
if (textures.length > 1) {
|
||||
textures.splice(1)
|
||||
}
|
||||
if (textures.length) {
|
||||
var tex = textures[0]
|
||||
tex.particle = false
|
||||
if (tex.img.naturalWidth !== tex.img.naturalWidth && tex.error) {
|
||||
tex.error = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bone Rig
|
||||
if (!Format.bone_rig && old_format.bone_rig) {
|
||||
@ -811,6 +798,7 @@ BARS.defineActions(function() {
|
||||
optional_box_uv: true,
|
||||
uv_rotation: true,
|
||||
animation_mode: true,
|
||||
codec: Codecs.project
|
||||
})
|
||||
|
||||
//Import
|
||||
|
258
js/io/project.js
258
js/io/project.js
@ -1,86 +1,140 @@
|
||||
const Project = {
|
||||
name : '',
|
||||
parent : '',
|
||||
geometry_name : '',
|
||||
description : '',
|
||||
_box_uv : false,
|
||||
get box_uv() {return Project._box_uv},
|
||||
class ModelProject {
|
||||
constructor() {
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].reset(this);
|
||||
}
|
||||
|
||||
this._box_uv = false;
|
||||
this._texture_width = 16;
|
||||
this._texture_height = 16;
|
||||
}
|
||||
extend() {
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].merge(this, object)
|
||||
}
|
||||
}
|
||||
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},
|
||||
}
|
||||
get texture_width() {return this._texture_width}
|
||||
get texture_height() {return this._texture_height}
|
||||
set texture_width(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
Project._texture_width = n;
|
||||
},
|
||||
this._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',
|
||||
this._texture_height = n;
|
||||
}
|
||||
get optional_box_uv() {
|
||||
return Format.optional_box_uv;
|
||||
}
|
||||
reset() {
|
||||
Blockbench.dispatchEvent('reset_project');
|
||||
if (isApp) updateRecentProjectThumbnail()
|
||||
if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
|
||||
|
||||
Screencam.stopTimelapse();
|
||||
|
||||
Format = 0;
|
||||
Outliner.elements.empty();
|
||||
Outliner.root.purge();
|
||||
Canvas.materials;
|
||||
selected.empty();
|
||||
Group.all.empty();
|
||||
Group.selected = undefined;
|
||||
Cube.all.empty();
|
||||
Cube.selected.empty();
|
||||
Locator.all.empty();
|
||||
Locator.selected.empty();
|
||||
Texture.all.empty();
|
||||
Texture.selected = undefined;
|
||||
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].reset(this)
|
||||
}
|
||||
this.texture_width = this.texture_height = 16;
|
||||
this.overrides = null;
|
||||
|
||||
Blockbench.display_settings = display = {};
|
||||
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.empty();
|
||||
Undo.index = 0;
|
||||
Undo.current_save = null;
|
||||
Painter.current = {};
|
||||
Animator.animations.purge();
|
||||
Timeline.animators.purge();
|
||||
Animator.selected = undefined;
|
||||
$('#var_placeholder_area').val('');
|
||||
}
|
||||
}
|
||||
new Property(ModelProject, 'string', 'name', {
|
||||
label: 'dialog.project.name'
|
||||
});
|
||||
new Property(ModelProject, 'string', 'parent', {
|
||||
label: 'dialog.project.parent',
|
||||
condition: {formats: ['java_block']
|
||||
}});
|
||||
new Property(ModelProject, 'string', 'geometry_name', {
|
||||
label: 'dialog.project.geoname',
|
||||
condition: () => Format.bone_rig
|
||||
});
|
||||
new Property(ModelProject, 'string', 'modded_entity_version', {
|
||||
label: 'dialog.project.modded_entity_version',
|
||||
default: '1.15',
|
||||
condition: {formats: ['modded_entity']},
|
||||
options() {
|
||||
let options = {}
|
||||
for (var key in Codecs.modded_entity.templates) {
|
||||
if (Codecs.modded_entity.templates[key] instanceof Function == false) {
|
||||
options[key] = Codecs.modded_entity.templates[key].name;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
});
|
||||
new Property(ModelProject, 'boolean', 'ambientocclusion', {
|
||||
label: 'dialog.project.ao',
|
||||
default: true,
|
||||
condition: {formats: ['java_block']}
|
||||
});
|
||||
new Property(ModelProject, 'boolean', 'front_gui_light', {
|
||||
exposed: false,
|
||||
condition: () => Format.display_mode});
|
||||
new Property(ModelProject, 'vector', 'visible_box', {
|
||||
exposed: false,
|
||||
default: [1, 1, 0]
|
||||
});
|
||||
new Property(ModelProject, 'boolean', 'layered_textures', {
|
||||
label: 'dialog.project.layered_textures',
|
||||
condition() {return Format.single_texture}
|
||||
});
|
||||
|
||||
|
||||
const Project = new ModelProject();
|
||||
|
||||
|
||||
//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('');
|
||||
Project.reset()
|
||||
}
|
||||
function newProject(format, force) {
|
||||
if (force || showSaveDialog()) {
|
||||
resetProject();
|
||||
if (Format) {
|
||||
Project.reset();
|
||||
}
|
||||
Modes.options.edit.select();
|
||||
if (format instanceof ModelFormat) {
|
||||
format.select();
|
||||
@ -101,39 +155,46 @@ BARS.defineActions(function() {
|
||||
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;
|
||||
let form = {
|
||||
format: {type: 'info', label: 'data.format', text: Format.name||'unknown'}
|
||||
}
|
||||
|
||||
for (var key in ModelProject.properties) {
|
||||
let property = ModelProject.properties[key];
|
||||
if (property.exposed == false || !Condition(property.condition)) continue;
|
||||
|
||||
let entry = form[property.name] = {
|
||||
label: property.label,
|
||||
value: Project[property.name],
|
||||
type: property.type
|
||||
}
|
||||
if (property.type == 'boolean') entry.type = 'checkbox';
|
||||
if (property.type == 'string') entry.type = 'text';
|
||||
if (property.options) {
|
||||
entry.options = typeof property.options == 'function' ? property.options() : property.options;
|
||||
entry.type = 'select';
|
||||
}
|
||||
}
|
||||
|
||||
form.box_uv = {label: 'dialog.project.box_uv', type: 'checkbox', value: Project.box_uv, condition: Format.optional_box_uv};
|
||||
form.texture_width = {
|
||||
label: 'dialog.project.width',
|
||||
type: 'number',
|
||||
value: Project.texture_width,
|
||||
min: 1
|
||||
};
|
||||
form.texture_height = {
|
||||
label: 'dialog.project.height',
|
||||
type: 'number',
|
||||
value: Project.texture_height,
|
||||
min: 1
|
||||
};
|
||||
|
||||
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
|
||||
},
|
||||
},
|
||||
width: 500,
|
||||
form,
|
||||
onConfirm: function(formResult) {
|
||||
var save;
|
||||
if (Project.box_uv != formResult.box_uv ||
|
||||
@ -165,11 +226,20 @@ BARS.defineActions(function() {
|
||||
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 (Format.single_texture) {
|
||||
if (Project.layered_textures !== formResult.layered_textures && Texture.all.length >= 2) {
|
||||
Project.layered_textures = formResult.layered_textures;
|
||||
Texture.all.forEach((tex, i) => {
|
||||
tex.visible = i < 3
|
||||
})
|
||||
texturelist.$forceUpdate()
|
||||
Canvas.updateLayeredTextures();
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in ModelProject.properties) {
|
||||
ModelProject.properties[key].merge(Project, formResult);
|
||||
}
|
||||
|
||||
if (save) {
|
||||
Undo.finishEdit('change global UV')
|
||||
|
@ -81,6 +81,7 @@ BARS.defineActions(function() {
|
||||
center_windows: ['start_screen'],
|
||||
hide_toolbars: true,
|
||||
onSelect: function () {
|
||||
if (Format && isApp) updateRecentProjectThumbnail()
|
||||
},
|
||||
onUnselect: function () {
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
|
||||
class Face {
|
||||
constructor(direction, data) {
|
||||
constructor(direction, data, cube) {
|
||||
this.direction = direction || 'north';
|
||||
this.cube = cube;
|
||||
this.reset()
|
||||
this.uv = [0, 0, canvasGridSize(), canvasGridSize()]
|
||||
if (data) {
|
||||
@ -49,8 +50,8 @@ class Face {
|
||||
return this;
|
||||
}
|
||||
getTexture() {
|
||||
if (Format.single_texture && Project.box_uv && this.texture !== null) {
|
||||
return textures[0];
|
||||
if (Format.single_texture && this.texture !== null) {
|
||||
return Texture.getDefault();
|
||||
}
|
||||
if (typeof this.texture === 'string') {
|
||||
return textures.findInArray('uuid', this.texture)
|
||||
@ -94,7 +95,6 @@ class Cube extends NonGroup {
|
||||
constructor(data, uuid) {
|
||||
super(data, uuid)
|
||||
let size = canvasGridSize();
|
||||
this.name = 'cube';
|
||||
this.from = [0, 0, 0];
|
||||
this.to = [size, size, size];
|
||||
this.shade = true;
|
||||
@ -111,20 +111,27 @@ class Cube extends NonGroup {
|
||||
this.autouv = 0
|
||||
this.parent = 'root';
|
||||
|
||||
for (var key in Cube.properties) {
|
||||
Cube.properties[key].reset(this);
|
||||
}
|
||||
|
||||
this.faces = {
|
||||
north: new Face('north'),
|
||||
east: new Face('east'),
|
||||
south: new Face('south'),
|
||||
west: new Face('west'),
|
||||
up: new Face('up'),
|
||||
down: new Face('down')
|
||||
north: new Face('north', null, this),
|
||||
east: new Face('east', null, this),
|
||||
south: new Face('south', null, this),
|
||||
west: new Face('west', null, this),
|
||||
up: new Face('up', null, this),
|
||||
down: new Face('down', null, this)
|
||||
}
|
||||
if (data && typeof data === 'object') {
|
||||
this.extend(data)
|
||||
}
|
||||
}
|
||||
extend(object) {
|
||||
Merge.string(this, object, 'name')
|
||||
for (var key in Cube.properties) {
|
||||
Cube.properties[key].merge(this, object)
|
||||
}
|
||||
|
||||
this.sanitizeName();
|
||||
Merge.boolean(this, object, 'shade')
|
||||
Merge.boolean(this, object, 'mirror_uv')
|
||||
@ -198,10 +205,10 @@ class Cube extends NonGroup {
|
||||
}
|
||||
init() {
|
||||
super.init();
|
||||
if (Format.single_texture && textures[0]) {
|
||||
if (Format.single_texture && Texture.getDefault()) {
|
||||
for (var face in this.faces) {
|
||||
if (this.faces[face].texture !== null) {
|
||||
this.faces[face].texture = textures[0].uuid
|
||||
this.faces[face].texture = Texture.getDefault().uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -284,14 +291,18 @@ class Cube extends NonGroup {
|
||||
delete copy.parent;
|
||||
return copy;
|
||||
}
|
||||
getSaveCopy(meta) {
|
||||
var el = {
|
||||
name: this.name,
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
autouv: this.autouv,
|
||||
color: this.color
|
||||
getSaveCopy() {
|
||||
var el = {}
|
||||
|
||||
for (var key in Cube.properties) {
|
||||
Cube.properties[key].copy(this, el)
|
||||
}
|
||||
|
||||
el.from = this.from;
|
||||
el.to = this.to;
|
||||
el.autouv = this.autouv;
|
||||
el.color = this.color;
|
||||
|
||||
el.locked = this.locked;
|
||||
if (!this.visibility) el.visibility = false;
|
||||
if (!this.export) el.export = false;
|
||||
@ -792,6 +803,9 @@ class Cube extends NonGroup {
|
||||
Cube.selected = [];
|
||||
Cube.all = [];
|
||||
|
||||
new Property(Cube, 'string', 'name', {default: 'cube'})
|
||||
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
@ -811,7 +825,7 @@ BARS.defineActions(function() {
|
||||
|
||||
if (textures.length && Format.single_texture) {
|
||||
for (var face in base_cube.faces) {
|
||||
base_cube.faces[face].texture = textures[0].uuid
|
||||
base_cube.faces[face].texture = Texture.getDefault().uuid
|
||||
}
|
||||
main_uv.loadData()
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
|
||||
class Group extends OutlinerElement {
|
||||
constructor(data) {
|
||||
super()
|
||||
constructor(data, uuid) {
|
||||
super(uuid)
|
||||
|
||||
for (var key in Group.properties) {
|
||||
Group.properties[key].reset(this);
|
||||
}
|
||||
|
||||
this.name = Format.bone_rig ? 'bone' : 'group'
|
||||
this.children = []
|
||||
this.origin = [0, 0, 0];
|
||||
if (!Format.centered_grid) {
|
||||
this.origin.V3_set(8, 8, 8);
|
||||
}
|
||||
this.rotation = [0, 0, 0];
|
||||
this.reset = false;
|
||||
this.shade = true;
|
||||
this.selected = false;
|
||||
@ -28,11 +28,15 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
}
|
||||
extend(object) {
|
||||
for (var key in Group.properties) {
|
||||
Group.properties[key].merge(this, object)
|
||||
}
|
||||
Merge.string(this, object, 'name')
|
||||
this.sanitizeName();
|
||||
Merge.boolean(this, object, 'shade')
|
||||
Merge.boolean(this, object, 'mirror_uv')
|
||||
Merge.boolean(this, object, 'reset')
|
||||
/*
|
||||
if (object.origin) {
|
||||
Merge.number(this.origin, object.origin, 0)
|
||||
Merge.number(this.origin, object.origin, 1)
|
||||
@ -42,7 +46,7 @@ class Group extends OutlinerElement {
|
||||
Merge.number(this.rotation, object.rotation, 0)
|
||||
Merge.number(this.rotation, object.rotation, 1)
|
||||
Merge.number(this.rotation, object.rotation, 2)
|
||||
}
|
||||
}*/
|
||||
Merge.number(this, object, 'autouv')
|
||||
Merge.boolean(this, object, 'export')
|
||||
Merge.boolean(this, object, 'locked')
|
||||
@ -213,11 +217,11 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
}
|
||||
resolve() {
|
||||
var scope = this;
|
||||
var array = this.children.slice().reverse();
|
||||
var array = this.children.slice();
|
||||
var index = this.getParentArray().indexOf(this)
|
||||
|
||||
array.forEach(function(s, i) {
|
||||
s.addTo(scope.parent)
|
||||
array.forEach((s, i) => {
|
||||
s.addTo(this.parent, index)
|
||||
})
|
||||
TickUpdates.outliner = true;
|
||||
this.remove(false);
|
||||
@ -277,7 +281,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
duplicate() {
|
||||
var copied_groups = [];
|
||||
var copy = this.getChildlessCopy()
|
||||
var copy = this.getChildlessCopy(false)
|
||||
delete copy.parent;
|
||||
copied_groups.push(copy)
|
||||
copy.sortInBefore(this, 1).init()
|
||||
@ -293,16 +297,18 @@ class Group extends OutlinerElement {
|
||||
return copy;
|
||||
}
|
||||
getSaveCopy() {
|
||||
var scope = this;
|
||||
var base_group = this.getChildlessCopy();
|
||||
var base_group = this.getChildlessCopy(true);
|
||||
for (var child of this.children) {
|
||||
base_group.children.push(child.getSaveCopy());
|
||||
}
|
||||
delete base_group.parent;
|
||||
return base_group;
|
||||
}
|
||||
getChildlessCopy() {
|
||||
var base_group = new Group();
|
||||
getChildlessCopy(keep_uuid) {
|
||||
var base_group = new Group({name: this.name}, keep_uuid ? this.uuid : null);
|
||||
for (var key in Group.properties) {
|
||||
Group.properties[key].copy(this, base_group)
|
||||
}
|
||||
base_group.name = this.name;
|
||||
base_group.origin.V3_set(this.origin);
|
||||
base_group.rotation.V3_set(this.rotation);
|
||||
@ -318,6 +324,9 @@ class Group extends OutlinerElement {
|
||||
var obj = {
|
||||
name: this.name
|
||||
}
|
||||
for (var key in Group.properties) {
|
||||
Group.properties[key].copy(this, obj)
|
||||
}
|
||||
if (this.shade == false) {
|
||||
obj.shade = false
|
||||
}
|
||||
@ -329,10 +338,9 @@ class Group extends OutlinerElement {
|
||||
obj.visibility = this.visibility;
|
||||
obj.autouv = this.autouv;
|
||||
}
|
||||
obj.origin = this.origin.slice()
|
||||
|
||||
if (!this.rotation.allEqual(0)) {
|
||||
obj.rotation = this.rotation.slice()
|
||||
if (this.rotation.allEqual(0)) {
|
||||
delete obj.rotation;
|
||||
}
|
||||
if (this.reset) {
|
||||
obj.reset = true
|
||||
@ -415,6 +423,13 @@ class Group extends OutlinerElement {
|
||||
Group.selected;
|
||||
Group.all = [];
|
||||
|
||||
new Property(Group, 'vector', 'origin', {default() {
|
||||
return Format.centered_grid ? [0, 0, 0] : [8, 8, 8]
|
||||
}});
|
||||
new Property(Group, 'vector', 'rotation');
|
||||
new Property(Group, 'array', 'cem_animations', {condition: () => Format.id == 'optifine_entity'});
|
||||
|
||||
|
||||
function getCurrentGroup() {
|
||||
if (Group.selected) {
|
||||
return Group.selected
|
||||
|
@ -2,19 +2,22 @@
|
||||
class Locator extends NonGroup {
|
||||
constructor(data, uuid) {
|
||||
super(data, uuid);
|
||||
this.from = new Array().V3_set(0, 0, 0);
|
||||
this.name = 'locator';
|
||||
|
||||
for (var key in Locator.properties) {
|
||||
Locator.properties[key].reset(this);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this.extend(data);
|
||||
}
|
||||
}
|
||||
extend(object) {
|
||||
Merge.string(this, object, 'name');
|
||||
for (var key in Locator.properties) {
|
||||
Locator.properties[key].merge(this, object)
|
||||
}
|
||||
this.sanitizeName();
|
||||
Merge.boolean(this, object, 'locked')
|
||||
Merge.boolean(this, object, 'export');
|
||||
Merge.arrayVector(this, object, 'from');
|
||||
return this;
|
||||
}
|
||||
getUndoCopy() {
|
||||
@ -25,14 +28,14 @@ class Locator extends NonGroup {
|
||||
return copy;
|
||||
}
|
||||
getSaveCopy() {
|
||||
var el = {
|
||||
name: this.name,
|
||||
export: this.export ? undefined : false,
|
||||
locked: this.locked,
|
||||
from: this.from,
|
||||
uuid: this.uuid,
|
||||
type: 'locator'
|
||||
};
|
||||
let el = {};
|
||||
for (var key in Locator.properties) {
|
||||
Locator.properties[key].copy(this, el)
|
||||
}
|
||||
el.export = this.export ? undefined : false;
|
||||
el.locked = this.locked;
|
||||
el.uuid = this.uuid;
|
||||
el.type = 'locator';
|
||||
return el;
|
||||
}
|
||||
init() {
|
||||
@ -81,6 +84,9 @@ class Locator extends NonGroup {
|
||||
])
|
||||
Locator.selected = [];
|
||||
Locator.all = [];
|
||||
|
||||
new Property(Locator, 'string', 'name', {default: 'locator'})
|
||||
new Property(Locator, 'vector', 'from')
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action('add_locator', {
|
||||
|
@ -139,10 +139,7 @@ class OutlinerElement {
|
||||
TickUpdates.outliner = true;
|
||||
return this;
|
||||
}
|
||||
addTo(group) {
|
||||
//Remove
|
||||
var index = -1;
|
||||
|
||||
addTo(group, index = -1) {
|
||||
//Resolve Group Argument
|
||||
if (group === undefined) {
|
||||
group = 'root'
|
||||
@ -639,7 +636,7 @@ function parseGroups(array, importGroup, startIndex) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var obj = new Group(array[i])
|
||||
var obj = new Group(array[i], array[i].uuid)
|
||||
obj.parent = addGroup
|
||||
obj.isOpen = !!array[i].isOpen
|
||||
if (array[i].uuid) {
|
||||
|
@ -73,7 +73,7 @@ const Canvas = {
|
||||
},
|
||||
getCurrentPreview() {
|
||||
if (quad_previews.current) return quad_previews.current;
|
||||
var canvas = $('canvas.preview:hover').get(0)
|
||||
var canvas = $('.preview:hover').get(0)
|
||||
if (canvas) return canvas.preview
|
||||
},
|
||||
withoutGizmos(cb) {
|
||||
@ -87,10 +87,14 @@ const Canvas = {
|
||||
edit(rot_origin)
|
||||
edit(Vertexsnap.vertexes)
|
||||
Cube.selected.forEach(function(obj) {
|
||||
var m = obj.mesh
|
||||
if (m && m.outline) {
|
||||
edit(m.outline)
|
||||
}
|
||||
var m = obj.mesh;
|
||||
if (!m) return;
|
||||
if (m.outline) edit(m.outline);
|
||||
})
|
||||
Cube.all.forEach(function(obj) {
|
||||
var m = obj.mesh;
|
||||
if (!m) return;
|
||||
if (m.grid_box) edit(m.grid_box);
|
||||
})
|
||||
}
|
||||
editVis(obj => {
|
||||
@ -189,7 +193,7 @@ const Canvas = {
|
||||
if (texture) {
|
||||
used = false;
|
||||
for (var face in obj.faces) {
|
||||
if (obj.faces[face].texture === texture.uuid) {
|
||||
if (obj.faces[face].getTexture() == texture) {
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
@ -234,6 +238,9 @@ const Canvas = {
|
||||
mat.side = side
|
||||
}
|
||||
})
|
||||
if (Project.layered_textures && Canvas.layered_material) {
|
||||
Canvas.layered_material.side = side;
|
||||
}
|
||||
emptyMaterials.forEach(function(mat) {
|
||||
mat.side = side
|
||||
})
|
||||
@ -495,13 +502,44 @@ const Canvas = {
|
||||
}
|
||||
iterate(el, elmesh)
|
||||
},
|
||||
getLayeredMaterial() {
|
||||
getLayeredMaterial(layers) {
|
||||
if (Canvas.layered_material && !layers) return Canvas.layered_material;
|
||||
// https://codepen.io/Fyrestar/pen/YmpXYr
|
||||
var vertShader = `
|
||||
uniform bool SHADE;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying float light;
|
||||
varying float lift;
|
||||
|
||||
float AMBIENT = 0.5;
|
||||
float XFAC = -0.15;
|
||||
float ZFAC = 0.05;
|
||||
|
||||
void main()
|
||||
{
|
||||
vUv = uv;
|
||||
|
||||
if (SHADE) {
|
||||
|
||||
vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );
|
||||
|
||||
|
||||
float yLight = (1.0+N.y) * 0.5;
|
||||
light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;
|
||||
|
||||
} else {
|
||||
|
||||
light = 1.0;
|
||||
|
||||
}
|
||||
|
||||
if (color.b == 1.25) {
|
||||
lift = 0.1;
|
||||
} else {
|
||||
lift = 0.0;
|
||||
}
|
||||
|
||||
vUv = uv;
|
||||
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}`
|
||||
@ -510,47 +548,70 @@ const Canvas = {
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform sampler2D tOne;
|
||||
uniform sampler2D tSec;
|
||||
uniform sampler2D t0;
|
||||
uniform sampler2D t1;
|
||||
uniform sampler2D t2;
|
||||
|
||||
uniform bool SHADE;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying float light;
|
||||
varying float lift;
|
||||
|
||||
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);
|
||||
vec4 Ca = texture2D(t0, vUv);
|
||||
vec4 Cb = texture2D(t1, vUv);
|
||||
vec4 Cc = texture2D(t2, vUv);
|
||||
|
||||
vec3 ctemp = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a);
|
||||
vec4 ctemp4 = vec4(ctemp, Ca.a + (1.0 - Ca.a) * Cb.a);
|
||||
|
||||
vec3 c = ctemp4.rgb + Cc.rgb * Cc.a * (1.0 - ctemp4.a);
|
||||
gl_FragColor= vec4(lift + c * light, ctemp4.a + (1.0 - ctemp4.a) * Cc.a);
|
||||
|
||||
if (gl_FragColor.a < 0.05) discard;
|
||||
}`
|
||||
|
||||
var uniforms = {
|
||||
tOne: { type: "t", value: textures[1].getMaterial().map },
|
||||
tSec: { type: "t", value: textures[0].getMaterial().map }
|
||||
SHADE: {type: 'bool', value: settings.shading.value},
|
||||
t0: {type: 't', value: null},
|
||||
t1: {type: 't', value: null},
|
||||
t2: {type: 't', value: null}
|
||||
};
|
||||
let i = 0;
|
||||
if (layers instanceof Array == false) layers = Texture.all;
|
||||
layers.forEachReverse(texture => {
|
||||
if (texture.visible && i < 3) {
|
||||
uniforms[`t${i}`].value = texture.getMaterial().map;
|
||||
i++;
|
||||
}
|
||||
})
|
||||
|
||||
var material_shh = new THREE.ShaderMaterial({
|
||||
uniforms: uniforms,
|
||||
vertexShader: vertShader,
|
||||
fragmentShader: fragShader
|
||||
fragmentShader: fragShader,
|
||||
side: Canvas.getRenderSide(),
|
||||
vertexColors: THREE.FaceColors,
|
||||
transparent: true
|
||||
});
|
||||
Canvas.layered_material = material_shh;
|
||||
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
|
||||
*/
|
||||
},
|
||||
updateLayeredTextures() {
|
||||
delete Canvas.layered_material;
|
||||
if (Format.single_texture && Texture.all.length >= 2) {
|
||||
Canvas.updateAllFaces();
|
||||
}
|
||||
},
|
||||
adaptObjectFaces(cube, mesh) {
|
||||
if (!mesh) mesh = cube.mesh
|
||||
if (!mesh) return;
|
||||
if (Prop.wireframe) {
|
||||
mesh.material = Canvas.wireframeMaterial
|
||||
/*} else if (settings.layered_textures.value && Format && Format.id.includes('bedrock')) {
|
||||
mesh.material = Canvas.getLayeredMaterial();*/
|
||||
} else if (Format.single_texture && Project.layered_textures && Texture.all.length >= 2) {
|
||||
mesh.material = Canvas.getLayeredMaterial();
|
||||
|
||||
} else {
|
||||
var materials = []
|
||||
@ -571,7 +632,7 @@ const Canvas = {
|
||||
mesh.material = materials
|
||||
}
|
||||
},
|
||||
updateUV(obj, animation) {
|
||||
updateUV(obj, animation = true) {
|
||||
if (Prop.wireframe === true) return;
|
||||
var mesh = obj.mesh
|
||||
if (mesh === undefined) return;
|
||||
@ -848,7 +909,8 @@ const Canvas = {
|
||||
var height = end[1]-start[1];
|
||||
var step = Math.abs( height / uv_size[1] );
|
||||
uv_offset[1] *= step;
|
||||
if (texture) step *= Project.texture_height / texture.height;
|
||||
let tex_height = texture.frameCount ? (texture.height / texture.frameCount) : texture.height;
|
||||
if (texture) step *= Project.texture_height / tex_height;
|
||||
if (step < epsilon) step = epsilon;
|
||||
|
||||
for (var line = start[1] - uv_offset[1]; line <= end[1]; line += step) {
|
||||
@ -875,5 +937,41 @@ const Canvas = {
|
||||
lines.no_export = true;
|
||||
|
||||
return lines;
|
||||
},
|
||||
updatePaintingGrid() {
|
||||
Cube.all.forEach(cube => {
|
||||
Canvas.buildGridBox(cube)
|
||||
})
|
||||
},
|
||||
|
||||
getModelSize() {
|
||||
var visible_box = new THREE.Box3()
|
||||
Canvas.withoutGizmos(() => {
|
||||
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 = radius*2
|
||||
let height = Math.abs(visible_box.max.y - visible_box.min.y)
|
||||
if (height === Infinity) height = 0;
|
||||
|
||||
return [width, height]
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
var scene, main_preview, previews,
|
||||
var scene,
|
||||
main_preview, MediaPreview,
|
||||
Sun, lights,
|
||||
emptyMaterials,
|
||||
outlines,
|
||||
@ -114,9 +115,20 @@ class Preview {
|
||||
//Node
|
||||
this.canvas = document.createElement('canvas')
|
||||
this.canvas.preview = this;
|
||||
this.canvas.className = 'preview';
|
||||
this.height = 0;
|
||||
this.width = 0;
|
||||
this.node = document.createElement('div')
|
||||
this.node.className = 'preview';
|
||||
this.node.appendChild(this.canvas);
|
||||
let menu = $(`<div class="tool preview_menu"> <i class="material-icons">more_vert</i> </div>`)[0]
|
||||
menu.onclick = (event) => {
|
||||
this.menu.open(menu, this)
|
||||
}
|
||||
BarItem.prototype.addLabel(false, {
|
||||
name: tl('data.preview'),
|
||||
node: menu
|
||||
})
|
||||
this.node.appendChild(menu)
|
||||
//Cameras
|
||||
this.isOrtho = false
|
||||
this.angle = null;
|
||||
@ -228,21 +240,23 @@ class Preview {
|
||||
}
|
||||
scope.loadBackground()
|
||||
})
|
||||
|
||||
previews.push(this)
|
||||
Preview.all.push(this);
|
||||
}
|
||||
//Render
|
||||
resize() {
|
||||
if (!this.canvas.isConnected) return;
|
||||
this.height = this.canvas.parentElement.clientHeight;
|
||||
this.width = this.canvas.parentElement.clientWidth;
|
||||
resize(width, height) {
|
||||
if (this.canvas.isConnected && this !== MediaPreview) {
|
||||
this.height = this.node.parentElement.clientHeight;
|
||||
this.width = this.node.parentElement.clientWidth;
|
||||
} else if (height && width) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.isOrtho === false) {
|
||||
this.camPers.aspect = this.width / this.height
|
||||
this.camPers.updateProjectionMatrix();
|
||||
if (Transformer) {
|
||||
Transformer.update()
|
||||
}
|
||||
} else {
|
||||
this.camOrtho.right = this.width / 80
|
||||
this.camOrtho.left = this.camOrtho.right*-1
|
||||
@ -251,8 +265,14 @@ class Preview {
|
||||
this.camOrtho.updateProjectionMatrix();
|
||||
}
|
||||
this.renderer.setSize(this.width, this.height);
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.updateBackground()
|
||||
|
||||
if (this.canvas.isConnected) {
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.updateBackground()
|
||||
if (Transformer) {
|
||||
Transformer.update()
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
raycast(event) {
|
||||
@ -322,7 +342,6 @@ class Preview {
|
||||
}
|
||||
}
|
||||
render() {
|
||||
if (this.canvas.isConnected === false) return;
|
||||
this.controls.update()
|
||||
this.renderer.render(
|
||||
display_mode
|
||||
@ -346,10 +365,6 @@ class Preview {
|
||||
this.camera.zoom = 0.5;
|
||||
this.camOrtho.updateProjectionMatrix()
|
||||
}
|
||||
if (Transformer && Transformer.camera !== this.camera) {
|
||||
Transformer.camera = this.camera;
|
||||
Transformer.update();
|
||||
}
|
||||
this.setLockedAngle()
|
||||
this.controls.updateSceneScale();
|
||||
return this;
|
||||
@ -365,36 +380,29 @@ class Preview {
|
||||
this.angle = angle
|
||||
this.controls.enableRotate = false;
|
||||
|
||||
var dist = 64
|
||||
switch (angle) {
|
||||
case 0:
|
||||
this.camOrtho.axis = 'y'
|
||||
//this.camOrtho.position.set(0,dist,0)
|
||||
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'z'}]
|
||||
break;
|
||||
case 1:
|
||||
this.camOrtho.axis = 'y'
|
||||
//this.camOrtho.position.set(0,-dist,0)
|
||||
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'z'}]
|
||||
break;
|
||||
case 2:
|
||||
this.camOrtho.axis = 'z'
|
||||
//this.camOrtho.position.set(0,0,dist)
|
||||
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'y'}]
|
||||
break;
|
||||
case 3:
|
||||
this.camOrtho.axis = 'z'
|
||||
//this.camOrtho.position.set(0,0,-dist)
|
||||
this.camOrtho.backgroundHandle = [{n: true, a: 'x'}, {n: true, a: 'y'}]
|
||||
break;
|
||||
case 4:
|
||||
this.camOrtho.axis = 'x'
|
||||
//this.camOrtho.position.set(dist,0,0)
|
||||
this.camOrtho.backgroundHandle = [{n: true, a: 'z'}, {n: true, a: 'y'}]
|
||||
break;
|
||||
case 5:
|
||||
this.camOrtho.axis = 'x'
|
||||
//this.camOrtho.position.set(-dist,0,0)
|
||||
this.camOrtho.backgroundHandle = [{n: false, a: 'z'}, {n: true, a: 'y'}]
|
||||
break;
|
||||
}
|
||||
@ -602,6 +610,8 @@ class Preview {
|
||||
return scope.raycaster.ray.origin
|
||||
}
|
||||
occupyTransformer(event) {
|
||||
if (this == MediaPreview || Transformer.dragging) return this;
|
||||
|
||||
Transformer.camera = this.isOrtho ? this.camOrtho : this.camPers
|
||||
Transformer.orbit_controls = this.controls
|
||||
Transformer.setCanvas(this.canvas)
|
||||
@ -655,7 +665,7 @@ class Preview {
|
||||
};
|
||||
if (!Modes.edit) return;
|
||||
|
||||
$(this.canvas).parent().append(this.selection.box)
|
||||
$(this.node).append(this.selection.box)
|
||||
this.selection.activated = settings.canvas_unselect.value;
|
||||
this.selection.old_selected = selected.slice();
|
||||
|
||||
@ -880,10 +890,18 @@ class Preview {
|
||||
Canvas.withoutGizmos(function() {
|
||||
|
||||
scope.render()
|
||||
var dataUrl = scope.canvas.toDataURL()
|
||||
|
||||
if (options.crop == false && !options.width && !options.height) {
|
||||
var dataUrl = scope.canvas.toDataURL()
|
||||
Screencam.returnScreenshot(dataUrl, cb)
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.crop !== false && !(display_mode && display_slot === 'gui') && !options.width && !options.height) {
|
||||
let frame = new CanvasFrame(scope.canvas);
|
||||
frame.autoCrop()
|
||||
Screencam.returnScreenshot(frame.canvas.toDataURL(), cb)
|
||||
return;
|
||||
}
|
||||
|
||||
dataUrl = dataUrl.replace('data:image/png;base64,','')
|
||||
@ -922,10 +940,10 @@ class Preview {
|
||||
$('#preview').empty()
|
||||
|
||||
var wrapper = $('<div class="single_canvas_wrapper"></div>')
|
||||
wrapper.append(this.canvas)
|
||||
wrapper.append(this.node)
|
||||
$('#preview').append(wrapper)
|
||||
|
||||
previews.forEach(function(prev) {
|
||||
Preview.all.forEach(function(prev) {
|
||||
if (prev.canvas.isConnected) {
|
||||
prev.resize()
|
||||
}
|
||||
@ -992,6 +1010,7 @@ class Preview {
|
||||
]
|
||||
}},
|
||||
'_',
|
||||
'focus_on_selection',
|
||||
{icon: 'add_a_photo', name: 'menu.preview.save_angle', condition(preview) {return !preview.movingBackground && !Modes.display}, click(preview) {
|
||||
preview.newAnglePreset()
|
||||
}},
|
||||
@ -1041,25 +1060,27 @@ class Preview {
|
||||
}}
|
||||
])
|
||||
|
||||
Preview.all = [];
|
||||
|
||||
function openQuadView() {
|
||||
quad_previews.enabled = true;
|
||||
|
||||
$('#preview').empty()
|
||||
|
||||
var wrapper1 = $('<div class="quad_canvas_wrapper qcw_x qcw_y"></div>')
|
||||
wrapper1.append(quad_previews.one.canvas)
|
||||
wrapper1.append(quad_previews.one.node)
|
||||
$('#preview').append(wrapper1)
|
||||
|
||||
var wrapper2 = $('<div class="quad_canvas_wrapper qcw_y"></div>')
|
||||
wrapper2.append(quad_previews.two.canvas)
|
||||
wrapper2.append(quad_previews.two.node)
|
||||
$('#preview').append(wrapper2)
|
||||
|
||||
var wrapper3 = $('<div class="quad_canvas_wrapper qcw_x"></div>')
|
||||
wrapper3.append(quad_previews.three.canvas)
|
||||
wrapper3.append(quad_previews.three.node)
|
||||
$('#preview').append(wrapper3)
|
||||
|
||||
var wrapper4 = $('<div class="quad_canvas_wrapper"></div>')
|
||||
wrapper4.append(quad_previews.four.canvas)
|
||||
wrapper4.append(quad_previews.four.node)
|
||||
$('#preview').append(wrapper4)
|
||||
|
||||
updateInterface()
|
||||
@ -1309,8 +1330,6 @@ const Screencam = {
|
||||
|
||||
//Init/Update
|
||||
function initCanvas() {
|
||||
|
||||
previews = []
|
||||
|
||||
//Objects
|
||||
scene = new THREE.Scene();
|
||||
@ -1383,6 +1402,8 @@ function initCanvas() {
|
||||
}
|
||||
active_scene = canvas_scenes.normal
|
||||
|
||||
MediaPreview = new Preview({id: 'media'})
|
||||
|
||||
main_preview = new Preview({id: 'main'}).fullscreen()
|
||||
|
||||
//TransformControls
|
||||
@ -1400,45 +1421,45 @@ function initCanvas() {
|
||||
lights = new THREE.Object3D()
|
||||
lights.name = 'lights'
|
||||
|
||||
var light_top = new THREE.DirectionalLight();
|
||||
light_top.name = 'light_top'
|
||||
light_top.position.set(8, 100, 8)
|
||||
lights.add(light_top);
|
||||
lights.top = new THREE.DirectionalLight();
|
||||
lights.top.name = 'light_top'
|
||||
lights.top.position.set(0, 100, 0)
|
||||
lights.add(lights.top);
|
||||
|
||||
light_top.intensity = 0.45
|
||||
lights.top.intensity = 0.41
|
||||
|
||||
var light_bottom = new THREE.DirectionalLight();
|
||||
light_bottom.name = 'light_bottom'
|
||||
light_bottom.position.set(8, 100, 8)
|
||||
lights.add(light_bottom);
|
||||
lights.bottom = new THREE.DirectionalLight();
|
||||
lights.bottom.name = 'light_bottom'
|
||||
lights.bottom.position.set(0, -100, 0)
|
||||
lights.add(lights.bottom);
|
||||
|
||||
light_bottom.intensity = 0.11
|
||||
lights.bottom.intensity = -0.02
|
||||
|
||||
var light_north = new THREE.DirectionalLight();
|
||||
light_north.name = 'light_north'
|
||||
light_north.position.set(8, 8, -100)
|
||||
lights.add(light_north);
|
||||
lights.north = new THREE.DirectionalLight();
|
||||
lights.north.name = 'light_north'
|
||||
lights.north.position.set(0, 0, -100)
|
||||
lights.add(lights.north);
|
||||
|
||||
var light_south = new THREE.DirectionalLight();
|
||||
light_south.name = 'light_south'
|
||||
light_south.position.set(8, 8, 100)
|
||||
lights.add(light_south);
|
||||
lights.south = new THREE.DirectionalLight();
|
||||
lights.south.name = 'light_south'
|
||||
lights.south.position.set(0, 0, 100)
|
||||
lights.add(lights.south);
|
||||
|
||||
light_north.intensity = light_south.intensity = 0.33
|
||||
lights.north.intensity = lights.south.intensity = 0.3
|
||||
|
||||
var light_west = new THREE.DirectionalLight();
|
||||
light_west.name = 'light_west'
|
||||
light_west.position.set(-100, 8, 8)
|
||||
lights.add(light_west);
|
||||
lights.west = new THREE.DirectionalLight();
|
||||
lights.west.name = 'light_west'
|
||||
lights.west.position.set(-100, 0, 0)
|
||||
lights.add(lights.west);
|
||||
|
||||
var light_east = new THREE.DirectionalLight();
|
||||
light_east.name = 'light_east'
|
||||
light_east.position.set(100, 8, 8)
|
||||
lights.add(light_east);
|
||||
lights.east = new THREE.DirectionalLight();
|
||||
lights.east.name = 'light_east'
|
||||
lights.east.position.set(100, 0, 0)
|
||||
lights.add(lights.east);
|
||||
|
||||
light_west.intensity = light_east.intensity = 0.22
|
||||
lights.west.intensity = lights.east.intensity = 0.1
|
||||
|
||||
setShading()
|
||||
updateShading()
|
||||
|
||||
quad_previews = {
|
||||
one: new Preview({id: 'one'}).loadAnglePreset(DefaultCameraPresets[1]),
|
||||
@ -1508,8 +1529,10 @@ function initCanvas() {
|
||||
function animate() {
|
||||
TickUpdates.Run()
|
||||
requestAnimationFrame( animate );
|
||||
previews.forEach(function(prev) {
|
||||
prev.render()
|
||||
Preview.all.forEach(function(prev) {
|
||||
if (prev.canvas.isConnected) {
|
||||
prev.render()
|
||||
}
|
||||
})
|
||||
framespersecond++;
|
||||
if (display_mode === true && ground_animation === true && !Transformer.hoverAxis) {
|
||||
@ -1517,14 +1540,16 @@ function animate() {
|
||||
}
|
||||
}
|
||||
|
||||
function setShading() {
|
||||
function updateShading() {
|
||||
Canvas.updateLayeredTextures();
|
||||
scene.remove(lights)
|
||||
display_scene.remove(lights)
|
||||
Sun.intensity = settings.brightness.value/100;
|
||||
Sun.intensity = settings.brightness.value/50;
|
||||
if (settings.shading.value === true) {
|
||||
(display_mode ? display_scene : scene).add(lights)
|
||||
} else {
|
||||
Sun.intensity *= (1/0.6)
|
||||
Sun.intensity *= 0.5;
|
||||
let parent = display_mode ? display_scene : scene;
|
||||
parent.add(lights);
|
||||
lights.position.copy(parent.position).multiplyScalar(-1);
|
||||
}
|
||||
}
|
||||
function updateCubeHighlights(hover_cube, force_off) {
|
||||
@ -1533,8 +1558,13 @@ function updateCubeHighlights(hover_cube, force_off) {
|
||||
var mesh = cube.mesh;
|
||||
mesh.geometry.faces.forEach(face => {
|
||||
var b_before = face.color.b;
|
||||
if (Settings.get('highlight_cubes') && (hover_cube == cube || cube.selected) && Modes.edit && !force_off) {
|
||||
face.color.setRGB(1.3, 1.32, 1.34);
|
||||
if (
|
||||
Settings.get('highlight_cubes') &&
|
||||
((hover_cube == cube && !Transformer.dragging) || cube.selected) &&
|
||||
Modes.edit &&
|
||||
!force_off
|
||||
) {
|
||||
face.color.setRGB(1.25, 1.28, 1.3);
|
||||
} else {
|
||||
face.color.setRGB(1, 1, 1);
|
||||
}
|
||||
@ -1674,7 +1704,7 @@ function buildGrid() {
|
||||
Canvas.side_grids.x.visible = !Modes.display;
|
||||
Canvas.side_grids.x.rotation.z = Math.PI/2;
|
||||
Canvas.side_grids.x.position.y = Format.centered_grid ? 8 : 0;
|
||||
Canvas.side_grids.z.position.y = -512
|
||||
Canvas.side_grids.z.position.z = 0
|
||||
Canvas.side_grids.x.children.forEach(el => {
|
||||
el.layers.set(1)
|
||||
});
|
||||
@ -1685,7 +1715,7 @@ function buildGrid() {
|
||||
Canvas.side_grids.z.rotation.z = Math.PI/2;
|
||||
Canvas.side_grids.z.rotation.y = Math.PI/2
|
||||
Canvas.side_grids.z.position.y = Format.centered_grid ? 8 : 0;
|
||||
Canvas.side_grids.z.position.z = -512
|
||||
Canvas.side_grids.z.position.z = 0
|
||||
Canvas.side_grids.z.children.forEach(el => {
|
||||
el.layers.set(3)
|
||||
});
|
||||
@ -1820,6 +1850,17 @@ BARS.defineActions(function() {
|
||||
main_preview.toggleFullscreen()
|
||||
}
|
||||
})
|
||||
new Action('focus_on_selection', {
|
||||
icon: 'center_focus_weak',
|
||||
category: 'view',
|
||||
condition: () => !Modes.display,
|
||||
keybind: new Keybind({key: 191}),
|
||||
click: function () {
|
||||
let center = getSelectionCenter();
|
||||
if (!Format.centered_grid) center.V3_subtract(8, 8, 8)
|
||||
quad_previews.current.controls.target.fromArray(center);
|
||||
}
|
||||
})
|
||||
|
||||
new Action('toggle_camera_projection', {
|
||||
icon: 'switch_video',
|
||||
|
@ -579,7 +579,7 @@
|
||||
this.children[2].children[0].children[6].renderOrder -= 9
|
||||
this.children[2].scale.set(0.8, 0.8, 0.8)
|
||||
|
||||
|
||||
/*
|
||||
function updateLayers(obj) {
|
||||
if (obj.name.includes('X')) {
|
||||
obj.layers.set(4)
|
||||
@ -593,6 +593,7 @@
|
||||
}
|
||||
this.children[0].children[0].children.forEach(updateLayers)
|
||||
this.children[1].children[0].children.forEach(updateLayers)
|
||||
*/
|
||||
|
||||
//Vars
|
||||
var changeEvent = { type: "change" };
|
||||
@ -605,44 +606,16 @@
|
||||
|
||||
var point = new THREE.Vector3();
|
||||
var offset = new THREE.Vector3();
|
||||
|
||||
var rotation = new THREE.Vector3();
|
||||
var offsetRotation = new THREE.Vector3();
|
||||
var scale = 1;
|
||||
|
||||
var lookAtMatrix = new THREE.Matrix4();
|
||||
var eye = new THREE.Vector3();
|
||||
|
||||
var tempMatrix = new THREE.Matrix4();
|
||||
var tempVector = new THREE.Vector3();
|
||||
var tempQuaternion = new THREE.Quaternion();
|
||||
var unitX = new THREE.Vector3( 1, 0, 0 );
|
||||
var unitY = new THREE.Vector3( 0, 1, 0 );
|
||||
var unitZ = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
var quaternionXYZ = new THREE.Quaternion();
|
||||
var quaternionX = new THREE.Quaternion();
|
||||
var quaternionY = new THREE.Quaternion();
|
||||
var quaternionZ = new THREE.Quaternion();
|
||||
var quaternionE = new THREE.Quaternion();
|
||||
|
||||
var oldRotationMatrix = new THREE.Vector4()
|
||||
var oldRotationArray = []
|
||||
var parentRotationArray = []
|
||||
var oldScale = 0;
|
||||
var oldScaleTranslation = 0;
|
||||
var positionSnapOffset = new THREE.Vector3()
|
||||
var originalValue = null;
|
||||
var previousValue = 0;
|
||||
var tempScale = 1;
|
||||
|
||||
var parentRotationMatrix = new THREE.Matrix4();
|
||||
|
||||
var worldPosition = new THREE.Vector3();
|
||||
var worldRotation = new THREE.Euler();
|
||||
var worldRotationMatrix = new THREE.Matrix4();
|
||||
var camPosition = new THREE.Vector3();
|
||||
var camRotation = new THREE.Euler();
|
||||
|
||||
|
||||
this.attach = function ( object ) {
|
||||
@ -738,7 +711,7 @@
|
||||
if (scope.elements.length == 0) return;
|
||||
|
||||
if (object) {
|
||||
worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( object.matrixWorld ) );
|
||||
if (!this.dragging) worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( object.matrixWorld ) );
|
||||
if (Toolbox.selected.transformerMode === 'rotate') {
|
||||
_gizmo[ _mode ].update( worldRotation, eye );
|
||||
this.rotation.set(0, 0, 0);
|
||||
@ -777,14 +750,6 @@
|
||||
this.canvas.removeEventListener( "mousemove", onPointerHover );
|
||||
this.canvas.removeEventListener( "touchmove", onPointerHover );
|
||||
|
||||
this.canvas.removeEventListener( "mousemove", onPointerMove );
|
||||
this.canvas.removeEventListener( "touchmove", onPointerMove );
|
||||
|
||||
this.canvas.removeEventListener( "mouseup", onPointerUp );
|
||||
this.canvas.removeEventListener( "mouseout", onPointerUp );
|
||||
this.canvas.removeEventListener( "touchend", onPointerUp );
|
||||
this.canvas.removeEventListener( "touchcancel", onPointerUp );
|
||||
this.canvas.removeEventListener( "touchleave", onPointerUp );
|
||||
}
|
||||
this.canvas = canvas;
|
||||
this.canvas.addEventListener( "mousedown", onPointerDown, false );
|
||||
@ -792,15 +757,8 @@
|
||||
|
||||
this.canvas.addEventListener( "mousemove", onPointerHover, false );
|
||||
this.canvas.addEventListener( "touchmove", onPointerHover, {passive: true} );
|
||||
|
||||
|
||||
this.canvas.addEventListener( "mousemove", onPointerMove, false );
|
||||
this.canvas.addEventListener( "touchmove", onPointerMove, {passive: true} );
|
||||
|
||||
this.canvas.addEventListener( "mouseup", onPointerUp, false );
|
||||
this.canvas.addEventListener( "mouseout", onPointerUp, false );
|
||||
this.canvas.addEventListener( "touchend", onPointerUp, {passive: true} );
|
||||
this.canvas.addEventListener( "touchcancel", onPointerUp, {passive: true} );
|
||||
this.canvas.addEventListener( "touchleave", onPointerUp, {passive: true} );
|
||||
}
|
||||
this.setCanvas(domElement)
|
||||
this.simulateMouseDown = function(e) {
|
||||
@ -837,7 +795,9 @@
|
||||
this.getTransformSpace = function() {
|
||||
if (!selected.length) return;
|
||||
|
||||
let input_space = BarItems.transform_space.get()
|
||||
let input_space = Toolbox.selected == BarItems.rotate_tool ? BarItems.rotation_space.get() : BarItems.transform_space.get()
|
||||
|
||||
if (Toolbox.selected == BarItems.rotate_tool && Format.rotation_limit) return 2;
|
||||
|
||||
if (input_space == 'local' && selected[0].rotatable && Toolbox.selected.id !== 'pivot_tool') {
|
||||
let is_local = true;
|
||||
@ -913,11 +873,11 @@
|
||||
|
||||
let space = Transformer.getTransformSpace();
|
||||
//Rotation
|
||||
if (Toolbox.selected.id === 'rotate_tool') {
|
||||
Transformer.rotation_ref = rotation_object.mesh.parent;
|
||||
|
||||
} else if (space === 2 || Toolbox.selected.id == 'resize_tool') {
|
||||
if (space === 2 || Toolbox.selected.id == 'resize_tool') {
|
||||
Transformer.rotation_ref = selected[0] && selected[0].mesh;
|
||||
if (Toolbox.selected.id == 'rotate_tool' && Group.selected) {
|
||||
Transformer.rotation_ref = Group.selected.mesh;
|
||||
}
|
||||
|
||||
} else if (space instanceof Group) {
|
||||
Transformer.rotation_ref = space.mesh;
|
||||
@ -990,17 +950,17 @@
|
||||
|
||||
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
|
||||
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
|
||||
if (intersect) {
|
||||
//scope.dragging = true
|
||||
}
|
||||
|
||||
if (_dragging === true) return;
|
||||
scope.hoverAxis = null;
|
||||
|
||||
if ( intersect ) {
|
||||
scope.hoverAxis = intersect.object.name;
|
||||
/*
|
||||
if (scope.camera.axis && (scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) {
|
||||
scope.hoverAxis = null;
|
||||
}
|
||||
*/
|
||||
event.preventDefault();
|
||||
}
|
||||
if ( scope.axis !== scope.hoverAxis ) {
|
||||
@ -1010,6 +970,8 @@
|
||||
}
|
||||
}
|
||||
function onPointerDown( event ) {
|
||||
|
||||
document.addEventListener( "mouseup", onPointerUp, false );
|
||||
|
||||
if ( scope.elements.length === 0 || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
|
||||
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
|
||||
@ -1018,17 +980,21 @@
|
||||
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
|
||||
if ( intersect ) {
|
||||
scope.dragging = true
|
||||
document.addEventListener( "touchend", onPointerUp, {passive: true} );
|
||||
document.addEventListener( "touchcancel", onPointerUp, {passive: true} );
|
||||
document.addEventListener( "touchleave", onPointerUp, {passive: true} );
|
||||
|
||||
document.addEventListener( "mousemove", onPointerMove, false );
|
||||
document.addEventListener( "touchmove", onPointerMove, {passive: true} );
|
||||
|
||||
Transformer.getWorldPosition(worldPosition)
|
||||
if (scope.camera.axis && (scope.hoverAxis && scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) return;
|
||||
//if (scope.camera.axis && (scope.hoverAxis && scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
scope.dispatchEvent( mouseDownEvent );
|
||||
|
||||
scope.axis = intersect.object.name;
|
||||
scope.update();
|
||||
tempScale = 1
|
||||
oldScaleTranslation = 0;
|
||||
eye.copy( camPosition ).sub( worldPosition ).normalize();
|
||||
_gizmo[ _mode ].setActivePlane( scope.axis, eye );
|
||||
var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
|
||||
@ -1510,9 +1476,16 @@
|
||||
scope.dispatchEvent( objectChangeEvent );
|
||||
}
|
||||
function onPointerUp( event ) {
|
||||
event.preventDefault(); // Prevent MouseEvent on mobile
|
||||
//event.preventDefault(); // Prevent MouseEvent on mobile
|
||||
document.removeEventListener( "mouseup", onPointerUp );
|
||||
scope.dragging = false
|
||||
|
||||
document.removeEventListener( "mousemove", onPointerMove );
|
||||
document.removeEventListener( "touchmove", onPointerMove );
|
||||
document.removeEventListener( "touchend", onPointerUp );
|
||||
document.removeEventListener( "touchcancel", onPointerUp );
|
||||
document.removeEventListener( "touchleave", onPointerUp );
|
||||
|
||||
if ( event.button !== undefined && event.button !== 0 && event.button !== 2 ) return;
|
||||
|
||||
if ( _dragging && scope.axis !== null ) {
|
||||
|
87
js/property.js
Normal file
87
js/property.js
Normal file
@ -0,0 +1,87 @@
|
||||
class Property {
|
||||
constructor(target_class, type = 'boolean', name, options = 0) {
|
||||
if (!target_class.properties) {
|
||||
target_class.properties = {};
|
||||
}
|
||||
target_class.properties[name] = this;
|
||||
|
||||
this.class = target_class;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
|
||||
if (options.default) {
|
||||
this.default = options.default;
|
||||
} else {
|
||||
switch (this.type) {
|
||||
case 'string': this.default = ''; break;
|
||||
case 'number': this.default = 0; break;
|
||||
case 'boolean': this.default = false; break;
|
||||
case 'array': this.default = []; break;
|
||||
case 'vector': this.default = [0, 0, 0]; break;
|
||||
case 'vector2': this.default = [0, 0]; break;
|
||||
}
|
||||
}
|
||||
switch (this.type) {
|
||||
case 'string': this.isString = true; break;
|
||||
case 'number': this.isNumber = true; break;
|
||||
case 'boolean': this.isBoolean = true; break;
|
||||
case 'array': this.isArray = true; break;
|
||||
case 'vector': this.isVector = true; break;
|
||||
case 'vector2': this.isVector2 = true; break;
|
||||
}
|
||||
|
||||
if (typeof options.merge == 'function') this.merge = options.merge;
|
||||
if (typeof options.reset == 'function') this.reset = options.reset;
|
||||
if (options.condition) this.condition = options.condition;
|
||||
if (options.exposed == false) this.exposed = false;
|
||||
if (options.label) this.label = options.label;
|
||||
if (options.options) this.options = options.options;
|
||||
}
|
||||
merge(instance, data) {
|
||||
if (data[this.name] == undefined || !Condition(this.condition)) return;
|
||||
|
||||
if (this.isString) {
|
||||
Merge.string(instance, data, this.name)
|
||||
}
|
||||
else if (this.isNumber) {
|
||||
Merge.number(instance, data, this.name)
|
||||
}
|
||||
else if (this.isBoolean) {
|
||||
Merge.boolean(instance, data, this.name)
|
||||
}
|
||||
else if (this.isArray || this.isVector || this.isVector2) {
|
||||
if (data[this.name] instanceof Array) {
|
||||
if (instance[this.name] instanceof Array == false) {
|
||||
instance[this.name] = [];
|
||||
}
|
||||
instance[this.name].replace(data[this.name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
copy(instance, target) {
|
||||
if (!Condition(this.condition)) return;
|
||||
|
||||
if (this.isArray || this.isVector || this.isVector2) {
|
||||
if (instance[this.name] instanceof Array) {
|
||||
target[this.name] = instance[this.name].slice();
|
||||
}
|
||||
} else {
|
||||
target[this.name] = instance[this.name];
|
||||
}
|
||||
}
|
||||
reset(instance) {
|
||||
if (typeof this.default == 'function') {
|
||||
var dft = this.default(instance);
|
||||
} else {
|
||||
var dft = this.default;
|
||||
}
|
||||
if (this.isArray || this.isVector || this.isVector2) {
|
||||
if (instance[this.name] instanceof Array == false) {
|
||||
instance[this.name] = [];
|
||||
}
|
||||
instance[this.name].replace(dft);
|
||||
} else {
|
||||
instance[this.name] = dft;
|
||||
}
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@ function colorDistance(color1, color2) {
|
||||
onVueSetup(() => {
|
||||
ColorPanel = Interface.Panels.color = new Panel({
|
||||
id: 'color',
|
||||
icon: 'palette',
|
||||
condition: () => Modes.id === 'paint',
|
||||
toolbars: {
|
||||
picker: Toolbars.color_picker,
|
||||
|
@ -288,7 +288,7 @@ const Painter = {
|
||||
let tool = Toolbox.selected.id;
|
||||
|
||||
ctx.clip()
|
||||
if (event.touches && event.touches[0] && event.touches[0].force) {
|
||||
if (event.touches && event.touches[0] && event.touches[0].touchType == 'stylus' && event.touches[0].force) {
|
||||
|
||||
// Stylus
|
||||
var touch = event.touches[0];
|
||||
@ -361,7 +361,7 @@ const Painter = {
|
||||
for (var face in cube.faces) {
|
||||
var tag = cube.faces[face]
|
||||
ctx.beginPath();
|
||||
if (tag.texture === Painter.current.texture.uuid) {
|
||||
if (tag.getTexture() === texture) {
|
||||
var face_rect = getRectangle(
|
||||
Math.floor(tag.uv[0] * uvFactorX),
|
||||
Math.floor(tag.uv[1] * uvFactorY),
|
||||
|
@ -16,6 +16,7 @@ const TextureGenerator = {
|
||||
var dialog = new Dialog({
|
||||
id: 'add_bitmap',
|
||||
title: tl('action.create_texture'),
|
||||
width: 412,
|
||||
form: {
|
||||
name: {label: 'generic.name', value: 'texture'},
|
||||
folder: {label: 'dialog.create_texture.folder'},
|
||||
@ -28,6 +29,7 @@ const TextureGenerator = {
|
||||
var dialog2 = new Dialog({
|
||||
id: 'texture_template',
|
||||
title: tl('dialog.create_texture.template'),
|
||||
width: 412,
|
||||
form: {
|
||||
compress: {label: 'dialog.create_texture.compress', type: 'checkbox', value: true, condition: Project.box_uv},
|
||||
power: {label: 'dialog.create_texture.power', type: 'checkbox', value: true},
|
||||
@ -81,7 +83,7 @@ const TextureGenerator = {
|
||||
options.color = new tinycolor().toRgb()
|
||||
}
|
||||
if (Format.single_texture) {
|
||||
options.texture = textures[0]
|
||||
options.texture = Texture.getDefault()
|
||||
}
|
||||
var texture = new Texture({
|
||||
mode: 'bitmap',
|
||||
@ -514,7 +516,7 @@ const TextureGenerator = {
|
||||
face_list.push(this);
|
||||
}
|
||||
|
||||
var cube_array = Format.single_texture ? Cube.all : Cube.selected;
|
||||
var cube_array = (Format.single_texture ? Cube.all : Cube.selected).filter(cube => cube.visibility);
|
||||
cube_array.forEach(cube => {
|
||||
var fi = 0;
|
||||
for (var face_key in cube.faces) {
|
||||
@ -640,7 +642,7 @@ const TextureGenerator = {
|
||||
if (face.texture === undefined || face.texture === null) return false;
|
||||
texture = face.getTexture()
|
||||
} else {
|
||||
texture = textures[0];
|
||||
texture = Texture.getDefault();
|
||||
}
|
||||
if (!texture || !texture.img) return false;
|
||||
|
||||
|
@ -4,17 +4,15 @@ class Texture {
|
||||
constructor(data, uuid) {
|
||||
var scope = this;
|
||||
//Info
|
||||
this.id = '';
|
||||
this.name = 'texture'
|
||||
this.folder = '';
|
||||
this.namespace = '';
|
||||
this.path = ''
|
||||
this.particle = false
|
||||
for (var key in Texture.properties) {
|
||||
Texture.properties[key].reset(this);
|
||||
}
|
||||
//meta
|
||||
this.source = ''
|
||||
this.selected = false
|
||||
this.show_icon = true
|
||||
this.error = 0;
|
||||
this.visible = true;
|
||||
//Data
|
||||
this.img = 0;
|
||||
this.width = 0;
|
||||
@ -62,7 +60,7 @@ class Texture {
|
||||
vertexColors: THREE.FaceColors,
|
||||
map: tex,
|
||||
transparent: true,
|
||||
alphaTest: 0.2
|
||||
alphaTest: 0.05
|
||||
});
|
||||
mat.name = this.name;
|
||||
Canvas.materials[this.uuid] = mat;
|
||||
@ -145,7 +143,7 @@ class Texture {
|
||||
}
|
||||
}
|
||||
get frameCount() {
|
||||
if (this.ratio !== 1 && this.ratio !== (Project.texture_width / Project.texture_height) && 1/this.ratio % 1 === 0) {
|
||||
if (Format.animated_textures && this.ratio !== 1 && this.ratio !== (Project.texture_width / Project.texture_height) && 1/this.ratio % 1 === 0) {
|
||||
return 1/this.ratio
|
||||
}
|
||||
}
|
||||
@ -162,32 +160,27 @@ class Texture {
|
||||
}
|
||||
}
|
||||
getUndoCopy(bitmap) {
|
||||
var copy = {
|
||||
path: this.path,
|
||||
name: this.name,
|
||||
folder: this.folder,
|
||||
namespace: this.namespace,
|
||||
id: this.id,
|
||||
particle: this.particle,
|
||||
selected: this.selected,
|
||||
mode: this.mode,
|
||||
saved: this.saved,
|
||||
uuid: this.uuid,
|
||||
old_width: this.old_width,
|
||||
old_height: this.old_height
|
||||
var copy = {}
|
||||
for (var key in Texture.properties) {
|
||||
Texture.properties[key].copy(this, copy)
|
||||
}
|
||||
copy.visible = this.visible;
|
||||
copy.selected = this.selected;
|
||||
copy.mode = this.mode;
|
||||
copy.saved = this.saved;
|
||||
copy.uuid = this.uuid;
|
||||
copy.old_width = this.old_width;
|
||||
copy.old_height = this.old_height;
|
||||
if (bitmap || this.mode === 'bitmap') {
|
||||
copy.source = this.source
|
||||
}
|
||||
return copy
|
||||
}
|
||||
extend(data) {
|
||||
Merge.string(this, data, 'path')
|
||||
Merge.string(this, data, 'name')
|
||||
Merge.string(this, data, 'folder')
|
||||
Merge.string(this, data, 'namespace')
|
||||
Merge.string(this, data, 'id')
|
||||
Merge.boolean(this, data, 'particle')
|
||||
for (var key in Texture.properties) {
|
||||
Texture.properties[key].merge(this, data)
|
||||
}
|
||||
Merge.boolean(this, data, 'visible')
|
||||
Merge.string(this, data, 'mode', mode => (mode === 'bitmap' || mode === 'link'))
|
||||
Merge.boolean(this, data, 'saved')
|
||||
Merge.boolean(this, data, 'keep_size')
|
||||
@ -370,23 +363,12 @@ class Texture {
|
||||
}
|
||||
updateMaterial() {
|
||||
var scope = this;
|
||||
var img = new Image()
|
||||
try {
|
||||
img.src = scope.source
|
||||
} catch(err) {
|
||||
}
|
||||
|
||||
Canvas.materials[scope.uuid].name = this.name;
|
||||
img.onload = function() {
|
||||
Canvas.materials[scope.uuid].map.dispose()
|
||||
var tex = new THREE.Texture(img)
|
||||
img.tex = tex;
|
||||
img.tex.magFilter = THREE.NearestFilter
|
||||
img.tex.minFilter = THREE.NearestFilter
|
||||
img.tex.name = scope.name;
|
||||
img.tex.needsUpdate = true;
|
||||
Canvas.materials[scope.uuid].map.name = scope.name;
|
||||
Canvas.materials[scope.uuid].map.image.src = scope.source;
|
||||
Canvas.materials[scope.uuid].map.needsUpdate = true;
|
||||
|
||||
Canvas.materials[scope.uuid].map = tex
|
||||
}
|
||||
return this;
|
||||
}
|
||||
reopen(force) {
|
||||
@ -505,8 +487,14 @@ class Texture {
|
||||
Prop.active_panel = 'textures'
|
||||
}
|
||||
this.selected = true
|
||||
textures.selected = this
|
||||
this.scrollTo()
|
||||
Texture.selected = this;
|
||||
this.scrollTo();
|
||||
if (Project.layered_textures) {
|
||||
Canvas.updatePaintingGrid()
|
||||
} else if (Format.single_texture) {
|
||||
Canvas.updateAllFaces()
|
||||
TickUpdates.selection = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
add(undo) {
|
||||
@ -526,22 +514,10 @@ class Texture {
|
||||
loadTextureDraggable()
|
||||
|
||||
if (Format.single_texture && Cube.all.length) {
|
||||
Cube.all.forEach(function(s) {
|
||||
uv_dialog.allFaces.forEach(function(side) {
|
||||
if (s.faces[side].texture !== null) {
|
||||
s.faces[side].texture = scope.uuid;
|
||||
}
|
||||
})
|
||||
})
|
||||
Canvas.updateAllFaces()
|
||||
if (selected.length) {
|
||||
main_uv.loadData()
|
||||
}
|
||||
textures.forEach(function (t, i) {
|
||||
if (t !== scope) {
|
||||
textures.splice(i, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
TickUpdates.selection = true;
|
||||
|
||||
@ -555,7 +531,9 @@ class Texture {
|
||||
Undo.initEdit({textures: [this]})
|
||||
}
|
||||
this.stopWatcher()
|
||||
if (textures.selected == this) textures.selected = false;
|
||||
if (Texture.selected == this) {
|
||||
Texture.selected = undefined;
|
||||
}
|
||||
textures.splice(textures.indexOf(this), 1)
|
||||
if (!no_update) {
|
||||
Canvas.updateAllFaces()
|
||||
@ -568,6 +546,23 @@ class Texture {
|
||||
Undo.finishEdit('remove_textures', {textures: []})
|
||||
}
|
||||
}
|
||||
toggleVisibility() {
|
||||
if (!Project.layered_textures) {
|
||||
this.visible = true;
|
||||
return this;
|
||||
}
|
||||
this.visible = !this.visible;
|
||||
let c = 0;
|
||||
Texture.all.forEach(tex => {
|
||||
if (tex.visible) {
|
||||
c++;
|
||||
if (c >= 3 && tex !== this) {
|
||||
tex.visible = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
Canvas.updateLayeredTextures();
|
||||
}
|
||||
//Use
|
||||
enableParticle() {
|
||||
textures.forEach(function(s) {
|
||||
@ -669,7 +664,7 @@ class Texture {
|
||||
lines: [
|
||||
`<div style="height: 140px;">
|
||||
<div id="texture_menu_thumbnail">${scope.img.outerHTML}</div>
|
||||
<p class="multiline_text" id="te_path">${path}</p>
|
||||
<p class="multiline_text" id="te_path">${settings.streamer_mode.value ? `[${tl('generic.redacted')}]` : path}</p>
|
||||
</div>`
|
||||
],
|
||||
form: {
|
||||
@ -998,6 +993,29 @@ class Texture {
|
||||
}
|
||||
])
|
||||
Texture.all = textures;
|
||||
Texture.getDefault = function() {
|
||||
if (Texture.selected && Texture.all.includes(Texture.selected)) {
|
||||
return Texture.selected;
|
||||
} else if (Texture.selected) {
|
||||
Texture.selected = undefined;
|
||||
}
|
||||
if (Project.layered_textures && Texture.all.length > 1) {
|
||||
var i = 0;
|
||||
for (var i = Texture.all.length-1; i >= 0; i--) {
|
||||
if (Texture.all[i].visible) {
|
||||
return Texture.all[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return Texture.all[0]
|
||||
}
|
||||
new Property(Texture, 'string', 'path')
|
||||
new Property(Texture, 'string', 'name')
|
||||
new Property(Texture, 'string', 'folder')
|
||||
new Property(Texture, 'string', 'namespace')
|
||||
new Property(Texture, 'string', 'id')
|
||||
new Property(Texture, 'boolean', 'particle')
|
||||
|
||||
|
||||
function saveTextures() {
|
||||
textures.forEach(function(t) {
|
||||
@ -1024,30 +1042,64 @@ function loadTextureDraggable() {
|
||||
return t.find('.texture_icon_wrapper').clone().addClass('texture_drag_helper').attr('texid', t.attr('texid'))
|
||||
},
|
||||
drag: function(event, ui) {
|
||||
|
||||
$('.outliner_node[order]').attr('order', null)
|
||||
var tar = $('#cubes_list li .drag_hover.outliner_node').deepest()
|
||||
var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
|
||||
if (element) {
|
||||
tar.attr('order', '0')
|
||||
$('.texture[order]').attr('order', null)
|
||||
if ($('#cubes_list.drag_hover').length === 0 && $('#cubes_list li .drag_hover.outliner_node').length) {
|
||||
var tar = $('#cubes_list li .drag_hover.outliner_node').last()
|
||||
var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
|
||||
if (element) {
|
||||
tar.attr('order', '0')
|
||||
}
|
||||
} else if ($('#texture_list li:hover').length) {
|
||||
let node = $('#texture_list > .texture:hover')
|
||||
if (node.length) {
|
||||
var target_tex = Texture.all.findInArray('uuid', node.attr('texid'));
|
||||
index = Texture.all.indexOf(target_tex);
|
||||
let offset = event.clientY - node[0].offsetTop;
|
||||
if (offset > 24) {
|
||||
node.attr('order', '1')
|
||||
} else {
|
||||
node.attr('order', '-1')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
setTimeout(function() {
|
||||
if ($('canvas.preview:hover').length > 0) {
|
||||
$('.texture[order]').attr('order', null)
|
||||
var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
|
||||
if (!tex) return;
|
||||
if ($('.preview:hover').length > 0) {
|
||||
var data = Canvas.raycast(event)
|
||||
if (data.cube && data.face) {
|
||||
var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
|
||||
var cubes_list = data.cube.selected ? Cube.selected : [data.cube];
|
||||
Undo.initEdit({elements: cubes_list})
|
||||
if (tex) {
|
||||
if (tex && cubes_list) {
|
||||
Undo.initEdit({elements: cubes_list})
|
||||
cubes_list.forEach(cube => {
|
||||
if (cube instanceof Cube) {
|
||||
cube.applyTexture(tex, data.shiftKey || [data.face])
|
||||
}
|
||||
})
|
||||
Undo.finishEdit('apply texture')
|
||||
}
|
||||
Undo.finishEdit('apply texture')
|
||||
}
|
||||
} else if ($('#texture_list:hover').length > 0) {
|
||||
let index = Texture.all.length-1
|
||||
let node = $('#texture_list > .texture:hover')
|
||||
if (node.length) {
|
||||
var target_tex = Texture.all.findInArray('uuid', node.attr('texid'));
|
||||
index = Texture.all.indexOf(target_tex);
|
||||
let own_index = Texture.all.indexOf(tex)
|
||||
if (own_index == index) return;
|
||||
if (own_index < index) index--;
|
||||
if (event.clientY - node[0].offsetTop > 24) index++;
|
||||
}
|
||||
Undo.initEdit({texture_order: true})
|
||||
Texture.all.remove(tex)
|
||||
Texture.all.splice(index, 0, tex)
|
||||
Canvas.updateLayeredTextures()
|
||||
Undo.finishEdit('reorder textures')
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
@ -1059,7 +1111,8 @@ function unselectTextures() {
|
||||
textures.forEach(function(s) {
|
||||
s.selected = false;
|
||||
})
|
||||
textures.selected = false
|
||||
Texture.selected = undefined;
|
||||
Canvas.updateLayeredTextures()
|
||||
}
|
||||
function getTexturesById(id) {
|
||||
if (id === undefined) return;
|
||||
@ -1089,6 +1142,17 @@ Clipbench.pasteTextures = function() {
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(textures, selected, {
|
||||
get() {
|
||||
console.warn('textures.selected is deprecated. Please use Texture.selected instead.')
|
||||
return Texture.selected;
|
||||
},
|
||||
set(tex) {
|
||||
console.warn('textures.selected is deprecated. Please use Texture.selected instead.')
|
||||
Texture.selected = tex;
|
||||
}
|
||||
})
|
||||
|
||||
TextureAnimator = {
|
||||
isPlaying: false,
|
||||
interval: false,
|
||||
@ -1166,7 +1230,9 @@ TextureAnimator = {
|
||||
onVueSetup(function() {
|
||||
texturelist = new Vue({
|
||||
el: '#texture_list',
|
||||
data: {textures}
|
||||
data: {
|
||||
textures: Texture.all
|
||||
}
|
||||
})
|
||||
texturelist._data.elements = textures
|
||||
})
|
||||
@ -1260,12 +1326,13 @@ BARS.defineActions(function() {
|
||||
icon: 'play_arrow',
|
||||
category: 'textures',
|
||||
condition: function() {
|
||||
if (!Format.animated_textures) return false;
|
||||
var i = 0;
|
||||
var show = false;
|
||||
while (i < textures.length) {
|
||||
if (textures[i].frameCount > 1) {
|
||||
show = true;
|
||||
i = textures.length
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -278,9 +278,11 @@ class UVEditor {
|
||||
})
|
||||
this.jquery.viewport.on('mousewheel', function(e) {
|
||||
let event = e.originalEvent;
|
||||
event.stopPropagation()
|
||||
|
||||
if (event.ctrlOrCmd) {
|
||||
|
||||
event.stopPropagation()
|
||||
|
||||
var n = (event.deltaY < 0) ? 0.1 : -0.1;
|
||||
n *= scope.zoom
|
||||
var number = limitNumber(scope.zoom + n, 1, scope.max_zoom)
|
||||
@ -365,19 +367,18 @@ class UVEditor {
|
||||
convertTouchEvent(event);
|
||||
var multiplier = (Project.box_uv && tex) ? tex.width/Project.texture_width : 1
|
||||
var pixel_size = scope.inner_width / tex.width
|
||||
var result = {};
|
||||
|
||||
if (Toolbox.selected.id === 'copy_paste_tool') {
|
||||
return {
|
||||
x: Math.round(event.offsetX/pixel_size*1),
|
||||
y: Math.round(event.offsetY/pixel_size*1)
|
||||
}
|
||||
result.x = Math.round(event.offsetX/pixel_size*1);
|
||||
result.y = Math.round(event.offsetY/pixel_size*1);
|
||||
} else {
|
||||
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
|
||||
return {
|
||||
x: Math.floor(event.offsetX/pixel_size*1 + offset),
|
||||
y: Math.floor(event.offsetY/pixel_size*1 + offset)
|
||||
}
|
||||
result.x = Math.floor(event.offsetX/pixel_size*1 + offset);
|
||||
result.y = Math.floor(event.offsetY/pixel_size*1 + offset);
|
||||
}
|
||||
if (tex.frameCount) result.y += (tex.height / tex.frameCount) * tex.currentFrame;
|
||||
return result;
|
||||
}
|
||||
startPaintTool(event) {
|
||||
var scope = this;
|
||||
@ -666,7 +667,7 @@ class UVEditor {
|
||||
}
|
||||
}
|
||||
getTexture() {
|
||||
if (Format.single_texture) return textures[0];
|
||||
if (Format.single_texture) return Texture.getDefault();
|
||||
return Cube.selected[0].faces[this.face].getTexture();
|
||||
}
|
||||
//Set
|
||||
@ -736,9 +737,9 @@ class UVEditor {
|
||||
}
|
||||
|
||||
if (this.zoom > 1) {
|
||||
this.jquery.viewport.css('overflow', 'scroll scroll')
|
||||
this.jquery.viewport.addClass('zoomed').css('overflow', 'scroll scroll')
|
||||
} else {
|
||||
this.jquery.viewport.css('overflow', 'hidden')
|
||||
this.jquery.viewport.removeClass('zoomed').css('overflow', 'hidden')
|
||||
}
|
||||
}
|
||||
setFace(face, update = true) {
|
||||
@ -754,9 +755,9 @@ class UVEditor {
|
||||
setToMainSlot() {
|
||||
var scope = this;
|
||||
$('.panel#uv').append(this.jquery.main)
|
||||
this.jquery.main.on('mousewheel', function(e) {
|
||||
$('.panel#uv').on('mousewheel', function(e) {
|
||||
|
||||
if (!Project.box_uv && !e.ctrlOrCmd) {
|
||||
if (!Project.box_uv && !e.ctrlOrCmd && $('#uv_panel_sides:hover, #uv_viewport:not(.zoomed):hover').length) {
|
||||
var faceIDs = {'north': 0, 'south': 1, 'west': 2, 'east': 3, 'up': 4, 'down': 5}
|
||||
var id = faceIDs[scope.face]
|
||||
event.deltaY > 0 ? id++ : id--;
|
||||
@ -903,7 +904,7 @@ class UVEditor {
|
||||
if (!face && Cube.selected.length) {
|
||||
var face = Cube.selected[0].faces[this.face];
|
||||
}
|
||||
var tex = face ? face.getTexture() : textures[0];
|
||||
var tex = face ? face.getTexture() : Texture.getDefault();
|
||||
if (!tex || typeof tex !== 'object' || (tex.error && tex.error != 2)) {
|
||||
this.img.src = '';
|
||||
this.img.style.display = 'none';
|
||||
@ -2057,7 +2058,7 @@ BARS.defineActions(function() {
|
||||
new BarSelect('uv_grid', {
|
||||
category: 'uv',
|
||||
condition: () => !Project.box_uv && Cube.selected.length,
|
||||
width: 60,
|
||||
min_width: 68,
|
||||
value: 'auto',
|
||||
options: {
|
||||
'auto': 'Pixel',
|
||||
|
168
js/transform.js
168
js/transform.js
@ -41,10 +41,11 @@ function origin2geometry() {
|
||||
Canvas.updatePositions()
|
||||
Undo.finishEdit('origin to geometry')
|
||||
}
|
||||
function getSelectionCenter() {
|
||||
function getSelectionCenter(all = false) {
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(obj => {
|
||||
let items = (selected.length == 0 || all) ? elements : selected;
|
||||
items.forEach(obj => {
|
||||
if (obj.getWorldCenter) {
|
||||
var pos = obj.getWorldCenter();
|
||||
center[0] += pos.x
|
||||
@ -52,13 +53,13 @@ function getSelectionCenter() {
|
||||
center[2] += pos.z
|
||||
}
|
||||
})
|
||||
for (var i = 0; i < 3; i++) {
|
||||
center[i] = center[i] / selected.length
|
||||
if (items.length) {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
center[i] = center[i] / items.length
|
||||
}
|
||||
}
|
||||
if (!Format.centered_grid) {
|
||||
center[0] += 8;
|
||||
center[1] += 8;
|
||||
center[2] += 8;
|
||||
center.V3_add(8, 8, 8)
|
||||
}
|
||||
return center;
|
||||
}
|
||||
@ -645,26 +646,68 @@ function getRotationInterval(event) {
|
||||
} else if (event.shiftKey && event.ctrlOrCmd) {
|
||||
return 0.25;
|
||||
} else if (event.shiftKey) {
|
||||
return 45;
|
||||
return 22.5;
|
||||
} else if (event.ctrlOrCmd) {
|
||||
return 1;
|
||||
} else {
|
||||
return 5;
|
||||
return 2.5;
|
||||
}
|
||||
}
|
||||
function getRotationObject() {
|
||||
if (Format.bone_rig && Group.selected) return Group.selected;
|
||||
if (Format.rotate_cubes && Cube.selected.length) return Cube.selected;
|
||||
}
|
||||
function rotateOnAxis(modify, axis) {
|
||||
function rotateOnAxis(modify, axis, slider) {
|
||||
var things;
|
||||
if (Format.bone_rig && Group.selected) {
|
||||
things = [Group.selected]
|
||||
} else if (Format.rotate_cubes && Cube.selected.length) {
|
||||
things = Cube.selected;
|
||||
}
|
||||
if (!things) return;
|
||||
/*
|
||||
if (Format.bone_rig && Group.selected) {
|
||||
if (!Group.selected) return;
|
||||
var value = modify(Group.selected.rotation[axis]);
|
||||
Group.selected.rotation[axis] = Math.trimDeg(value)
|
||||
Canvas.updateAllBones()
|
||||
return
|
||||
let obj = Group.selected.mesh
|
||||
|
||||
if (typeof space == 'object') {
|
||||
let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
|
||||
let rotWorldMatrix = new THREE.Matrix4();
|
||||
rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
|
||||
rotWorldMatrix.multiply(obj.matrix)
|
||||
obj.matrix.copy(rotWorldMatrix)
|
||||
obj.setRotationFromMatrix(rotWorldMatrix)
|
||||
let e = obj.rotation;
|
||||
Group.selected.rotation[0] = Math.radToDeg(e.x);
|
||||
Group.selected.rotation[1] = Math.radToDeg(e.y);
|
||||
Group.selected.rotation[2] = Math.radToDeg(e.z);
|
||||
Canvas.updateAllBones()
|
||||
|
||||
} else if (space == 0) {
|
||||
let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
|
||||
let rotWorldMatrix = new THREE.Matrix4();
|
||||
rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
|
||||
rotWorldMatrix.multiply(obj.matrixWorld)
|
||||
|
||||
let inverse = new THREE.Matrix4().getInverse(obj.parent.matrixWorld)
|
||||
rotWorldMatrix.premultiply(inverse)
|
||||
|
||||
obj.matrix.copy(rotWorldMatrix)
|
||||
obj.setRotationFromMatrix(rotWorldMatrix)
|
||||
let e = obj.rotation;
|
||||
Group.selected.rotation[0] = Math.radToDeg(e.x);
|
||||
Group.selected.rotation[1] = Math.radToDeg(e.y);
|
||||
Group.selected.rotation[2] = Math.radToDeg(e.z);
|
||||
Canvas.updateAllBones()
|
||||
|
||||
} else {
|
||||
var value = modify(Group.selected.rotation[axis]);
|
||||
Group.selected.rotation[axis] = Math.trimDeg(value)
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!Format.rotate_cubes) return;
|
||||
*/
|
||||
//Warning
|
||||
if (Format.rotation_limit && settings.dialog_rotation_limit.value) {
|
||||
var i = 0;
|
||||
@ -692,19 +735,13 @@ function rotateOnAxis(modify, axis) {
|
||||
}
|
||||
}
|
||||
var axis_letter = getAxisLetter(axis)
|
||||
var origin = Cube.selected[0].origin
|
||||
Cube.selected.forEach(function(obj, i) {
|
||||
var origin =things[0].origin
|
||||
things.forEach(function(obj, i) {
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
origin = obj.origin
|
||||
}
|
||||
})
|
||||
/*
|
||||
if (origin.allEqual(8)) {
|
||||
origin = getSelectionCenter()
|
||||
origin.forEach((n, ni) => {
|
||||
origin[ni] = Math.round(n*2)/2
|
||||
})
|
||||
}*/
|
||||
Cube.selected.forEach(function(obj, i) {
|
||||
if (obj.rotation.allEqual(0)) {
|
||||
obj.origin.V3_set(origin)
|
||||
@ -729,13 +766,77 @@ function rotateOnAxis(modify, axis) {
|
||||
obj.rotation[axis] = obj_val
|
||||
obj.rotation_axis = axis_letter
|
||||
})
|
||||
*/
|
||||
let space = Transformer.getTransformSpace()
|
||||
things.forEach(obj => {
|
||||
let mesh = obj.mesh;
|
||||
if (obj instanceof Cube) {
|
||||
if (obj.rotation.allEqual(0)) {
|
||||
obj.origin.V3_set(origin)
|
||||
}
|
||||
}
|
||||
|
||||
if (slider || space == 2) {
|
||||
var obj_val = modify(obj.rotation[axis]);
|
||||
obj_val = Math.trimDeg(obj_val)
|
||||
if (Format.rotation_limit) {
|
||||
//Limit To 1 Axis
|
||||
obj.rotation[(axis+1)%3] = 0
|
||||
obj.rotation[(axis+2)%3] = 0
|
||||
//Limit Angle
|
||||
obj_val = Math.round(obj_val/22.5)*22.5
|
||||
if (obj_val > 45 || obj_val < -45) {
|
||||
|
||||
let f = obj_val > 45
|
||||
obj.roll(axis, f!=(axis==1) ? 1 : 3)
|
||||
obj_val = f ? -22.5 : 22.5;
|
||||
}
|
||||
}
|
||||
obj.rotation[axis] = obj_val
|
||||
if (obj instanceof Cube) {
|
||||
obj.rotation_axis = axis_letter
|
||||
}
|
||||
|
||||
} else if (space instanceof Group) {
|
||||
let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
|
||||
let rotWorldMatrix = new THREE.Matrix4();
|
||||
rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
|
||||
rotWorldMatrix.multiply(mesh.matrix)
|
||||
mesh.matrix.copy(rotWorldMatrix)
|
||||
mesh.setRotationFromMatrix(rotWorldMatrix)
|
||||
let e = mesh.rotation;
|
||||
obj.rotation[0] = Math.radToDeg(e.x);
|
||||
obj.rotation[1] = Math.radToDeg(e.y);
|
||||
obj.rotation[2] = Math.radToDeg(e.z);
|
||||
|
||||
} else if (space == 0) {
|
||||
let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
|
||||
let rotWorldMatrix = new THREE.Matrix4();
|
||||
rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
|
||||
rotWorldMatrix.multiply(mesh.matrixWorld)
|
||||
|
||||
let inverse = new THREE.Matrix4().getInverse(mesh.parent.matrixWorld)
|
||||
rotWorldMatrix.premultiply(inverse)
|
||||
|
||||
mesh.matrix.copy(rotWorldMatrix)
|
||||
mesh.setRotationFromMatrix(rotWorldMatrix)
|
||||
let e = mesh.rotation;
|
||||
obj.rotation[0] = Math.radToDeg(e.x);
|
||||
obj.rotation[1] = Math.radToDeg(e.y);
|
||||
obj.rotation[2] = Math.radToDeg(e.z);
|
||||
|
||||
}
|
||||
if (obj instanceof Group) {
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
|
||||
|
||||
new BarSelect('transform_space', {
|
||||
condition: () => Modes.edit,
|
||||
condition: {modes: ['edit'], tools: ['move_tool', 'pivot_tool']},
|
||||
category: 'transform',
|
||||
options: {
|
||||
global: true,
|
||||
@ -746,6 +847,19 @@ BARS.defineActions(function() {
|
||||
updateSelection();
|
||||
}
|
||||
})
|
||||
new BarSelect('rotation_space', {
|
||||
condition: {modes: ['edit'], tools: ['rotate_tool']},
|
||||
category: 'transform',
|
||||
value: 'local',
|
||||
options: {
|
||||
global: 'action.transform_space.global',
|
||||
bone: {condition: () => Format.bone_rig, name: true, name: 'action.transform_space.bone'},
|
||||
local: 'action.transform_space.local'
|
||||
},
|
||||
onChange() {
|
||||
updateSelection();
|
||||
}
|
||||
})
|
||||
let grid_locked_interval = function(event) {
|
||||
event = event||0;
|
||||
return canvasGridSize(event.shiftKey, event.ctrlOrCmd);
|
||||
@ -951,7 +1065,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
},
|
||||
change: function(modify) {
|
||||
rotateOnAxis(modify, 0)
|
||||
rotateOnAxis(modify, 0, true)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
@ -977,7 +1091,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
},
|
||||
change: function(modify) {
|
||||
rotateOnAxis(modify, 1)
|
||||
rotateOnAxis(modify, 1, true)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
@ -1003,7 +1117,7 @@ BARS.defineActions(function() {
|
||||
}
|
||||
},
|
||||
change: function(modify) {
|
||||
rotateOnAxis(modify, 2)
|
||||
rotateOnAxis(modify, 2, true)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
|
32
js/undo.js
32
js/undo.js
@ -17,9 +17,6 @@ var Undo = {
|
||||
}
|
||||
- This still causes issues, for example with different texture selections
|
||||
*/
|
||||
if (aspects.textures && aspects.textures.length == 0 && Format.single_texture && textures.length == 1) {
|
||||
aspects.textures[0] = textures[0];
|
||||
}
|
||||
Undo.current_save = new Undo.save(aspects)
|
||||
return Undo.current_save;
|
||||
},
|
||||
@ -155,15 +152,21 @@ var Undo = {
|
||||
}
|
||||
|
||||
if (aspects.group) {
|
||||
this.group = aspects.group.getChildlessCopy()
|
||||
this.group.uuid = aspects.group.uuid
|
||||
this.group = aspects.group.getChildlessCopy(true)
|
||||
}
|
||||
|
||||
if (aspects.textures) {
|
||||
this.textures = {}
|
||||
aspects.textures.forEach(function(t) {
|
||||
aspects.textures.forEach(t => {
|
||||
var tex = t.getUndoCopy(aspects.bitmap)
|
||||
scope.textures[t.uuid] = tex
|
||||
this.textures[t.uuid] = tex
|
||||
})
|
||||
}
|
||||
|
||||
if (aspects.texture_order && Texture.all.length) {
|
||||
this.texture_order = [];
|
||||
Texture.all.forEach(tex => {
|
||||
this.texture_order.push(tex.uuid);
|
||||
})
|
||||
}
|
||||
|
||||
@ -321,14 +324,25 @@ var Undo = {
|
||||
}
|
||||
for (var uuid in reference.textures) {
|
||||
if (!save.textures[uuid]) {
|
||||
var tex = Undo.getItemByUUID(textures, uuid)
|
||||
var tex = Undo.getItemByUUID(Texture.all, uuid)
|
||||
if (tex) {
|
||||
textures.splice(textures.indexOf(tex), 1)
|
||||
Texture.all.splice(Texture.all.indexOf(tex), 1)
|
||||
}
|
||||
if (Texture.selected == tex) {
|
||||
Texture.selected = textures.selected = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
Canvas.updateAllFaces()
|
||||
}
|
||||
|
||||
if (save.texture_order) {
|
||||
Texture.all.sort((a, b) => {
|
||||
return save.texture_order.indexOf(a.uuid) - save.texture_order.indexOf(b.uuid);
|
||||
})
|
||||
Canvas.updateLayeredTextures()
|
||||
}
|
||||
|
||||
if (save.settings) {
|
||||
for (var key in save.settings) {
|
||||
settings[key].value = save.settings[key]
|
||||
|
13
js/util.js
13
js/util.js
@ -29,7 +29,7 @@ const Condition = function(condition, context) {
|
||||
} else if (typeof condition === 'object') {
|
||||
if (condition.modes instanceof Array && condition.modes.includes(Modes.id) === false) return false;
|
||||
if (condition.formats instanceof Array && Format && condition.formats.includes(Format.id) === false) return false;
|
||||
if (condition.tools instanceof Array && condition.tools.includes(Toolbox.selected.id) === false) return false;
|
||||
if (condition.tools instanceof Array && window.Toolbox && condition.tools.includes(Toolbox.selected.id) === false) return false;
|
||||
|
||||
if (condition.method instanceof Function) {
|
||||
return condition.method(context);
|
||||
@ -572,6 +572,17 @@ function pathToExtension(path) {
|
||||
if (!matches || !matches.length) return '';
|
||||
return matches[0].replace('.', '').toLowerCase()
|
||||
}
|
||||
Object.defineProperty(String.prototype, 'hashCode', {
|
||||
value() {
|
||||
var hash = 0, i, chr;
|
||||
for (i = 0; i < this.length; i++) {
|
||||
chr = this.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + chr;
|
||||
hash |= 0;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
});
|
||||
|
||||
//Color
|
||||
tinycolor.prototype.toInt = function() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
(function() {
|
||||
$.getScript("lib/file_saver.js");
|
||||
$.getScript('https://rawgit.com/nodeca/pako/master/dist/pako.js', function() {
|
||||
$.getScript('https://rawgit.com/nodeca/pako/master/dist/pako.min.js', function() {
|
||||
window.zlib = pako
|
||||
})
|
||||
})()
|
||||
@ -47,6 +47,7 @@ window.onbeforeunload = function() {
|
||||
if (Prop.project_saved === false && elements.length > 0) {
|
||||
return 'Unsaved Changes';
|
||||
} else {
|
||||
Blockbench.dispatchEvent('before_closing')
|
||||
EditSession.quit()
|
||||
}
|
||||
}
|
||||
|
61
lang/de.json
61
lang/de.json
@ -47,9 +47,9 @@
|
||||
"keys.printscreen": "Drucken",
|
||||
"keys.pause": "Pause",
|
||||
"message.rotation_limit.title": "Rotationsbegrenzung",
|
||||
"message.rotation_limit.message": "Rotationen sind von Minecraft auf nur eine Achse und 22,5 Grad Abstände begrenzt. Das Drehen auf einer weiteren Achse setzt alle anderen Achsen zurück. Konvertiere das Modell in ein freies Modell, wenn du die freie Rotationen benötigst.",
|
||||
"message.rotation_limit.message": "Rotationen sind von Minecraft auf nur eine Achse und 22,5 Grad Schritte begrenzt. Das Drehen auf einer weiteren Achse setzt alle anderen Achsen zurück. Konvertiere das Modell in ein freies Modell, wenn du die freie Rotationen benötigst.",
|
||||
"message.file_not_found.title": "Datei nicht gefunden",
|
||||
"message.file_not_found.message": "Blockbench konnte die angeforderte Datei nicht finden. Überprüfe, ob die Datei lokal gespeichert ist und nicht in einer Cloud. ",
|
||||
"message.file_not_found.message": "Blockbench konnte die angeforderte Datei nicht finden. Überprüfe, ob die Datei lokal gespeichert ist und nicht in einer Cloud.",
|
||||
"message.screenshot.title": "Bildschirmfoto",
|
||||
"message.screenshot.message": "Bildschirmfoto aufgezeichnet",
|
||||
"message.screenshot.clipboard": "Zwischenablage",
|
||||
@ -84,7 +84,7 @@
|
||||
"message.image_editor.title": "Wähle ein Bildbearbeitungsprogramm",
|
||||
"message.image_editor.file": "Datei auswählen...",
|
||||
"message.image_editor.exe": "Öffne die Programmdatei eines Bildbearbeitungsprogramms",
|
||||
"message.display_skin.title": "Spleierskin",
|
||||
"message.display_skin.title": "Spielerskin",
|
||||
"message.display_skin.message": "Wähle eine Skindatei von deinem Computer oder gebe einen Spielernamen an",
|
||||
"message.display_skin.upload": "Skindatei",
|
||||
"message.display_skin.name": "Spielername",
|
||||
@ -105,7 +105,7 @@
|
||||
"dialog.project.width": "Textur-Breite",
|
||||
"dialog.project.height": "Textur-Höhe",
|
||||
"dialog.texture.title": "Textur",
|
||||
"dialog.texture.variable": "Alias",
|
||||
"dialog.texture.variable": "Variable",
|
||||
"dialog.texture.namespace": "Namensraum",
|
||||
"dialog.texture.folder": "Ordner",
|
||||
"dialog.extrude.title": "Grafik Extrudieren",
|
||||
@ -143,7 +143,7 @@
|
||||
"dialog.plugins.app_only": "Nur für die Desktopanwendung",
|
||||
"dialog.plugins.author": "von %0",
|
||||
"dialog.plugins.show_less": "Weniger anzeigen",
|
||||
"dialog.entitylist.title": "Tiermodell öffnen",
|
||||
"dialog.entitylist.title": "Objektmodell öffnen",
|
||||
"dialog.entitylist.text": "Wähle das Modell, welches du öffnen möchtest",
|
||||
"dialog.entitylist.bones": "Knochen",
|
||||
"dialog.entitylist.cubes": "Elemente",
|
||||
@ -151,17 +151,13 @@
|
||||
"dialog.create_texture.template": "Template",
|
||||
"dialog.create_texture.resolution": "Auflösung",
|
||||
"dialog.input.title": "Eingabe",
|
||||
"dialog.update.title": "Aktualisierungen",
|
||||
"dialog.update.refresh": "Neu laden",
|
||||
"dialog.update.up_to_date": "Blockbench ist aktuell!",
|
||||
"dialog.update.connecting": "Mit Server verbinden",
|
||||
"dialog.settings.settings": "Einstellungen",
|
||||
"dialog.settings.keybinds": "Tastenbelegungen",
|
||||
"dialog.settings.about": "Über",
|
||||
"layout.color.back": "Dunkler",
|
||||
"layout.color.back.desc": "Hintergründe und Eingabefelder",
|
||||
"layout.color.dark": "Dunkel",
|
||||
"layout.color.dark.desc": "Huntergrund der Vorschau",
|
||||
"layout.color.dark.desc": "Hintergrund der Vorschau",
|
||||
"layout.color.ui": "Oberfläche",
|
||||
"layout.color.ui.desc": "Haupt-Oberflächenfarbe",
|
||||
"layout.color.bright_ui": "Helle Oberfläche",
|
||||
@ -170,7 +166,7 @@
|
||||
"layout.color.button.desc": "Schaltflächen und Schalter",
|
||||
"layout.color.selected": "Auswahl",
|
||||
"layout.color.selected.desc": "Ausgewählte Objekte und Registerkarten",
|
||||
"layout.color.border": "Rahmen",
|
||||
"layout.color.border": "Grenze",
|
||||
"layout.color.border.desc": "Rahmen von Schaltflächen und anderem",
|
||||
"layout.color.accent": "Akzent",
|
||||
"layout.color.accent.desc": "Akzentfarbe für Details",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Export",
|
||||
"settings.language": "Sprache",
|
||||
"settings.language.desc": "Sprache der Benutzeroberfläche. Starte Blockbench neu, um die Änderungen wirksam zu machen.",
|
||||
"settings.show_actions": "Aktionen anzeigen",
|
||||
"settings.show_actions.desc": "Alle Aktionen in der Statusleiste anzeigen",
|
||||
"settings.backup_interval": "Abstand der Sicherheitskopien",
|
||||
"settings.backup_interval.desc": "Zeit zwischen den automatischen Sicherheitskopien in Minuten",
|
||||
"settings.origin_size": "Angelpunkt",
|
||||
@ -219,7 +213,7 @@
|
||||
"settings.base_grid": "Kleines Gitter",
|
||||
"settings.base_grid.desc": "Kleines Gitter und Achsen anzeigen",
|
||||
"settings.large_grid": "Großes Gitter",
|
||||
"settings.large_grid.desc": "3x3 Blöcke großes Gitter anzeigen",
|
||||
"settings.large_grid.desc": "16x16 Blöcke großes Gitter anzeigen",
|
||||
"settings.full_grid": "Kompletter großes Gitter",
|
||||
"settings.full_grid.desc": "Vollständiges, genaues 3x3 Blöcke Gitter anzeigen",
|
||||
"settings.large_box": "Blockrahmen",
|
||||
@ -235,7 +229,7 @@
|
||||
"settings.paint_side_restrict": "Pinsel auf Seite beschränken",
|
||||
"settings.paint_side_restrict.desc": "Beschränkt den Pinsel auf das Verändern der Seite, auf die geklickt wurde",
|
||||
"settings.autouv": "Auto UV",
|
||||
"settings.autouv.desc": "Auto UV per Standard aktivieren",
|
||||
"settings.autouv.desc": "Auto UV standardmäßig aktivieren",
|
||||
"settings.create_rename": "Neue Elemente umbenennen",
|
||||
"settings.create_rename.desc": "Beim Erstellen von Elementen oder Gruppen das Namensfeld zum Umbenennen auswählen",
|
||||
"settings.edit_size": "Gitterauflösung",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Das Blockbench-Einstellungsmenü öffnen",
|
||||
"action.plugins_window": "Plugins...",
|
||||
"action.plugins_window.desc": "Öffnet den Pluginstore",
|
||||
"action.update_window": "Aktualisierungen...",
|
||||
"action.update_window.desc": "Nach Blockbench Aktualisierungen suchen",
|
||||
"action.reset_keybindings": "Tastenbelegungen zurücksetzen",
|
||||
"action.reset_keybindings.desc": "Alle Tastenbelegungen auf die Standardwerte zurücksetzen",
|
||||
"action.reset_layout": "Layout zurücksetzen",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Texturen müssen quadratisch sein",
|
||||
"message.unsaved_texture.title": "Ungespeicherte Texturen",
|
||||
"message.unsaved_texture.message": "Alle ungespeicherten Änderungen an dieser Textur gehen dadurch verloren. Möchtest du fortfahren?",
|
||||
"dialog.update.no_connection": "Keine Internetverbindung",
|
||||
"dialog.update.latest": "Aktuelle Version",
|
||||
"dialog.update.installed": "Installierte Version",
|
||||
"dialog.update.update": "Aktualisieren",
|
||||
"action.vertex_snap_mode.move": "Verschieben",
|
||||
"action.vertex_snap_mode.scale": "Größe ändern",
|
||||
"action.open_model_folder": "Modellordner öffnen",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Für Partikel verwenden",
|
||||
"message.update_notification.title": "Ein Update ist verfügbar",
|
||||
"message.update_notification.message": "Die neue Blockbench Version \"%0\" ist verfügbar. Möchtest du diese jetzt installieren?",
|
||||
"message.update_notification.install": "Installieren",
|
||||
"message.update_notification.later": "Später",
|
||||
"message.untextured": "Diese Fläche hat keine Textur",
|
||||
"dialog.toolbar_edit.title": "Toolbar Anpassen",
|
||||
"keybindings.reset": "Zurücksetzen",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Drehung",
|
||||
"timeline.position": "Position",
|
||||
"timeline.scale": "Größe",
|
||||
"menu.timeline.add": "Keyframe hinzufügen",
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
"panel.animations": "Animationen",
|
||||
"panel.keyframe": "Keyframe",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Fügt einen Keyframe hinzu. Halte Umschalt gedrückt, um die Werte zurückzusetzen",
|
||||
"action.bring_up_all_animations.desc": "Listet alle verwendeten Animatoren in der Timeline auf",
|
||||
"timeline.timeline": "Anweisungen",
|
||||
"menu.palette.load": "Palette laden",
|
||||
"menu.palette.load.default": "Standard",
|
||||
"panel.color.picker": "Farbwähler",
|
||||
"panel.color.palette": "Palette",
|
||||
@ -1114,5 +1098,30 @@
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.double": "Inside and Outside",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
74
lang/en.json
74
lang/en.json
@ -39,6 +39,9 @@
|
||||
"generic.name": "Name",
|
||||
"generic.none": "None",
|
||||
"generic.unset": "Unset",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
|
||||
"dates.today": "Today",
|
||||
"dates.yesterday": "Yesterday",
|
||||
@ -55,8 +58,8 @@
|
||||
"mode.start.recent": "Recent",
|
||||
"mode.start.no_recents": "No recently opened models",
|
||||
|
||||
"format.free": "Free Model",
|
||||
"format.free.desc": "Model without restrictions for Unity etc.",
|
||||
"format.free": "Generic Model",
|
||||
"format.free.desc": "Model without restrictions for game engines, rendering etc.",
|
||||
"format.skin": "Skin",
|
||||
"format.skin.desc": "Edit player and entity skins",
|
||||
"format.java_block": "Java Block/Item",
|
||||
@ -116,7 +119,7 @@
|
||||
"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.",
|
||||
"message.rotation_limit.title": "Rotation Limits",
|
||||
"message.rotation_limit.message": "Rotations are limited by Minecraft to one axis and 22.5 degree increments. Rotating on a different axis will clear all rotations on the other axes. Convert the model to \"Free Model\" if you are modeling for other purposes and need free rotations.",
|
||||
"message.rotation_limit.message": "Rotations are limited by Minecraft to one axis and 22.5 degree increments. Rotating on a different axis will clear all rotations on the other axes. Convert the model to \"Generic Model\" if you are modeling for other purposes and need free rotations.",
|
||||
"message.file_not_found.title": "File Not Found",
|
||||
"message.file_not_found.message": "Blockbench could not find the requested file. Make sure it is saved locally and not in a cloud.",
|
||||
"message.recover_backup.title": "Recover Model",
|
||||
@ -165,10 +168,8 @@
|
||||
"message.square_textures": "Textures have to be square",
|
||||
"message.unsaved_texture.title": "Unsaved Texture",
|
||||
"message.unsaved_texture.message": "All unsaved changes to this texture will be lost. Do you want to proceed?",
|
||||
"message.update_notification.title": "An Update Is Available",
|
||||
"message.update_notification.message": "The new Blockbench version \"%0\" is available. Do you want to install it now?",
|
||||
"message.update_notification.install": "Install",
|
||||
"message.update_notification.later": "Later",
|
||||
"message.update_notification.title": "Could not Install Update",
|
||||
"message.update_notification.message": "A new Blockbench version is available. Please enable Automatic Updates in the settings in order to update!",
|
||||
|
||||
"message.image_editor.title": "Select an image editor",
|
||||
"message.image_editor.file": "Select File...",
|
||||
@ -232,6 +233,7 @@
|
||||
"dialog.project.openparent": "Open Parent",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.project.ao": "Ambient Occlusion",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.project.box_uv": "Box UV",
|
||||
"dialog.project.width": "Texture Width",
|
||||
"dialog.project.height": "Texture Height",
|
||||
@ -239,10 +241,13 @@
|
||||
"dialog.convert_project.title": "Convert Project",
|
||||
"dialog.convert_project.text": "Are you sure you want to convert this project? You cannot undo this step.",
|
||||
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
|
||||
"dialog.texture.title": "Texture",
|
||||
"dialog.texture.variable": "Variable",
|
||||
"dialog.texture.namespace": "Namespace",
|
||||
"dialog.texture.folder": "Folder",
|
||||
|
||||
|
||||
"dialog.resize_texture.fill": "Fill with",
|
||||
"dialog.resize_texture.fill.transparent": "Transparent",
|
||||
@ -334,15 +339,6 @@
|
||||
|
||||
"dialog.input.title": "Input",
|
||||
|
||||
"dialog.update.title": "Updates",
|
||||
"dialog.update.refresh": "Refresh",
|
||||
"dialog.update.up_to_date": "Blockbench is up to date!",
|
||||
"dialog.update.connecting": "Connecting to server",
|
||||
"dialog.update.no_connection": "No internet connection",
|
||||
"dialog.update.latest": "Latest Version",
|
||||
"dialog.update.installed": "Installed Version",
|
||||
"dialog.update.update": "Update",
|
||||
|
||||
"dialog.sketchfab_uploader.title": "Upload Sketchfab Model",
|
||||
"dialog.sketchfab_uploader.token": "API Token",
|
||||
"dialog.sketchfab_uploader.about_token": "The token is used to connect Blockbench to your Sketchfab account. You can find it on %0",
|
||||
@ -365,6 +361,7 @@
|
||||
"dialog.skin.model": "Model",
|
||||
"dialog.skin.texture": "Texture (Optional)",
|
||||
"dialog.skin.pose": "Pose",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
|
||||
"dialog.settings.settings": "Settings",
|
||||
"dialog.settings.keybinds": "Keybindings",
|
||||
@ -413,6 +410,8 @@
|
||||
"layout.css": "Custom CSS",
|
||||
|
||||
"about.version": "Version:",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"about.creator": "Creator:",
|
||||
"about.website": "Website:",
|
||||
"about.bugtracker": "Bug Tracker:",
|
||||
@ -431,19 +430,14 @@
|
||||
"settings.category.defaults": "Defaults",
|
||||
"settings.category.dialogs": "Dialogs",
|
||||
"settings.category.export": "Export",
|
||||
"settings.category.application": "Application",
|
||||
|
||||
"settings.language": "Language",
|
||||
"settings.language.desc": "Interface language. Restart Blockbench to apply changes",
|
||||
"settings.username": "Username",
|
||||
"settings.username.desc": "Username for edit sessions",
|
||||
"settings.show_actions": "Display Actions",
|
||||
"settings.show_actions.desc": "Display every action in the status bar",
|
||||
"settings.recent_projects": "Recent Model Cap",
|
||||
"settings.recent_projects.desc": "Maximum number of recent models to remember",
|
||||
"settings.backup_interval": "Backup Interval",
|
||||
"settings.backup_interval.desc": "Interval of the automatic backups in minutes",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
|
||||
"settings.origin_size": "Pivot Marker",
|
||||
"settings.origin_size.desc": "Size of the pivot point marker",
|
||||
@ -536,7 +530,7 @@
|
||||
"settings.minifiedout": "Minified Export",
|
||||
"settings.minifiedout.desc": "Write JSON file in one line",
|
||||
"settings.export_groups": "Export Groups",
|
||||
"settings.export_groups.desc": "Save groups in blockmodel files",
|
||||
"settings.export_groups.desc": "Save groups in block or item model files",
|
||||
"settings.credit": "Credit Comment",
|
||||
"settings.credit.desc": "Add a credit comment to exported files",
|
||||
"settings.sketchfab_token": "Sketchfab Token",
|
||||
@ -544,6 +538,15 @@
|
||||
"settings.default_path": "Default Path",
|
||||
"settings.default_path.desc": "Folder from where Blockbench loads default textures",
|
||||
|
||||
"settings.recent_projects": "Recent Model Cap",
|
||||
"settings.recent_projects.desc": "Maximum number of recent models to remember",
|
||||
"settings.backup_interval": "Backup Interval",
|
||||
"settings.backup_interval.desc": "Interval of the automatic backups in minutes",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
|
||||
"category.navigate": "Navigation",
|
||||
"category.tools": "Tools",
|
||||
"category.file": "File",
|
||||
@ -659,8 +662,8 @@
|
||||
"action.add_model.desc": "Add a model from a file to the current model",
|
||||
"action.extrude_texture": "Extruded Texture",
|
||||
"action.extrude_texture.desc": "Generate a model by stretching out a texture",
|
||||
"action.export_blockmodel": "Export Blockmodel",
|
||||
"action.export_blockmodel.desc": "Export a Minecraft block or item model",
|
||||
"action.export_blockmodel": "Export Block/Item Model",
|
||||
"action.export_blockmodel.desc": "Export a Minecraft Java Edition block or item model",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it",
|
||||
"action.export_bedrock": "Export Bedrock Geometry",
|
||||
@ -693,8 +696,6 @@
|
||||
"action.settings_window.desc": "Open the Blockbench settings dialog.",
|
||||
"action.plugins_window": "Plugins...",
|
||||
"action.plugins_window.desc": "Open the plugin store window",
|
||||
"action.update_window": "Updates...",
|
||||
"action.update_window.desc": "Search for Blockbench updates.",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"action.edit_session": "Edit Session...",
|
||||
@ -784,6 +785,7 @@
|
||||
"action.transform_space.global": "Global",
|
||||
"action.transform_space.bone": "Bone",
|
||||
"action.transform_space.local": "Local",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.scale": "Scale...",
|
||||
"action.scale.desc": "Scale the selected cubes",
|
||||
"action.rotate_cw": "Rotate %0 +90",
|
||||
@ -867,6 +869,8 @@
|
||||
"action.sidebar_right.desc": "Open the interface to edit elements",
|
||||
"action.load_camera_angle": "Camera Angle: %0",
|
||||
"action.load_camera_angle.desc": "Load the camera angle '%0'",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
|
||||
"action.import_texture": "Import Texture",
|
||||
"action.import_texture.desc": "Import one or more textures from your file system",
|
||||
@ -962,6 +966,8 @@
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"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",
|
||||
@ -1020,6 +1026,9 @@
|
||||
"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.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
|
||||
"menu.cube.color": "Marker Color",
|
||||
"menu.cube.texture": "Texture",
|
||||
@ -1080,15 +1089,18 @@
|
||||
"menu.toolbar.reset": "Reset",
|
||||
|
||||
"menu.animation.loop": "Loop",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"menu.animation.override": "Override",
|
||||
"menu.animation.anim_time_update": "Update Variable",
|
||||
|
||||
"menu.timeline.add": "Add Keyframe",
|
||||
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
|
||||
"web.download_app": "Download App",
|
||||
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled",
|
||||
|
||||
"cube.color.light_blue": "Light Blue",
|
||||
"cube.color.yellow": "Yellow",
|
||||
"cube.color.orange": "Orange",
|
||||
|
51
lang/es.json
51
lang/es.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Plantilla",
|
||||
"dialog.create_texture.resolution": "Resolución",
|
||||
"dialog.input.title": "Entrada",
|
||||
"dialog.update.title": "Actualizaciones",
|
||||
"dialog.update.refresh": "Reintentar",
|
||||
"dialog.update.up_to_date": "¡Blockbench está actualizado!",
|
||||
"dialog.update.connecting": "Conectando con el servidor",
|
||||
"dialog.settings.settings": "Ajustes",
|
||||
"dialog.settings.keybinds": "Atajos de Teclado",
|
||||
"dialog.settings.about": "Acerca de",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Exportar",
|
||||
"settings.language": "Lenguaje",
|
||||
"settings.language.desc": "Lenguaje de la interfaz. Reinicia Blockbench para aplicar los cambios.",
|
||||
"settings.show_actions": "Mostrar Acciones",
|
||||
"settings.show_actions.desc": "Mostrar todas las acciones en la barra de estado",
|
||||
"settings.backup_interval": "Intervalo de Backup",
|
||||
"settings.backup_interval.desc": "Intervalo de los backups automáticos en minutos",
|
||||
"settings.origin_size": "Marcador de Pivote",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Abre la ventana de ajustes de Blockbench",
|
||||
"action.plugins_window": "Plugins...",
|
||||
"action.plugins_window.desc": "Abre la ventana de la tienda de plugins",
|
||||
"action.update_window": "Actualizaciones...",
|
||||
"action.update_window.desc": "Busca actualizaciones para Blockbench",
|
||||
"action.reset_keybindings": "Resetear Atajos de Teclado",
|
||||
"action.reset_keybindings.desc": "Resetea todos los atajos de teclado a los que tiene Blockbench por defecto",
|
||||
"action.reset_layout": "Resetear Diseño",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Las texturas tienen que ser cuadradas",
|
||||
"message.unsaved_texture.title": "Textura sin guardar",
|
||||
"message.unsaved_texture.message": "Todos los cambios no guardados de esta textura serán perdidos. ¿Quieres continuar?",
|
||||
"dialog.update.no_connection": "No hay conexión a Internet",
|
||||
"dialog.update.latest": "Última version",
|
||||
"dialog.update.installed": "Versión instalada",
|
||||
"dialog.update.update": "Actualizar",
|
||||
"action.vertex_snap_mode.move": "Mover",
|
||||
"action.vertex_snap_mode.scale": "Reescalar",
|
||||
"action.open_model_folder": "Abrir la Carpeta del Modelo",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Usar para Partículas",
|
||||
"message.update_notification.title": "Una Actualización Está Disponible",
|
||||
"message.update_notification.message": "La nueva versión de Blockbench \"%0\" está disponible. ¿Quieres instalarla ahora?",
|
||||
"message.update_notification.install": "Instalar",
|
||||
"message.update_notification.later": "Después",
|
||||
"message.untextured": "La superficie no tiene una textura",
|
||||
"dialog.toolbar_edit.title": "Personalizar Barra de Herramientas",
|
||||
"keybindings.reset": "Resetear",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotación",
|
||||
"timeline.position": "Posición",
|
||||
"timeline.scale": "Escala",
|
||||
"menu.timeline.add": "Añadir Frame Clave",
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
"panel.animations": "Animaciones",
|
||||
"panel.keyframe": "Frame Clave",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Añade un frame clave automáticamente. Pulsa shift para forzar los valores por defecto",
|
||||
"action.bring_up_all_animations.desc": "Trae todos los animadores modificados a la timeline",
|
||||
"timeline.timeline": "Instrucciones",
|
||||
"menu.palette.load": "Cargar Paleta",
|
||||
"menu.palette.load.default": "Por Defecto",
|
||||
"panel.color.picker": "Seleccionador",
|
||||
"panel.color.palette": "Paleta",
|
||||
@ -1110,9 +1094,34 @@
|
||||
"switches.lock": "Bloquear",
|
||||
"camera_angle.isometric_right": "Derecha Isométrica",
|
||||
"camera_angle.isometric_left": "Izquierda Isométrica",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides": "Renderizar Lados",
|
||||
"settings.render_sides.desc": "Seleccionar qué lado de una cara es renderizado",
|
||||
"settings.render_sides.auto": "Automático",
|
||||
"settings.render_sides.front": "Exterior",
|
||||
"settings.render_sides.double": "Interior y Exterior",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
43
lang/fr.json
43
lang/fr.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Étalon",
|
||||
"dialog.create_texture.resolution": "Résolution",
|
||||
"dialog.input.title": "Entrée",
|
||||
"dialog.update.title": "Mises à jour",
|
||||
"dialog.update.refresh": "Réessayer",
|
||||
"dialog.update.up_to_date": "Blockbench est à jour !",
|
||||
"dialog.update.connecting": "Connexion au serveur en cours",
|
||||
"dialog.settings.settings": "Réglages",
|
||||
"dialog.settings.keybinds": "Raccourcis clavier",
|
||||
"dialog.settings.about": "À propos",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Exporter",
|
||||
"settings.language": "Langue",
|
||||
"settings.language.desc": "Langue de l'interface. Redémarrez Blockbench pour appliquer les modifications.",
|
||||
"settings.show_actions": "Actions d’affichage",
|
||||
"settings.show_actions.desc": "Afficher chaque action dans la barre d’état",
|
||||
"settings.backup_interval": "Intervalle de sauvegarde",
|
||||
"settings.backup_interval.desc": "Intervalle des sauvegardes automatiques en minutes",
|
||||
"settings.origin_size": "Point de pivot",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Ouvrir la boîte de dialogue des paramètres Blockbench.",
|
||||
"action.plugins_window": "Plugins…",
|
||||
"action.plugins_window.desc": "Ouvrir le plugin store",
|
||||
"action.update_window": "Mises à jour…",
|
||||
"action.update_window.desc": "Rechercher des mises à jour de Blockbench.",
|
||||
"action.reset_keybindings": "Réinitialiser les raccourcis clavier",
|
||||
"action.reset_keybindings.desc": "Réinitialiser tous les raccourcis clavier aux valeurs par défaut de Blockbench",
|
||||
"action.reset_layout": "Réinitialiser la mise en page",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Les textures doivent être carrées",
|
||||
"message.unsaved_texture.title": "Texture non sauvegardée",
|
||||
"message.unsaved_texture.message": "Toute les modification non enregistrée de cette texture sera perdue. Voulez-vous poursuivre ?",
|
||||
"dialog.update.no_connection": "Pas de connexion Internet",
|
||||
"dialog.update.latest": "Dernière version",
|
||||
"dialog.update.installed": "Version installée",
|
||||
"dialog.update.update": "Mettre à jour",
|
||||
"action.vertex_snap_mode.move": "Déplacer",
|
||||
"action.vertex_snap_mode.scale": "Redimensionner",
|
||||
"action.open_model_folder": "Ouvrir le dossier du modèle",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Texture des particules",
|
||||
"message.update_notification.title": "Une mise à jour est disponible",
|
||||
"message.update_notification.message": "La nouvelle version « %0 » de Blockbench est disponible. Voulez-vous l'installer maintenant ?",
|
||||
"message.update_notification.install": "Installer",
|
||||
"message.update_notification.later": "Plus tard",
|
||||
"message.untextured": "Cette surface n'a pas de texture",
|
||||
"dialog.toolbar_edit.title": "Personnaliser la barre d'outils",
|
||||
"keybindings.reset": "Réinitialiser",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotation",
|
||||
"timeline.position": "Position",
|
||||
"timeline.scale": "Taille",
|
||||
"menu.timeline.add": "Ajouter une image",
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
"panel.animations": "Animations",
|
||||
"panel.keyframe": "Image",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Ajouter une keyframe automatiquement. Utilisez Alt pour forcer les valeurs par défaut.",
|
||||
"action.bring_up_all_animations.desc": "Met toutes les animations modifiés dans la timeline",
|
||||
"timeline.timeline": "Instructions",
|
||||
"menu.palette.load": "Charger une palette",
|
||||
"menu.palette.load.default": "Par défaut",
|
||||
"panel.color.picker": "Sélecteur",
|
||||
"panel.color.palette": "Palette",
|
||||
@ -1114,5 +1098,30 @@
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.double": "Inside and Outside",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
229
lang/it.json
229
lang/it.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Sagoma",
|
||||
"dialog.create_texture.resolution": "Risoluzione",
|
||||
"dialog.input.title": "Input",
|
||||
"dialog.update.title": "Aggiornamenti",
|
||||
"dialog.update.refresh": "Riprova",
|
||||
"dialog.update.up_to_date": "Blockbench è aggiornato!",
|
||||
"dialog.update.connecting": "Connesione al server",
|
||||
"dialog.settings.settings": "Impostazioni",
|
||||
"dialog.settings.keybinds": "Tasti",
|
||||
"dialog.settings.about": "Sul Programma",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Esporta",
|
||||
"settings.language": "Lingua",
|
||||
"settings.language.desc": "Lingua Interfaccia. Apri di nuovo Blockbench per applicare modifiche.",
|
||||
"settings.show_actions": "Mostra Azioni",
|
||||
"settings.show_actions.desc": "Mostrare ogni azione nella barra stato",
|
||||
"settings.backup_interval": "Intervallo Backup",
|
||||
"settings.backup_interval.desc": "Intervallo del backup automatico in minuti",
|
||||
"settings.origin_size": "Origine di Rotazione",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Apri il dialogo delle impostazioni Blockbench",
|
||||
"action.plugins_window": "Plugin...",
|
||||
"action.plugins_window.desc": "Apri la schermata dei plugin",
|
||||
"action.update_window": "Aggiornamenti...",
|
||||
"action.update_window.desc": "Cerca aggiornamenti Blockbench.",
|
||||
"action.reset_keybindings": "Ripristina Tasti",
|
||||
"action.reset_keybindings.desc": "Ripristina tutti i tasti al predefinito di Blockbench",
|
||||
"action.reset_layout": "Ripristina Layout",
|
||||
@ -457,9 +449,9 @@
|
||||
"menu.texture.save": "Salva",
|
||||
"menu.texture.properties": "Proprietà",
|
||||
"menu.preview.background": "Sfondo",
|
||||
"menu.preview.background.load": "Caricare",
|
||||
"menu.preview.background.load": "Carica",
|
||||
"menu.preview.background.position": "Posizione",
|
||||
"menu.preview.background.lock": "Blocca Alla Videocamera",
|
||||
"menu.preview.background.lock": "Attacca Alla Videocamera",
|
||||
"menu.preview.screenshot": "Screenshot",
|
||||
"menu.preview.perspective": "Prospettiva",
|
||||
"menu.preview.perspective.normal": "Normale",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Le texture devono essere quadrate",
|
||||
"message.unsaved_texture.title": "Texture Non Salvata",
|
||||
"message.unsaved_texture.message": "Tutte le modifiche non salvate verranno perse. Vuoi procedere?",
|
||||
"dialog.update.no_connection": "Nessuna connesione Internet",
|
||||
"dialog.update.latest": "Versione più Recente",
|
||||
"dialog.update.installed": "Versione Installata",
|
||||
"dialog.update.update": "Aggiornamento",
|
||||
"action.vertex_snap_mode.move": "Muovi",
|
||||
"action.vertex_snap_mode.scale": "Scala",
|
||||
"action.open_model_folder": "Apri Cartella Modello",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Usare per Particelle",
|
||||
"message.update_notification.title": "È Disponibile un Aggiornamento",
|
||||
"message.update_notification.message": "La versione nuova \"%0\" di Blockbench è disponibile. La vuoi installare adesso?",
|
||||
"message.update_notification.install": "Installare",
|
||||
"message.update_notification.later": "Più Tardi",
|
||||
"message.untextured": "Questa superfice non ha una texture",
|
||||
"dialog.toolbar_edit.title": "Personalizza Toolbar",
|
||||
"keybindings.reset": "Resetta",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotazione",
|
||||
"timeline.position": "Posizione",
|
||||
"timeline.scale": "Scala",
|
||||
"menu.timeline.add": "Aggiungi Fotogramma",
|
||||
"menu.keyframe.quaternion": "Quaternione",
|
||||
"panel.animations": "Animazioni",
|
||||
"panel.keyframe": "Fotogramma",
|
||||
@ -720,7 +705,7 @@
|
||||
"action.action_control": "Controllo Azioni",
|
||||
"action.action_control.desc": "Cerca ed esegui ogni azione disponibile",
|
||||
"keybindings.recording": "Registrando Tasti",
|
||||
"keybindings.press": "Premi un tasto, una combinazione di tasti o clicca ovunque sullo schermo per registrare una combinzaione tasti",
|
||||
"keybindings.press": "Premi un tasto, una combinazione di tasti o clicca ovunque sullo schermo per registrare una combinzaione tasti.",
|
||||
"action.pivot_tool": "Strumento Origine",
|
||||
"action.pivot_tool.desc": "Strumento per modificare l'origine dei cubi e delle ossa",
|
||||
"action.slider_animation_speed": "Velocità Riproduzione",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Aggiungi un fotogramma automaticamente. Premi shift per forzare valori predefinti",
|
||||
"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",
|
||||
"panel.color.picker": "Picker",
|
||||
"panel.color.palette": "Tavolozza",
|
||||
@ -1007,112 +991,137 @@
|
||||
"menu.preview.background.clipboard": "Carica dagli Appunti",
|
||||
"dialog.ignore": "Ignora",
|
||||
"generic.unset": "Non settato",
|
||||
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
|
||||
"message.invalid_builtin_parent.title": "Genitore Incorporato Invalido",
|
||||
"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.element_pivot": "Origine dell'Elemento",
|
||||
"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",
|
||||
"dialog.save_angle.projection.orthographic": "Orthographic",
|
||||
"dialog.sketchfab_uploader.animations": "Animations",
|
||||
"dialog.settings.theme": "Theme",
|
||||
"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",
|
||||
"dialog.create_gif.length_mode.turntable": "Velocità Rotazione",
|
||||
"dialog.save_angle.projection": "Proiezione",
|
||||
"dialog.save_angle.projection.perspective": "Prospettiva",
|
||||
"dialog.save_angle.projection.orthographic": "Ortografica",
|
||||
"dialog.sketchfab_uploader.animations": "Animazioni",
|
||||
"dialog.settings.theme": "Tema",
|
||||
"settings.category.interface": "Interfaccia",
|
||||
"settings.preview_checkerboard": "Anteprima Scacchiera",
|
||||
"settings.preview_checkerboard.desc": "Alterna lo sfondo a scacchiera dieto l'anteprima",
|
||||
"settings.uv_checkerboard": "Scacchiera Editore UV",
|
||||
"settings.uv_checkerboard.desc": "Alterna lo sfondo a scacchiera dietro l'editore UV",
|
||||
"category.paint": "Dipingi",
|
||||
"action.fill_mode.color_connected": "Connected Colors",
|
||||
"action.fill_mode.color_connected": "Colori Connessi",
|
||||
"action.draw_shape_type": "Tipo di forma",
|
||||
"action.draw_shape_type.rectangle": "Rettangolo",
|
||||
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
|
||||
"action.draw_shape_type.ellipse": "Eclissi",
|
||||
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
|
||||
"action.draw_shape_type.rectangle_h": "Rettangolo (Vuoto)",
|
||||
"action.draw_shape_type.ellipse": "Ellisse",
|
||||
"action.draw_shape_type.ellipse_h": "Ellisse (Vuota)",
|
||||
"action.draw_shape_type.line": "Linea",
|
||||
"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.mirror_painting": "Pittura Specchiata",
|
||||
"action.mirror_painting.description": "Specchia il tratto del pennello sull'altro lato del modello",
|
||||
"action.lock_alpha": "Blocca Canale Alfa",
|
||||
"action.lock_alpha.description": "Blocca la trasparenza di tutti i pixel",
|
||||
"action.draw_shape_tool": "Disegna una forma",
|
||||
"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",
|
||||
"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",
|
||||
"action.load_camera_angle.desc": "Load the camera angle '%0'",
|
||||
"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.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.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",
|
||||
"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",
|
||||
"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 All",
|
||||
"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",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"action.draw_shape_tool.desc": "Strumento per disegnare figure semplici sulle texture",
|
||||
"action.copy_paste_tool": "Strumento Copia Incolla",
|
||||
"action.copy_paste_tool.desc": "Strumento per copiare e incollare selezioni di texture",
|
||||
"action.export_gltf": "Esporta come glTF",
|
||||
"action.export_gltf.desc": "Esporta il modello e le animzioni come un file glTF per usarlo in altre applicazioni 3D",
|
||||
"action.transform_space": "Spazio Trasformazione",
|
||||
"action.transform_space.desc": "Spazio trasformazione predefinito per tutti gli elementi e ossa",
|
||||
"action.transform_space.global": "Globale",
|
||||
"action.transform_space.bone": "Osso",
|
||||
"action.transform_space.local": "Locale",
|
||||
"action.toggle_camera_projection": "Alterna Proiezione Videocamera",
|
||||
"action.toggle_camera_projection.desc": "Alterna la proezione della videocamera tra prospettiva e ortografica",
|
||||
"action.load_camera_angle": "Angolo Videocamera: %0",
|
||||
"action.load_camera_angle.desc": "Carica l'angolo videocamera '%0'",
|
||||
"action.slider_face_tint": "Indice Tinta",
|
||||
"action.slider_face_tint.desc": "Imposta l'indice tinta della faccia corrente. -1 vuol dire non impostato.",
|
||||
"menu.help.quickstart": "Procedura Guidata D'inizio",
|
||||
"menu.help.developer": "Sviluppatore",
|
||||
"menu.help.developer.dev_tools": "Apri Dev Tools",
|
||||
"menu.help.developer.reset_storage": "Ripristino Impostazioni",
|
||||
"menu.help.developer.reset_storage.confirm": "Sei sicuro di voler ripristinare Blockbench alle impostazioni di fabbrica? Questo eliminera tutte le impostazioni, tutti i tasti personalizzati e plugin installati.",
|
||||
"menu.help.developer.cache_reload": "Ricarica Cache",
|
||||
"menu.texture.resize": "Ridimensiona...",
|
||||
"menu.preview.orthographic": "Ortografico",
|
||||
"menu.preview.save_angle": "Salva Angolo...",
|
||||
"menu.preview.angle": "Angoli",
|
||||
"menu.preview.angle.initial": "Angolo Iniziale",
|
||||
"menu.preview.angle.load": "Carica",
|
||||
"menu.preview.maximize": "Aumentare al Massimo",
|
||||
"panel.color.both": "Entrambi",
|
||||
"uv_editor.copy_selection": "Copia Selezione",
|
||||
"uv_editor.paste_selection": "Incolla Selezione",
|
||||
"uv_editor.copy_paste_tool.place": "Piazza",
|
||||
"uv_editor.copy_paste_tool.cut": "Taglia",
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Specchia Asse X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Specchia Asse Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Ruota 90 Gradi",
|
||||
"dialog.project.modded_entity_version": "Versione Esporto",
|
||||
"dialog.save_angle.position": "Posizione Videocamera",
|
||||
"dialog.save_angle.target": "Punto Focale",
|
||||
"dialog.skin.pose": "Posa",
|
||||
"layout.color.frame": "Cornice Finestra",
|
||||
"layout.color.frame.desc": "Bordi e panello titolare della finestra",
|
||||
"settings.large_grid_size": "Dimensioni Reticolato Blocco",
|
||||
"settings.large_grid_size.desc": "Dimensioni del reticolato dei blocchi",
|
||||
"action.load_plugin_from_url": "Carica Plugin da URL",
|
||||
"action.load_plugin_from_url.desc": "Carica un plugin da un server specificando un URL",
|
||||
"action.cube_counter.desc": "Mostra il numero corrente dei cubi e altri dati",
|
||||
"action.unlock_everything": "Sblocca Tutti",
|
||||
"action.unlock_everything.desc": "Sblocca tutti i gruppi ed elementi nella lista degli elementi",
|
||||
"action.load_palette": "Carica Tavolozza",
|
||||
"action.load_palette.desc": "Carica una delle tavolozze integrate",
|
||||
"action.toggle_locked": "Alterna Blocco",
|
||||
"action.toggle_locked.desc": "Alterna lo stato di blocco degli elementi selezionati",
|
||||
"action.apply_display_preset": "Applica Preset",
|
||||
"action.apply_display_preset.desc": "Applica un preset impostazioni display predefinito oppure un preset personalizzato",
|
||||
"action.apply_display_preset.here": "Applica a Questo Slot",
|
||||
"action.apply_display_preset.everywhere": "Applica a Tutti gli Slot",
|
||||
"action.resolve_keyframe_expressions": "Risolvi Fotogrammi",
|
||||
"action.resolve_keyframe_expressions.desc": "Risolve le espressioni matematiche dei fotogrammi selezionati",
|
||||
"action.fold_all_animations": "Chiudi Animazioni",
|
||||
"action.timeline_focus.used": "In Uso",
|
||||
"menu.palette.load.empty": "Vuoto",
|
||||
"switches.lock": "Blocca",
|
||||
"camera_angle.isometric_right": "Isometrico Destro",
|
||||
"camera_angle.isometric_left": "Isometrico Sinistro",
|
||||
"settings.render_sides": "Lati Rendering",
|
||||
"settings.render_sides.desc": "Seleziona il lato di una faccia che viene mostrato",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.front": "Fuori",
|
||||
"settings.render_sides.double": "Dentro e Fuori",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
93
lang/ja.json
93
lang/ja.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "テンプレート",
|
||||
"dialog.create_texture.resolution": "解像度",
|
||||
"dialog.input.title": "入力",
|
||||
"dialog.update.title": "アップデート",
|
||||
"dialog.update.refresh": "リトライ",
|
||||
"dialog.update.up_to_date": "Blockbenchは最新です!",
|
||||
"dialog.update.connecting": "サーバーにつなげる",
|
||||
"dialog.settings.settings": "設定",
|
||||
"dialog.settings.keybinds": "キー設定",
|
||||
"dialog.settings.about": "About",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "エクスポート",
|
||||
"settings.language": "言語",
|
||||
"settings.language.desc": "言語を変更します。Blockbenchを再起動して変更を適用します",
|
||||
"settings.show_actions": "アクションの表示",
|
||||
"settings.show_actions.desc": "ステータスバーにすべてのアクションを表示する",
|
||||
"settings.backup_interval": "バックアップ間隔",
|
||||
"settings.backup_interval.desc": "自動バックアップの間隔を設定します-分-",
|
||||
"settings.origin_size": "回転軸",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Blockbenchの設定",
|
||||
"action.plugins_window": "プラグイン…",
|
||||
"action.plugins_window.desc": "プラグインストアを開く",
|
||||
"action.update_window": "アップデート…",
|
||||
"action.update_window.desc": "更新の確認",
|
||||
"action.reset_keybindings": "Reset Keybindings",
|
||||
"action.reset_keybindings.desc": "すべてのキー設定をデフォルトにリセットする",
|
||||
"action.reset_layout": "Reset Layout",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "テクスチャは正方形でなければ適用出来ません",
|
||||
"message.unsaved_texture.title": "保存されてないテクスチャ",
|
||||
"message.unsaved_texture.message": "テクスチャの変更は保存されず失われます。続行しますか?",
|
||||
"dialog.update.no_connection": "インターネットに接続されていません",
|
||||
"dialog.update.latest": "最新のバージョン",
|
||||
"dialog.update.installed": "インストールされたバージョン",
|
||||
"dialog.update.update": "更新する",
|
||||
"action.vertex_snap_mode.move": "Move",
|
||||
"action.vertex_snap_mode.scale": "Scale",
|
||||
"action.open_model_folder": "モデルフォルダを開く",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "パーティクル",
|
||||
"message.update_notification.title": "アップデート",
|
||||
"message.update_notification.message": "新しいBlockbench\"%0\"が使用可能です。今すぐインストールしますか?",
|
||||
"message.update_notification.install": "インストール",
|
||||
"message.update_notification.later": "後で",
|
||||
"message.untextured": "このPCにはテクスチャがありません",
|
||||
"dialog.toolbar_edit.title": "ツールバーのカスタマイズ",
|
||||
"keybindings.reset": "リセット",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotation",
|
||||
"timeline.position": "Position",
|
||||
"timeline.scale": "Scale",
|
||||
"menu.timeline.add": "Add Keyframe",
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
"panel.animations": "Animations",
|
||||
"panel.keyframe": "Keyframe",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "キーフレームを自動的に追加します。 Shiftキーを押してデフォルト値を表示します",
|
||||
"action.bring_up_all_animations.desc": "変更されたすべてのアニメーターをタイムラインに取り込みます",
|
||||
"timeline.timeline": "取扱説明書",
|
||||
"menu.palette.load": "パレットをロード",
|
||||
"menu.palette.load.default": "デフォルト",
|
||||
"panel.color.picker": "Picker",
|
||||
"panel.color.palette": "Palette",
|
||||
@ -1081,38 +1065,63 @@
|
||||
"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°",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.project.modded_entity_version": "バージョンをエクスポート",
|
||||
"dialog.save_angle.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 All",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"dialog.save_angle.target": "焦点",
|
||||
"dialog.skin.pose": "ポーズ",
|
||||
"layout.color.frame": "フレーム",
|
||||
"layout.color.frame.desc": "ボーダーとタイトルバーのフレーム",
|
||||
"settings.large_grid_size": "ブロックグリットサイズ",
|
||||
"settings.large_grid_size.desc": "ブロックグリットのサイズを変更",
|
||||
"action.load_plugin_from_url": "URLからプラグインをロード",
|
||||
"action.load_plugin_from_url.desc": "サーバーからプラグインをロードします",
|
||||
"action.cube_counter.desc": "現在のキューブ数とその他の統計を表示します",
|
||||
"action.unlock_everything": "アンロック",
|
||||
"action.unlock_everything.desc": "アウトライナーの全てのロックを解除します",
|
||||
"action.load_palette": "パレットをロード",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.load_palette.desc": "パレットプリセットをロードします",
|
||||
"action.toggle_locked": "トグルロック",
|
||||
"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.toggle_locked.desc": "ロックするかどうかを切り替えます",
|
||||
"action.apply_display_preset": "プリセットを適用",
|
||||
"action.apply_display_preset.desc": "カスタムの表示設定プリセットを適用します",
|
||||
"action.apply_display_preset.here": "スロットに適応",
|
||||
"action.apply_display_preset.everywhere": "全てのスロットに適応します",
|
||||
"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.fold_all_animations": "すべてのアニメーターを折りたたむ",
|
||||
"action.timeline_focus.used": "使用する",
|
||||
"menu.palette.load.empty": "空白",
|
||||
"switches.lock": "ロック",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
"camera_angle.isometric_left": "Isometric Left",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"camera_angle.isometric_right": "同尺-右",
|
||||
"camera_angle.isometric_left": "同尺-左",
|
||||
"settings.render_sides": "レンダリング",
|
||||
"settings.render_sides.desc": "面をレンダリングします",
|
||||
"settings.render_sides.auto": "オート",
|
||||
"settings.render_sides.front": "アウトサイド",
|
||||
"settings.render_sides.double": "両面",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
201
lang/ko.json
201
lang/ko.json
@ -99,7 +99,7 @@
|
||||
"dialog.project.title": "프로젝트",
|
||||
"dialog.project.name": "파일 이름",
|
||||
"dialog.project.parent": "부모 모델",
|
||||
"dialog.project.geoname": "몹 지오메트리 이름",
|
||||
"dialog.project.geoname": "모델 식별자",
|
||||
"dialog.project.openparent": "부모 모델 열기",
|
||||
"dialog.project.ao": "동적 그림자",
|
||||
"dialog.project.width": "텍스쳐 가로 크기",
|
||||
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "템플릿",
|
||||
"dialog.create_texture.resolution": "텍스쳐 해상도",
|
||||
"dialog.input.title": "입력",
|
||||
"dialog.update.title": "업데이트",
|
||||
"dialog.update.refresh": "재시도",
|
||||
"dialog.update.up_to_date": "Blockbench를 업데이트하여야 합니다!",
|
||||
"dialog.update.connecting": "서버 연결 중",
|
||||
"dialog.settings.settings": "설정",
|
||||
"dialog.settings.keybinds": "키 설정",
|
||||
"dialog.settings.about": "정보",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "내보내기 설정",
|
||||
"settings.language": "언어",
|
||||
"settings.language.desc": "언어. 변경 사항을 적용하려면 Blockbench 재시작 필요",
|
||||
"settings.show_actions": "액션 표시",
|
||||
"settings.show_actions.desc": "상태 표시 줄에 있는 모든 행동 표시",
|
||||
"settings.backup_interval": "백업 주기",
|
||||
"settings.backup_interval.desc": "분당 자동 백업 주기입니다.",
|
||||
"settings.origin_size": "중점 표시",
|
||||
@ -218,10 +212,10 @@
|
||||
"settings.texture_fps.desc": "에니메이션 텍스쳐의 초당 프레임",
|
||||
"settings.base_grid": "작은 격자",
|
||||
"settings.base_grid.desc": "작은 격자를 표시합니다",
|
||||
"settings.large_grid": "중간 격자",
|
||||
"settings.large_grid.desc": "1블록 단위의 중간 격자를 표시합니다",
|
||||
"settings.full_grid": "큰 격자",
|
||||
"settings.full_grid.desc": "3x3 크기의 큰 격자를 표기합니다",
|
||||
"settings.large_grid": "블록 격자",
|
||||
"settings.large_grid.desc": "16x16 크기의 블록 격자를 표시합니다.",
|
||||
"settings.full_grid": "정확한 블록 격자",
|
||||
"settings.full_grid.desc": "픽셀의 정확한 블록 격자를 표시합니다.",
|
||||
"settings.large_box": "중간 박스",
|
||||
"settings.large_box.desc": "3x3 경계 표시",
|
||||
"settings.display_grid": "보기 모드",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Blockbench 설정 대화 상자 열기",
|
||||
"action.plugins_window": "플러그인",
|
||||
"action.plugins_window.desc": "플러그인 스토어 메뉴를 엽니다.",
|
||||
"action.update_window": "업데이트...",
|
||||
"action.update_window.desc": "Blockbench 업데이트 검색",
|
||||
"action.reset_keybindings": "조작키 초기화",
|
||||
"action.reset_keybindings.desc": "설정한 모든 단축키를 기본값으로 되돌립니다.",
|
||||
"action.reset_layout": "레이아웃 초기화",
|
||||
@ -373,7 +365,7 @@
|
||||
"action.scale": "크기 조정...",
|
||||
"action.scale.desc": "선택된 큐브 크기",
|
||||
"action.center_all": "모두 중앙으로",
|
||||
"action.center_all.desc": "선택된 큐브를 중앙으로",
|
||||
"action.center_all.desc": "선택된 큐브를 중앙으로 합니다.",
|
||||
"action.toggle_visibility": "보이기 전환",
|
||||
"action.toggle_visibility.desc": "선택된 큐브 보이기 전환",
|
||||
"action.toggle_export": "내보내기 전환",
|
||||
@ -385,7 +377,7 @@
|
||||
"action.rename": "이름 바꾸기",
|
||||
"action.rename.desc": "선택된 큐브 이름 바꾸기",
|
||||
"action.add_display_preset": "새 사전 설정",
|
||||
"action.add_display_preset.desc": "디스플레이 설정의 새 사전 설정을 추가합니다.",
|
||||
"action.add_display_preset.desc": "새로운 사전 표기 설정을 추가합니다.",
|
||||
"action.fullscreen": "전체 화면",
|
||||
"action.fullscreen.desc": "전체화면 켜기/끄기",
|
||||
"action.zoom_in": "확대",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "텍스쳐는 정사각형이어야 합니다",
|
||||
"message.unsaved_texture.title": "저장되지 않은 텍스쳐",
|
||||
"message.unsaved_texture.message": "이 텍스쳐에 대한 변경 사항은 전부 지워질 것입니다. 계속하시겠습니까?",
|
||||
"dialog.update.no_connection": "인터넷 연결 없음",
|
||||
"dialog.update.latest": "최신 버전",
|
||||
"dialog.update.installed": "설치된 버전",
|
||||
"dialog.update.update": "업데이트",
|
||||
"action.vertex_snap_mode.move": "이동",
|
||||
"action.vertex_snap_mode.scale": "크기",
|
||||
"action.open_model_folder": "모델 폴더 열기",
|
||||
@ -549,13 +537,11 @@
|
||||
"menu.texture.particle": "파티클로 사용",
|
||||
"message.update_notification.title": "업데이트가 가능합니다.",
|
||||
"message.update_notification.message": "Blockbench의 새로운 버전 \"%0\"을 사용할 수 있습니다. 지금 설치하시겠습니까?",
|
||||
"message.update_notification.install": "설치",
|
||||
"message.update_notification.later": "나중에",
|
||||
"message.untextured": "이 표면은 텍스쳐가 없습니다",
|
||||
"dialog.toolbar_edit.title": "툴바 사용자 설정",
|
||||
"keybindings.reset": "초기화",
|
||||
"keybindings.clear": "없음",
|
||||
"action.cube_counter": "현재 큐브 수 및 기타 통계량 표시",
|
||||
"action.cube_counter": "큐브 개수 세기",
|
||||
"action.uv_rotation": "UV 회전",
|
||||
"action.uv_rotation.desc": "UV 표면의 각도",
|
||||
"action.uv_grid": "UV 그리드",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "회전",
|
||||
"timeline.position": "위치",
|
||||
"timeline.scale": "크기",
|
||||
"menu.timeline.add": "키프레임 추가",
|
||||
"menu.keyframe.quaternion": "쿼터니언",
|
||||
"panel.animations": "애니메이션",
|
||||
"panel.keyframe": "키프레임",
|
||||
@ -708,7 +693,7 @@
|
||||
"menu.preview.perspective.reset": "카메라 초기화",
|
||||
"action.fill_mode": "채우기 모드",
|
||||
"action.fill_mode.face": "면",
|
||||
"action.fill_mode.color": "색상",
|
||||
"action.fill_mode.color": "색깔",
|
||||
"action.fill_mode.cube": "큐브",
|
||||
"action.toggle_mirror_uv": "UV 반전",
|
||||
"action.toggle_mirror_uv.desc": "선택한 큐브의 X축에서 UV 미러링 토글",
|
||||
@ -938,92 +923,91 @@
|
||||
"layout.css": "커스텀 CSS",
|
||||
"settings.category.paint": "칠하기",
|
||||
"settings.deactivate_size_limit": "크기 제한 비활성화",
|
||||
"settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
|
||||
"settings.deactivate_size_limit.desc": "특정 모델의 크기 제한을 제거합니다. ( 경고 : 이 설정은 오류를 발생시킬 수 있습니다! )",
|
||||
"settings.brush_opacity_modifier": "불투명 브러쉬 수정",
|
||||
"settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus",
|
||||
"settings.brush_opacity_modifier.desc": "스타일러스펜을 사용할 때 브러쉬 투명도를 설정합니다.",
|
||||
"settings.brush_size_modifier": "브러쉬 크기 조정",
|
||||
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
|
||||
"settings.brush_size_modifier.desc": "스타일러스펜을 사용할 때 브러쉬 크기를 설정합니다. ",
|
||||
"settings.brush_modifier.pressure": "압력",
|
||||
"settings.brush_modifier.tilt": "기울기",
|
||||
"category.color": "색상",
|
||||
"action.import_theme": "테마 불러오기",
|
||||
"action.export_theme": "테마 내보내기",
|
||||
"action.export_theme.desc": "Create a theme file based on the current settings",
|
||||
"action.export_theme.desc": "현재 설정을 백업 파일로 생성합니다",
|
||||
"action.reset_theme": "테마 초기화",
|
||||
"action.reset_theme.desc": "Reset to the default Blockbench theme",
|
||||
"action.reset_theme.desc": "설정 초기화",
|
||||
"action.slider_color_h": "합성 색",
|
||||
"action.slider_color_s": "Saturation",
|
||||
"action.slider_color_s": "채도",
|
||||
"action.slider_color_v": "값",
|
||||
"action.add_to_palette": "색상 견본에 추가",
|
||||
"action.add_to_palette.desc": "Add the selected color to the color palette",
|
||||
"action.add_to_palette.desc": "선택된 색깔을 팔레트에 추가합니다.",
|
||||
"action.import_palette": "색상 견본 불러오기",
|
||||
"action.import_palette.desc": ".bbpalette 색상 견본 파일 불러오기",
|
||||
"action.export_palette": "색상 견본 내보내기",
|
||||
"action.export_palette.desc": ".bbpalette 파일로 색상 견본 내보내기",
|
||||
"action.generate_palette": "색상 견본 생성",
|
||||
"action.generate_palette.desc": "텍스쳐로부터 색상 견본 생성",
|
||||
"action.sort_palette": "Sort Palette",
|
||||
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
|
||||
"action.sort_palette": "팔레트 정렬",
|
||||
"action.sort_palette.desc": "팔레트의 모든 색깔을 색깔과 밝기로 정렬",
|
||||
"action.timelapse": "타임랩스",
|
||||
"action.timelapse.desc": "Record a timelapse of your modeling process",
|
||||
"action.timelapse.desc": "모델 제작의 진행 등의 모든 행동들을 기록합니다.",
|
||||
"action.add_keyframe": "키프레임 추가",
|
||||
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
|
||||
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
|
||||
"timeline.timeline": "Instructions",
|
||||
"menu.palette.load": "색상 견본 불러오기",
|
||||
"action.add_keyframe.desc": "자동으로 키 프레임을 추가합니다. 쉬프트를 눌러 강제로 기본 값으로 합니다.",
|
||||
"action.bring_up_all_animations.desc": "설정된 모든 애니메이션들을 타임라인으로 불러옵니다.",
|
||||
"timeline.timeline": "지시",
|
||||
"menu.palette.load.default": "기본값",
|
||||
"panel.color.picker": "색 고르기",
|
||||
"panel.color.palette": "색상 견본",
|
||||
"generic.import": "불러오기",
|
||||
"settings.brush_modifier.none": "없음",
|
||||
"action.export_entity": "베드락 엔티티 내보내기",
|
||||
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
|
||||
"settings.highlight_cubes": "Highlight Cubes",
|
||||
"settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them",
|
||||
"action.export_entity.desc": "현재 제작되어있는 모델을 엔티티 모델 ( mobs.json ) 로 저장합니다.",
|
||||
"settings.highlight_cubes": "큐브 강조하기",
|
||||
"settings.highlight_cubes.desc": "큐브를 마우스로 가리킬 시 혹은 선택할 시 강조하기",
|
||||
"action.add_marker": "마커 설정",
|
||||
"action.add_marker.desc": "Set a timeline marker",
|
||||
"action.add_marker.desc": "타임라인 표시하기",
|
||||
"timeline.pre_effect_script": "스크립트",
|
||||
"format.skin": "스킨",
|
||||
"format.skin.desc": "플레이어, 엔티티 스킨 수정",
|
||||
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
|
||||
"message.sketchfab.setup_guide": "Sketchfab 에서 3D 모델을 제작하는 방법은 %0 을(를) 참고하세요.",
|
||||
"dialog.skin.title": "스킨 생성",
|
||||
"dialog.skin.model": "스킨",
|
||||
"dialog.skin.model": "스킨 모델",
|
||||
"dialog.skin.texture": "텍스쳐 (선택 사항)",
|
||||
"action.toggle_skin_layer": "스킨 레이어 스위치",
|
||||
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
|
||||
"action.gui_light": "GUI Light",
|
||||
"action.gui_light.desc": "Select the way the item is lit in the inventory",
|
||||
"action.toggle_skin_layer.desc": "스킨 모델의 모자와 옷 등의 레이어를 활성화 혹은 비활성화합니다.",
|
||||
"action.gui_light": "GUI 밝기",
|
||||
"action.gui_light.desc": "아이템이 인벤토리에서 밝혀지는 방법을 정합니다.",
|
||||
"action.gui_light.side": "옆면 빛",
|
||||
"action.gui_light.front": "앞면 빛",
|
||||
"action.move_keyframe_back": "키 프레임을 뒤로 옮기기",
|
||||
"action.move_keyframe_forth": "Move Keyframes Forth",
|
||||
"action.move_keyframe_forth": "키 프레임을 앞으로 이동",
|
||||
"menu.help": "도움",
|
||||
"menu.help.discord": "디스코드 서버",
|
||||
"menu.help.report_issue": "버그 신고",
|
||||
"menu.help.plugin_documentation": "플러그인 API 문서",
|
||||
"menu.help.search_action": "Search and Run Action",
|
||||
"menu.help.search_action": "검색 후 실행 동작",
|
||||
"menu.help.donate": "기부",
|
||||
"menu.help.about": "더보기",
|
||||
"menu.preview.background.clipboard": "클립보드에서 불러오기",
|
||||
"dialog.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.",
|
||||
"generic.unset": "설정 안함",
|
||||
"message.invalid_builtin_parent.title": "잘못된 페런트입니다.",
|
||||
"message.invalid_builtin_parent.message": "잘못된 페런트 '%0' 의 링크가 모델을 저장하기 위하여 삭제되었습니다.",
|
||||
"dialog.resize_texture.fill": "채우기",
|
||||
"dialog.resize_texture.fill.transparent": "투명",
|
||||
"dialog.resize_texture.fill.color": "색상",
|
||||
"dialog.resize_texture.fill.repeat": "Repeat",
|
||||
"dialog.resize_texture.fill.repeat": "반복",
|
||||
"dialog.resize_texture.fill.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.scale.element_pivot": "엘리먼트 중심점",
|
||||
"dialog.scale.selection_center": "중심 선택",
|
||||
"dialog.create_gif.length_mode": "길이 설정",
|
||||
"dialog.create_gif.length_mode.seconds": "초",
|
||||
"dialog.create_gif.length_mode.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.create_gif.length_mode.animation": "애니메이션 길이",
|
||||
"dialog.create_gif.length_mode.turntable": "회전가능한 회선",
|
||||
"dialog.save_angle.projection": "빛 관통",
|
||||
"dialog.save_angle.projection.perspective": "원근법",
|
||||
"dialog.save_angle.projection.orthographic": "직교",
|
||||
"dialog.sketchfab_uploader.animations": "애니메이션",
|
||||
"dialog.settings.theme": "테마",
|
||||
"settings.category.interface": "인터페이스",
|
||||
@ -1081,38 +1065,63 @@
|
||||
"uv_editor.copy_paste_tool.mirror_x": "X축으로 좌우반전",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Y축으로 좌우반전",
|
||||
"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 All",
|
||||
"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",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"dialog.project.modded_entity_version": "저장될 버전",
|
||||
"dialog.save_angle.position": "카메라 위치",
|
||||
"dialog.save_angle.target": "초점",
|
||||
"dialog.skin.pose": "포즈",
|
||||
"layout.color.frame": "프레임",
|
||||
"layout.color.frame.desc": "경계와 제목",
|
||||
"settings.large_grid_size": "블록 격자 크기",
|
||||
"settings.large_grid_size.desc": "블록 격자의 크기",
|
||||
"action.load_plugin_from_url": "URL로부터 플러그인을 불러옵니다.",
|
||||
"action.load_plugin_from_url.desc": "지정된 URL의 서버로부터 플러그인을 불러옵니다.",
|
||||
"action.cube_counter.desc": "현재 큐브 개수와 다른 정보를 표시합니다.",
|
||||
"action.unlock_everything": "모두 잠금 해제",
|
||||
"action.unlock_everything.desc": "바깥쪽의 엘리먼트 잠금 해제",
|
||||
"action.load_palette": "팔레트 불러오기",
|
||||
"action.load_palette.desc": "사전에 설정된 팔레트 설정 불러오기",
|
||||
"action.toggle_locked": "잠금 여부 설정",
|
||||
"action.toggle_locked.desc": "설정된 ",
|
||||
"action.apply_display_preset": "기본 설정 적용하기",
|
||||
"action.apply_display_preset.desc": "기본 설정 혹은 커스텀 설정 적용하기",
|
||||
"action.apply_display_preset.here": "해당 슬릇에 적용하기",
|
||||
"action.apply_display_preset.everywhere": "모든 슬릇에 적용하기",
|
||||
"action.resolve_keyframe_expressions": "키 프레임 재설정하기",
|
||||
"action.resolve_keyframe_expressions.desc": "설정된 키 프레임의 수학 값 재설정하기",
|
||||
"action.fold_all_animations": "모든 애니메이션 접기",
|
||||
"action.timeline_focus.used": "사용됨",
|
||||
"menu.palette.load.empty": "공백",
|
||||
"switches.lock": "잠금",
|
||||
"camera_angle.isometric_right": "우측 치수",
|
||||
"camera_angle.isometric_left": "좌측으로 회전",
|
||||
"settings.render_sides": "렌더 ",
|
||||
"settings.render_sides.desc": "어느 면이 렌더될지 선택",
|
||||
"settings.render_sides.auto": "자동",
|
||||
"settings.render_sides.front": "바깥",
|
||||
"settings.render_sides.double": "안쪽과 바깥",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
63
lang/nl.json
63
lang/nl.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Sjabloon",
|
||||
"dialog.create_texture.resolution": "Resolutie",
|
||||
"dialog.input.title": "Invoer",
|
||||
"dialog.update.title": "Updates",
|
||||
"dialog.update.refresh": "Opnieuw proberen",
|
||||
"dialog.update.up_to_date": "Blockbench is up-to-date",
|
||||
"dialog.update.connecting": "Verbinden met de server",
|
||||
"dialog.settings.settings": "Instellingen",
|
||||
"dialog.settings.keybinds": "Sneltoetsen",
|
||||
"dialog.settings.about": "Over",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Exporteren",
|
||||
"settings.language": "Taal",
|
||||
"settings.language.desc": "Interface taal. Herstart Blockbench om wijzigingen aan te brengen",
|
||||
"settings.show_actions": "Toon Acties",
|
||||
"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": "Draaipunt Markeerder",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Open het Blockbench instellingen venster",
|
||||
"action.plugins_window": "Plugins...",
|
||||
"action.plugins_window.desc": "Open het plugin venster",
|
||||
"action.update_window": "Updates...",
|
||||
"action.update_window.desc": "Zoek voor Blockbench updates.",
|
||||
"action.reset_keybindings": "Herstel Sneltoetsen",
|
||||
"action.reset_keybindings.desc": "Herstel alle sneltoetsen naar Blockbench's standaard",
|
||||
"action.reset_layout": "Herstel Lay-out",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Texturen moeten vierkant zijn",
|
||||
"message.unsaved_texture.title": "Niet Opgeslagen Textuur",
|
||||
"message.unsaved_texture.message": "Alle niet opgeslagen veranderingen van deze textuur zullen verloren gaan. Wil je doorgaan?",
|
||||
"dialog.update.no_connection": "Geen internet connectie",
|
||||
"dialog.update.latest": "Laatste Versie",
|
||||
"dialog.update.installed": "Geïnstalleerde Versie",
|
||||
"dialog.update.update": "Update",
|
||||
"action.vertex_snap_mode.move": "Beweeg",
|
||||
"action.vertex_snap_mode.scale": "Schaal",
|
||||
"action.open_model_folder": "Open Model Map",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Gebruik voor Deeltjes",
|
||||
"message.update_notification.title": "Er is een update van Blockbench beschikbaar.",
|
||||
"message.update_notification.message": "Blockbench versie %0 is uit. Wil je deze nu installeren?",
|
||||
"message.update_notification.install": "Installeren",
|
||||
"message.update_notification.later": "Later",
|
||||
"message.untextured": "Dit oppervlak heeft geen texture.",
|
||||
"dialog.toolbar_edit.title": "Aangepast Gereedschap",
|
||||
"keybindings.reset": "Reset",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotatie",
|
||||
"timeline.position": "Positie",
|
||||
"timeline.scale": "Vergroot/Verklein",
|
||||
"menu.timeline.add": "Voeg KeyframeToe",
|
||||
"menu.keyframe.quaternion": "Quaternion",
|
||||
"panel.animations": "Animaties",
|
||||
"panel.keyframe": "Keyframe",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Voeg Automatisch een keyframe toe. Druk op shift om standaard waarden te forceren",
|
||||
"action.bring_up_all_animations.desc": "Brengt alle gemodificeerde animatoren in de tijdlijn",
|
||||
"timeline.timeline": "Instructies",
|
||||
"menu.palette.load": "Laad Palet",
|
||||
"menu.palette.load.default": "Standaard",
|
||||
"panel.color.picker": "Pipet",
|
||||
"panel.color.palette": "Palet",
|
||||
@ -1071,7 +1055,7 @@
|
||||
"menu.preview.save_angle": "Save Angle...",
|
||||
"menu.preview.angle": "Angles",
|
||||
"menu.preview.angle.initial": "Initial Angle",
|
||||
"menu.preview.angle.load": "Load",
|
||||
"menu.preview.angle.load": "Laad",
|
||||
"menu.preview.maximize": "Maximize",
|
||||
"panel.color.both": "Both",
|
||||
"uv_editor.copy_selection": "Copy Selection",
|
||||
@ -1080,22 +1064,22 @@
|
||||
"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",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.save_angle.position": "Camera Position",
|
||||
"uv_editor.copy_paste_tool.rotate": "Draai 90 graden",
|
||||
"dialog.project.modded_entity_version": "Exporteer versie",
|
||||
"dialog.save_angle.position": "Camera positie",
|
||||
"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": "Blok rastergrootte",
|
||||
"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.load_plugin_from_url": "Laad een plugin via een URL",
|
||||
"action.load_plugin_from_url.desc": "Laad een plugin van een server door de URL op te geven",
|
||||
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
|
||||
"action.unlock_everything": "Unlock All",
|
||||
"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.load_palette": "Palet laden",
|
||||
"action.load_palette.desc": "Laad een van de ingebouwde paletvoorinstellingen",
|
||||
"action.toggle_locked": "Toggle Lock",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.apply_display_preset": "Apply Preset",
|
||||
@ -1105,7 +1089,7 @@
|
||||
"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",
|
||||
"action.timeline_focus.used": "In gebruik",
|
||||
"menu.palette.load.empty": "Blank",
|
||||
"switches.lock": "Lock",
|
||||
"camera_angle.isometric_right": "Isometric Right",
|
||||
@ -1114,5 +1098,30 @@
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.double": "Inside and Outside",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
47
lang/pl.json
47
lang/pl.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Szablon",
|
||||
"dialog.create_texture.resolution": "Rozdzielczość",
|
||||
"dialog.input.title": "Wstaw",
|
||||
"dialog.update.title": "Aktualizacje",
|
||||
"dialog.update.refresh": "Odśwież",
|
||||
"dialog.update.up_to_date": "Blockbench jest aktualny!",
|
||||
"dialog.update.connecting": "Łączenie z serwerem",
|
||||
"dialog.settings.settings": "Ustawienia",
|
||||
"dialog.settings.keybinds": "Klawisze",
|
||||
"dialog.settings.about": "O programie",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Eksportuj",
|
||||
"settings.language": "Język",
|
||||
"settings.language.desc": "Język interfejsu. Otwórz Blockbench ponownie, żeby zatwierdzić zmiany.",
|
||||
"settings.show_actions": "Wyświetlaj akcje",
|
||||
"settings.show_actions.desc": "Wyświetlaj każdą akcję w pasku statusu",
|
||||
"settings.backup_interval": "Interwał kopii zapasowych",
|
||||
"settings.backup_interval.desc": "Interwał tworzenia automatycznych kopii zapasowych, w minutach",
|
||||
"settings.origin_size": "Punkt obrotu",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Otwórz okienko ustawień Blockbench",
|
||||
"action.plugins_window": "Pluginy...",
|
||||
"action.plugins_window.desc": "Otwórz okienko sklepu z pluginami",
|
||||
"action.update_window": "Aktualizacje...",
|
||||
"action.update_window.desc": "Znajdź aktualizacje dla Blockbench",
|
||||
"action.reset_keybindings": "Resetuj przypisanie klawiszy",
|
||||
"action.reset_keybindings.desc": "Resetuj wszystkie przypisania klawiszy do domyślnych",
|
||||
"action.reset_layout": "Resetuj układ",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Tekstury muszą być kwadratowe",
|
||||
"message.unsaved_texture.title": "Niezapisana tekstura",
|
||||
"message.unsaved_texture.message": "Wszystkie niezapisane zmiany tej tekstury zostaną utracone. Chcesz kontynuować?",
|
||||
"dialog.update.no_connection": "Brak łączności z internetem",
|
||||
"dialog.update.latest": "Najnowsza wersja",
|
||||
"dialog.update.installed": "Zainstalowana wersja",
|
||||
"dialog.update.update": "Aktualizacja",
|
||||
"action.vertex_snap_mode.move": "Przesuń",
|
||||
"action.vertex_snap_mode.scale": "Skaluj",
|
||||
"action.open_model_folder": "Otwórz folder modelu",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Użyj dla cząstek",
|
||||
"message.update_notification.title": "Dostępna jest aktualizacja",
|
||||
"message.update_notification.message": "Nowa wersja Blockbench \"%0\" jest dostępna. Chcesz ją teraz zainstalować?",
|
||||
"message.update_notification.install": "Zainstaluj",
|
||||
"message.update_notification.later": "Później",
|
||||
"message.untextured": "Ta powierzchnia nie ma tekstury",
|
||||
"dialog.toolbar_edit.title": "Dostosuj pasek z narzędziami",
|
||||
"keybindings.reset": "Resetuj",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotacja",
|
||||
"timeline.position": "Pozycja",
|
||||
"timeline.scale": "Rozmiar",
|
||||
"menu.timeline.add": "Dodaj klatkę kluczową",
|
||||
"menu.keyframe.quaternion": "Kwaternion",
|
||||
"panel.animations": "Animacje",
|
||||
"panel.keyframe": "Klatka kluczowa",
|
||||
@ -800,8 +785,8 @@
|
||||
"mode.start": "Start",
|
||||
"mode.start.new": "New",
|
||||
"mode.start.recent": "Recent",
|
||||
"format.free": "Free Model",
|
||||
"format.free.desc": "Model without restrictions for Unity etc.",
|
||||
"format.free": "Generic Model",
|
||||
"format.free.desc": "Model without restrictions for game engines, rendering etc.",
|
||||
"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",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Automatycznie dodawaj klatki kluczowe. Naciśnij Shift, aby wymusić podstawowe wartości",
|
||||
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
|
||||
"timeline.timeline": "Instrukcje",
|
||||
"menu.palette.load": "Wczytaj paletę",
|
||||
"menu.palette.load.default": "Podstawowa",
|
||||
"panel.color.picker": "Wybierz kolor",
|
||||
"panel.color.palette": "Paleta",
|
||||
@ -1114,5 +1098,30 @@
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.double": "Inside and Outside",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
49
lang/pt.json
49
lang/pt.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Modelo",
|
||||
"dialog.create_texture.resolution": "Resolução",
|
||||
"dialog.input.title": "Entrada",
|
||||
"dialog.update.title": "Atualizações",
|
||||
"dialog.update.refresh": "Tentar de novo",
|
||||
"dialog.update.up_to_date": "O Blockbench está atualizado!",
|
||||
"dialog.update.connecting": "Conectando-se ao servidor",
|
||||
"dialog.settings.settings": "Configurações",
|
||||
"dialog.settings.keybinds": "Atalhos",
|
||||
"dialog.settings.about": "Sobre",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Exportação",
|
||||
"settings.language": "Idioma",
|
||||
"settings.language.desc": "Idioma da interface. Reinicie o Blockbench para aplicar as alterações",
|
||||
"settings.show_actions": "Mostrar ações",
|
||||
"settings.show_actions.desc": "Mostrar todas as ações na barra de status",
|
||||
"settings.backup_interval": "Intervalo de salvamento",
|
||||
"settings.backup_interval.desc": "Intervalo entre salvamentos automáticos (em minutos)",
|
||||
"settings.origin_size": "Origem da rotação",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Abrir a janela de configurações do Blockbench.",
|
||||
"action.plugins_window": "Extensões...",
|
||||
"action.plugins_window.desc": "Abrir a janela da loja de extensões",
|
||||
"action.update_window": "Atualizações...",
|
||||
"action.update_window.desc": "Buscar por atualizações do Blockbench.",
|
||||
"action.reset_keybindings": "Redefinir atalhos de teclado",
|
||||
"action.reset_keybindings.desc": "Redefinir todos os atalhos de teclado aos padrões do Blockbench",
|
||||
"action.reset_layout": "Redefinir aparência",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Texturas têm que ser quadradas",
|
||||
"message.unsaved_texture.title": "Textura Não Salva",
|
||||
"message.unsaved_texture.message": "Todas as alterações não salvas serão perdidas.Você quer continuar?",
|
||||
"dialog.update.no_connection": "Sem conexão com a Internet",
|
||||
"dialog.update.latest": "Última Versão",
|
||||
"dialog.update.installed": "Versão Instalada",
|
||||
"dialog.update.update": "Atualização",
|
||||
"action.vertex_snap_mode.move": "Mover",
|
||||
"action.vertex_snap_mode.scale": "Redimensionar",
|
||||
"action.open_model_folder": "Abrir Pasta de Modelos",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Usar para Partículas",
|
||||
"message.update_notification.title": "Uma Atualização está Disponível",
|
||||
"message.update_notification.message": "A versão \"%0\" do Blockbench está disponível. Você deseja instalar agora?",
|
||||
"message.update_notification.install": "Instalar",
|
||||
"message.update_notification.later": "Mais tarde",
|
||||
"message.untextured": "Esta superfície não tem uma textura",
|
||||
"dialog.toolbar_edit.title": "Customizar Barra de Ferramentas",
|
||||
"keybindings.reset": "Redefinir",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotação",
|
||||
"timeline.position": "Posição",
|
||||
"timeline.scale": "Redimensionar",
|
||||
"menu.timeline.add": "Adicionar Quadro",
|
||||
"menu.keyframe.quaternion": "Quaternião",
|
||||
"panel.animations": "Animações",
|
||||
"panel.keyframe": "Quadro",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Adicione automaticamente um quadro-chave. Pressione shift para forçar os valores padrão",
|
||||
"action.bring_up_all_animations.desc": "Traz todos os animadores modificados para a linha do tempo",
|
||||
"timeline.timeline": "Instruções",
|
||||
"menu.palette.load": "Carregar Paleta",
|
||||
"menu.palette.load.default": "Padrão",
|
||||
"panel.color.picker": "Seletor",
|
||||
"panel.color.palette": "Paleta",
|
||||
@ -1110,9 +1094,34 @@
|
||||
"switches.lock": "Travar",
|
||||
"camera_angle.isometric_right": "Direita isométrica",
|
||||
"camera_angle.isometric_left": "Esquerda isométrica",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides": "Lados Carregados",
|
||||
"settings.render_sides.desc": "Selecione qual lado de uma face é carregado",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.front": "Fora",
|
||||
"settings.render_sides.double": "Dentro e Fora",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
183
lang/ru.json
183
lang/ru.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Шаблон",
|
||||
"dialog.create_texture.resolution": "Разрешение",
|
||||
"dialog.input.title": "Ввод",
|
||||
"dialog.update.title": "Обновления",
|
||||
"dialog.update.refresh": "Перезагрузить",
|
||||
"dialog.update.up_to_date": "Blockbench обновлён!",
|
||||
"dialog.update.connecting": "Подключение к серверу",
|
||||
"dialog.settings.settings": "Настройки",
|
||||
"dialog.settings.keybinds": "Управление",
|
||||
"dialog.settings.about": "О программе",
|
||||
@ -162,9 +158,9 @@
|
||||
"layout.color.back.desc": "Фон и поля ввода",
|
||||
"layout.color.dark": "Тьма",
|
||||
"layout.color.dark.desc": "Фон рабочей области",
|
||||
"layout.color.ui": "ИП",
|
||||
"layout.color.ui": "Интерфейс",
|
||||
"layout.color.ui.desc": "Основной цвет интерфейса",
|
||||
"layout.color.bright_ui": "Светлый ИП",
|
||||
"layout.color.bright_ui": "Светлый интерфейс",
|
||||
"layout.color.bright_ui.desc": "Контекстное меню и подсказки",
|
||||
"layout.color.button": "Кнопка",
|
||||
"layout.color.button.desc": "Кнопки и переключатели",
|
||||
@ -195,15 +191,13 @@
|
||||
"settings.category.general": "Основные",
|
||||
"settings.category.preview": "Предпросмотр",
|
||||
"settings.category.grid": "Сетка",
|
||||
"settings.category.edit": "Изменить",
|
||||
"settings.category.edit": "Редактирование",
|
||||
"settings.category.snapping": "Привязка к сетке",
|
||||
"settings.category.defaults": "По умолчанию",
|
||||
"settings.category.dialogs": "Диалоговые окна",
|
||||
"settings.category.export": "Экспорт",
|
||||
"settings.language": "Язык",
|
||||
"settings.language.desc": "Язык интерфейса. Перезапустите Blockbench, чтобы применить изменения.",
|
||||
"settings.show_actions": "Отображение действий",
|
||||
"settings.show_actions.desc": "Показывать каждое действие в строке состояния",
|
||||
"settings.backup_interval": "Интервал автосохранения",
|
||||
"settings.backup_interval.desc": "Интервал автосохранения в минутах",
|
||||
"settings.origin_size": "Центр поворота",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Открыть окно настроек Blockbench",
|
||||
"action.plugins_window": "Плагины...",
|
||||
"action.plugins_window.desc": "Открыть окно хранилища плагинов",
|
||||
"action.update_window": "Обновления...",
|
||||
"action.update_window.desc": "Проверить наличие обновлений Blockbench",
|
||||
"action.reset_keybindings": "Сбросить управление",
|
||||
"action.reset_keybindings.desc": "Вернуть все сочетания клавиш к первоначальным",
|
||||
"action.reset_layout": "Сбросить внешний вид",
|
||||
@ -383,7 +375,7 @@
|
||||
"action.toggle_shade": "Переключить тени",
|
||||
"action.toggle_shade.desc": "Переключить тени выделенных кубов",
|
||||
"action.rename": "Переименовать",
|
||||
"action.rename.desc": "Переименовать выделенные кубы",
|
||||
"action.rename.desc": "Переименовать всех выделенных кубов",
|
||||
"action.add_display_preset": "Новый шаблон",
|
||||
"action.add_display_preset.desc": "Создать шаблон настроек отображения",
|
||||
"action.fullscreen": "Полный экран",
|
||||
@ -412,12 +404,12 @@
|
||||
"action.save_textures.desc": "Сохранить все несохранённые текстуры",
|
||||
"action.animated_textures": "Проигрывать анимированные текстуры",
|
||||
"action.animated_textures.desc": "Проигрывать анимацию текстур",
|
||||
"action.origin_to_geometry": "Центр поворота к геометрии",
|
||||
"action.origin_to_geometry.desc": "Установить центр поворота в центр геометрии",
|
||||
"action.origin_to_geometry": "Оцентрировать центр поворота",
|
||||
"action.origin_to_geometry.desc": "Установить центр поворота в центр выбора",
|
||||
"action.rescale_toggle": "Переключить масштабирование",
|
||||
"action.rescale_toggle.desc": "Масштабировать кубы на основе их поворота",
|
||||
"action.bone_reset_toggle": "Сбросить кость",
|
||||
"action.bone_reset_toggle.desc": "Остановить часть от отображения кубов родительской модели",
|
||||
"action.bone_reset_toggle.desc": "Остановить кость от отображения кубов родительской модели",
|
||||
"action.reload": "Перезагрузить Blockbench",
|
||||
"action.reload.desc": "Перезагрузить Blockbench. Это удалит весь несохранённый прогресс.",
|
||||
"menu.file": "Файл",
|
||||
@ -426,7 +418,7 @@
|
||||
"menu.filter": "Фильтр",
|
||||
"menu.display": "Отображение",
|
||||
"menu.view": "Вид",
|
||||
"menu.file.new": "Новый",
|
||||
"menu.file.new": "Создать",
|
||||
"menu.file.recent": "Недавние",
|
||||
"menu.file.import": "Импортировать",
|
||||
"menu.file.export": "Экспортировать",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Текстуры должны быть квадратными",
|
||||
"message.unsaved_texture.title": "Несохранённая текстура",
|
||||
"message.unsaved_texture.message": "Все несохранённые изменения к этой текстуре будут потеряны. Вы хотите продолжить?",
|
||||
"dialog.update.no_connection": "Отсутствует подключение к Интернету",
|
||||
"dialog.update.latest": "Новейшая версия",
|
||||
"dialog.update.installed": "Установленная версия",
|
||||
"dialog.update.update": "Обновление",
|
||||
"action.vertex_snap_mode.move": "Перемещение",
|
||||
"action.vertex_snap_mode.scale": "Масштабирование",
|
||||
"action.open_model_folder": "Открыть расположение модели",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Использовать для частиц",
|
||||
"message.update_notification.title": "Доступно обновление",
|
||||
"message.update_notification.message": "Доступно обновление Blockbench «%0». Хотите установить его?",
|
||||
"message.update_notification.install": "Установить",
|
||||
"message.update_notification.later": "Позже",
|
||||
"message.untextured": "Эта поверхность не имеет текстур",
|
||||
"dialog.toolbar_edit.title": "Настроить панель инструментов",
|
||||
"keybindings.reset": "Сбросить",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Поворот",
|
||||
"timeline.position": "Позиция",
|
||||
"timeline.scale": "Масштаб",
|
||||
"menu.timeline.add": "Добавить кадр",
|
||||
"menu.keyframe.quaternion": "Кватернион",
|
||||
"panel.animations": "Анимации",
|
||||
"panel.keyframe": "Кадр",
|
||||
@ -666,7 +651,7 @@
|
||||
"panel.variable_placeholders.info": "Перечислите переменные, которые вы хотите просмотреть используя имя=значение",
|
||||
"status_bar.vertex_distance": "Дистанция: %0",
|
||||
"dialog.create_gif.title": "Запись GIF",
|
||||
"dialog.create_gif.length": "Длительность",
|
||||
"dialog.create_gif.length": "Длина",
|
||||
"dialog.create_gif.fps": "FPS",
|
||||
"dialog.create_gif.compression": "Сжатие",
|
||||
"dialog.create_gif.play": "Воспроизвести анимацию",
|
||||
@ -682,8 +667,8 @@
|
||||
"action.export_class_entity.desc": "Экспортировать модель сущности как класс Java",
|
||||
"settings.seethrough_outline": "Рентгенные контуры",
|
||||
"settings.seethrough_outline.desc": "Показывать контуры через объекты",
|
||||
"mode.edit": "Изменить",
|
||||
"mode.paint": "Красить",
|
||||
"mode.edit": "Редактирование",
|
||||
"mode.paint": "Рисование",
|
||||
"mode.display": "Предпросмотр",
|
||||
"mode.animate": "Анимировать",
|
||||
"status_bar.recording_gif": "Запись GIF",
|
||||
@ -708,7 +693,7 @@
|
||||
"menu.preview.perspective.reset": "Сбросить камеру",
|
||||
"action.fill_mode": "Режим заполнения",
|
||||
"action.fill_mode.face": "Грань",
|
||||
"action.fill_mode.color": "Цвет",
|
||||
"action.fill_mode.color": "Цвета",
|
||||
"action.fill_mode.cube": "Куб",
|
||||
"action.toggle_mirror_uv": "Зеркалить UV",
|
||||
"action.toggle_mirror_uv.desc": "Переключить зеркальность UV на оси X выделенных кубов",
|
||||
@ -760,22 +745,22 @@
|
||||
"message.recover_backup.message": "Blockbench был закрыт без сохранения. Вы хотите восстановить модель?",
|
||||
"message.install_plugin": "Установка плагина %0",
|
||||
"message.invalid_session.title": "Неверный ключ сеанса",
|
||||
"message.invalid_session.message": "Сеанс к которому вы пытаетесь подключиться истек или ваш ключ не правильный.",
|
||||
"message.invalid_session.message": "Сеанс, к которому вы пытаетесь подключиться, истёк или введён недействительный токен.",
|
||||
"dialog.create_texture.power": "Размер второй степени",
|
||||
"dialog.create_gif.turn": "Скорость поворота камеры",
|
||||
"action.edit_session": "Сеанс Редактирования...",
|
||||
"action.edit_session.desc": "Присоединиться к сеансу редактирования для коллаборации с другими пользователями",
|
||||
"action.edit_session": "Сеанс редактирования...",
|
||||
"action.edit_session.desc": "Присоединиться к сеансу для совместной работы с другими пользователями",
|
||||
"action.reset_keyframe": "Сбросить кадр",
|
||||
"action.reset_keyframe.desc": "Сбросить все значения выбранных кадров",
|
||||
"dialog.edit_session.title": "Сеанс Редактирования",
|
||||
"dialog.edit_session.title": "Сеанс редактирования",
|
||||
"edit_session.username": "Имя пользователя",
|
||||
"edit_session.token": "Ключ",
|
||||
"edit_session.about": "Сеансы редактирования могут быть использованы для коллаборации по интернету. Создайте сеанс, скопируйте его ключ и отправьте его Вашим друзьям, которые могут воспользоваться им чтобы присоединиться.",
|
||||
"edit_session.token": "Токен",
|
||||
"edit_session.about": "Сеансы редактирования можно использовать для совместной работы над моделями. Создайте сеанс, скопируйте токен и отправьте его друзьям, которые затем смогут присоединиться.",
|
||||
"edit_session.join": "Присоединиться к сеансу",
|
||||
"edit_session.create": "Создать сеанс",
|
||||
"edit_session.quit": "Покинуть сеанс",
|
||||
"edit_session.joined": "Пользователь %0 присоединился к сеансу",
|
||||
"edit_session.left": "Ползователь %0 покинул сеанс",
|
||||
"edit_session.joined": "%0 присоединяется к сеансу",
|
||||
"edit_session.left": "%0 покидает сеанс",
|
||||
"edit_session.quit_session": "Покинул текущий сеанс",
|
||||
"edit_session.status": "Статус",
|
||||
"edit_session.hosting": "Хост",
|
||||
@ -797,17 +782,17 @@
|
||||
"dates.yesterday": "Вчера",
|
||||
"dates.this_week": "Этой неделью",
|
||||
"dates.weeks_ago": "%0 недель назад",
|
||||
"mode.start": "Начать",
|
||||
"mode.start.new": "Новый",
|
||||
"mode.start": "Стартовый экран",
|
||||
"mode.start.new": "Создать",
|
||||
"mode.start.recent": "Недавние",
|
||||
"format.free": "Свободная модель",
|
||||
"format.free.desc": "Модель без ограничений для Unity и так далее.",
|
||||
"format.free.desc": "Модель без ограничений для Unity и т. п.",
|
||||
"format.java_block": "Блок/предмет Java",
|
||||
"format.java_block.desc": "Модель для издания Java. Размер и повороты ограничены.",
|
||||
"format.java_block.desc": "Модель для Java Edition. Размер и повороты ограничены.",
|
||||
"format.bedrock": "Модель Bedrock",
|
||||
"format.bedrock.desc": "Модель для издания Bedrock",
|
||||
"format.bedrock.desc": "Модель для Bedrock Edition",
|
||||
"format.bedrock_old": "Модель Bedrock (старая)",
|
||||
"format.bedrock_old.desc": "Модель издания Bedrock для версий старее 1.12",
|
||||
"format.bedrock_old.desc": "Модель Bedrock Edition для версий старее 1.12",
|
||||
"format.modded_entity": "Сущность для модов",
|
||||
"format.modded_entity.desc": "Модель сущности для модов. Может быть экспортирована как файл класса .java",
|
||||
"format.optifine_entity": "Сущность OptiFine",
|
||||
@ -828,7 +813,7 @@
|
||||
"dialog.model_stats.vertices": "Вершины",
|
||||
"dialog.model_stats.faces": "Грани",
|
||||
"settings.username": "Имя пользователя",
|
||||
"settings.username.desc": "Имя пользователя для сеансов редактирования...",
|
||||
"settings.username.desc": "Имя пользователя в сеансах редактирования",
|
||||
"settings.painting_grid": "Сетка рисования",
|
||||
"settings.painting_grid.desc": "Показывать сетку рисования на кубах с текстурой в режиме краски",
|
||||
"action.slider_brush_min_opacity": "Минимальная непрозрачность",
|
||||
@ -838,12 +823,12 @@
|
||||
"action.close_project": "Закрыть проект",
|
||||
"action.close_project.desc": "Закрыть текущий проект",
|
||||
"action.export_bedrock": "Экспортировать геометрию Bedrock",
|
||||
"action.export_bedrock.desc": "Экспортировать модель как файл геометрии издания Bedrock",
|
||||
"action.export_bedrock.desc": "Экспортировать модель как файл геометрии Bedrock Edition",
|
||||
"action.save_project": "Сохранить проект",
|
||||
"action.save_project.desc": "Сохранить текущую модель как файл проекта",
|
||||
"action.save_project_as": "Сохранить проект как",
|
||||
"action.save_project_as.desc": "Сохранить текущую модель как файл проекта в новом месте",
|
||||
"action.export_over": "Перезаписать модель",
|
||||
"action.export_over": "Сохранить модель",
|
||||
"action.export_over.desc": "Сохранить модель, текстуры и анимации перезаписывая файлы",
|
||||
"action.add_locator": "Добавить локатор",
|
||||
"action.add_locator.desc": "Добавить новый локатор для контроля позиции частиц, поводков и т.д.",
|
||||
@ -861,18 +846,18 @@
|
||||
"display.reference.crossbow": "Арбалет",
|
||||
"dialog.settings.search_results": "Результаты поиска",
|
||||
"settings.animation_snap": "Привязка Анимаций",
|
||||
"settings.animation_snap.desc": "Интервал привязки кадров на графике анимаций",
|
||||
"settings.animation_snap.desc": "Интервал привязки кадров на графике анимаций в секунду",
|
||||
"action.import_optifine_part": "Импортировать часть OptiFine",
|
||||
"action.import_optifine_part.desc": "Импортировать часть модели сущности OptiFine",
|
||||
"data.locator": "Локатор",
|
||||
"mode.start.no_recents": "Вы еще не открывали моделей",
|
||||
"mode.start.no_recents": "Нет открытых моделей",
|
||||
"panel.element": "Элемент",
|
||||
"panel.element.position": "Позиция",
|
||||
"panel.element.size": "Размер",
|
||||
"panel.element.origin": "Центральная точка",
|
||||
"panel.element.rotation": "Поворот",
|
||||
"message.canvas_limit_error.title": "Ошибка ограничения рабочей области",
|
||||
"message.canvas_limit_error.message": "Действие не может быть выполнено правильно, потому что формат ограничивает размеры рабочей области до 48 единиц. Сместите модель, чтобы предотвратить это.",
|
||||
"message.canvas_limit_error.message": "Действие не может быть выполнено правильно, потому что формат ограничивает размеры рабочей области до 48 единиц. Сместите центр поворота, чтобы предотвратить это.",
|
||||
"data.effect": "Эффект",
|
||||
"generic.name": "Имя",
|
||||
"settings.recent_projects": "Недавние модели",
|
||||
@ -936,7 +921,7 @@
|
||||
"layout.color.checkerboard.desc": "Фон рабочей области и редактора UV",
|
||||
"layout.font.code": "Шрифт кода",
|
||||
"layout.css": "Пользовательский CSS",
|
||||
"settings.category.paint": "Красить",
|
||||
"settings.category.paint": "Рисование",
|
||||
"settings.deactivate_size_limit": "Выключить лимит размера",
|
||||
"settings.deactivate_size_limit.desc": "Выключить лимит размера для определенных форматов. ПРЕДУПРЕЖДЕНИЕ: Это может вызвать ошибки с моделями.",
|
||||
"settings.brush_opacity_modifier": "Модификатор непрозрачности кисти",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Автоматическое добавление ключевого кадра. Нажмите Shift для ввода стандартных значений ",
|
||||
"action.bring_up_all_animations.desc": "Перенос всех модифицированных анимаций на временную шкалу",
|
||||
"timeline.timeline": "Инструкции",
|
||||
"menu.palette.load": "Загрузка палитры",
|
||||
"menu.palette.load.default": "Стандарт",
|
||||
"panel.color.picker": "Подборщик",
|
||||
"panel.color.palette": "Палитра",
|
||||
@ -984,11 +968,11 @@
|
||||
"action.add_marker.desc": "Установить пометку на шкале времени",
|
||||
"timeline.pre_effect_script": "Скрипт",
|
||||
"format.skin": "Скин",
|
||||
"format.skin.desc": "Редактировать скины игроков и сущностей",
|
||||
"format.skin.desc": "Редактирование скинов игроков и сущностей",
|
||||
"message.sketchfab.setup_guide": "Узнать, как настроить модели в Sketchfab: %0",
|
||||
"dialog.skin.title": "Создать скин",
|
||||
"dialog.skin.model": "Модель",
|
||||
"dialog.skin.texture": "Текстура (по желанию)",
|
||||
"dialog.skin.texture": "Текстура (необязательно)",
|
||||
"action.toggle_skin_layer": "Переключить слой скина",
|
||||
"action.toggle_skin_layer.desc": "Переключить слои шляпы и одежды",
|
||||
"action.gui_light": "Светлый интерфейс",
|
||||
@ -998,17 +982,17 @@
|
||||
"action.move_keyframe_back": "Сдвинуть кадры назад",
|
||||
"action.move_keyframe_forth": "Сдвинуть кадры вперед",
|
||||
"menu.help": "Помощь",
|
||||
"menu.help.discord": "Сервер Дискорд",
|
||||
"menu.help.discord": "Сервер в Discord",
|
||||
"menu.help.report_issue": "Сообщить о проблеме",
|
||||
"menu.help.plugin_documentation": "Документация API плагинов",
|
||||
"menu.help.plugin_documentation": "Документация Plugin API",
|
||||
"menu.help.search_action": "Найти и выполнить действие",
|
||||
"menu.help.donate": "Пожертвовать",
|
||||
"menu.help.about": "Инфо",
|
||||
"menu.help.about": "О программе...",
|
||||
"menu.preview.background.clipboard": "Загрузить из буфера обмена",
|
||||
"dialog.ignore": "Игнорировать",
|
||||
"generic.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.",
|
||||
"message.invalid_builtin_parent.title": "Неверный встроенный родитель",
|
||||
"message.invalid_builtin_parent.message": "Ссылка на неправильную родительскую модель '%0' была удалена для экспорта правильной модели",
|
||||
"dialog.resize_texture.fill": "Заполнить с помощью",
|
||||
"dialog.resize_texture.fill.transparent": "Прозрачный",
|
||||
"dialog.resize_texture.fill.color": "Цвет",
|
||||
@ -1020,18 +1004,18 @@
|
||||
"dialog.create_gif.length_mode.seconds": "Секунды",
|
||||
"dialog.create_gif.length_mode.frames": "Кадры",
|
||||
"dialog.create_gif.length_mode.animation": "Длина анимации",
|
||||
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
|
||||
"dialog.create_gif.length_mode.turntable": "Переключаемый поворот",
|
||||
"dialog.save_angle.projection": "Проэкция",
|
||||
"dialog.save_angle.projection.perspective": "Перспектива",
|
||||
"dialog.save_angle.projection.orthographic": "Ортография",
|
||||
"dialog.sketchfab_uploader.animations": "Анимации",
|
||||
"dialog.settings.theme": "Тема",
|
||||
"settings.category.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": "Текстура",
|
||||
"settings.preview_checkerboard": "Предварительный Просмотр Шахматной Доски",
|
||||
"settings.preview_checkerboard.desc": "Переключить фон шахматной доски за предварительным просмотром",
|
||||
"settings.uv_checkerboard": "шахматная доска UV редактора",
|
||||
"settings.uv_checkerboard.desc": "Переключить фон шахматной доски за UV редактором",
|
||||
"category.paint": "Рисование",
|
||||
"action.fill_mode.color_connected": "Соединённые цвета",
|
||||
"action.draw_shape_type": "Тип фигуры",
|
||||
"action.draw_shape_type.rectangle": "Четырёхугольник",
|
||||
@ -1040,7 +1024,7 @@
|
||||
"action.draw_shape_type.ellipse_h": "Пустой эллипс",
|
||||
"action.draw_shape_type.line": "Линия",
|
||||
"action.mirror_painting": "Зеркальное рисование",
|
||||
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
|
||||
"action.mirror_painting.description": "Зеркально отразите свои мазки текстуры на другой стороне модели",
|
||||
"action.lock_alpha": "Заблокировать Альфа Канал",
|
||||
"action.lock_alpha.description": "Заблокировать прозрачность всех пикселей",
|
||||
"action.draw_shape_tool": "Нарисовать фигуру",
|
||||
@ -1049,28 +1033,28 @@
|
||||
"action.copy_paste_tool.desc": "Инструмент для копирования/вставки выделенных текстур",
|
||||
"action.export_gltf": "Экспортировать как glTF",
|
||||
"action.export_gltf.desc": "Экспортировать модель и анимации как файл типа glTF чтобы использовать в других программах 3D моделирования",
|
||||
"action.transform_space": "Transform Space",
|
||||
"action.transform_space.desc": "Default transform space for elements and bones",
|
||||
"action.transform_space": "Место для Трансформации",
|
||||
"action.transform_space.desc": "Обычное место для трансформации для элементов и костей",
|
||||
"action.transform_space.global": "Глобальный",
|
||||
"action.transform_space.bone": "Кость",
|
||||
"action.transform_space.local": "Локальный",
|
||||
"action.toggle_camera_projection": "Включить проекцию камеры",
|
||||
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
|
||||
"action.toggle_camera_projection.desc": "переключить проекцию камеры между перспективы и ортографией",
|
||||
"action.load_camera_angle": "Угол камеры: %0",
|
||||
"action.load_camera_angle.desc": "Load the camera angle '%0'",
|
||||
"action.slider_face_tint": "Tint Index",
|
||||
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
|
||||
"action.load_camera_angle.desc": "Загрузить угол камеры '%0'",
|
||||
"action.slider_face_tint": "Индекс оттенка",
|
||||
"action.slider_face_tint.desc": "Поставить индекс оттенка на эту грань. -1 означает непоставлено",
|
||||
"menu.help.quickstart": "Помощь в начале",
|
||||
"menu.help.developer": "Фунции разработчика",
|
||||
"menu.help.developer.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.help.developer.reset_storage": "Перезагрузка фабрики",
|
||||
"menu.help.developer.reset_storage.confirm": "Вы уверены, что хотите снести Блокбенч до настроек фабрики. Это удалит все ваши настройки, горячтие клавиши и загруженные плагины.",
|
||||
"menu.help.developer.cache_reload": "Перезагрузить кэш",
|
||||
"menu.texture.resize": "Изменить размер",
|
||||
"menu.preview.orthographic": "Ортография",
|
||||
"menu.preview.save_angle": "Сохранить угол...",
|
||||
"menu.preview.angle": "Углы",
|
||||
"menu.preview.angle.initial": "Initial Angle",
|
||||
"menu.preview.angle.initial": "Инициальный угол",
|
||||
"menu.preview.angle.load": "Загрузить",
|
||||
"menu.preview.maximize": "Увеличить до конца",
|
||||
"panel.color.both": "Оба",
|
||||
@ -1081,38 +1065,63 @@
|
||||
"uv_editor.copy_paste_tool.mirror_x": "Отзеркалеть по X",
|
||||
"uv_editor.copy_paste_tool.mirror_y": "Отзеркалить по Y",
|
||||
"uv_editor.copy_paste_tool.rotate": "Повернуть на 90 градусов",
|
||||
"dialog.project.modded_entity_version": "Export Version",
|
||||
"dialog.project.modded_entity_version": "Экспортировать версию",
|
||||
"dialog.save_angle.position": "Позиция камеры",
|
||||
"dialog.save_angle.target": "Focal Point",
|
||||
"dialog.save_angle.target": "Точка Фокуса",
|
||||
"dialog.skin.pose": "Поза",
|
||||
"layout.color.frame": "Window Frame",
|
||||
"layout.color.frame.desc": "Border and title bar of the window",
|
||||
"layout.color.frame": "Окно",
|
||||
"layout.color.frame.desc": "Рамка и заголовок окна",
|
||||
"settings.large_grid_size": "Размер сетки блока",
|
||||
"settings.large_grid_size.desc": "Размер сетки блока",
|
||||
"action.load_plugin_from_url": "Загрузить плагин через ссылку",
|
||||
"action.load_plugin_from_url.desc": "Загрузить плагин через сервер, уточняя ссылку",
|
||||
"action.cube_counter.desc": "Показывает номер кубов и другую статистику",
|
||||
"action.unlock_everything": "Разблокировать всё",
|
||||
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
|
||||
"action.unlock_everything.desc": "Разблокировать все группы и элементы в аутлайнере",
|
||||
"action.load_palette": "Загрузить палитру",
|
||||
"action.load_palette.desc": "Load one of the built-in palette presets",
|
||||
"action.load_palette.desc": "Загрузить одну из встроенных предварительных палитр",
|
||||
"action.toggle_locked": "Включить блокировку",
|
||||
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
|
||||
"action.toggle_locked.desc": "Переключить будут ли выбранные элементы заблокированы",
|
||||
"action.apply_display_preset": "Применить предварительный набор",
|
||||
"action.apply_display_preset.desc": "Применить обычный или свой предварительный набор настроек",
|
||||
"action.apply_display_preset.here": "Применить к этому слоту",
|
||||
"action.apply_display_preset.everywhere": "Применить ко всем слотам",
|
||||
"action.resolve_keyframe_expressions": "Resolve Keyframe",
|
||||
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
|
||||
"action.resolve_keyframe_expressions": "Вычислить кадры",
|
||||
"action.resolve_keyframe_expressions.desc": "Вычисляет математические примеры выбранных кадров",
|
||||
"action.fold_all_animations": "Сложить все анимации",
|
||||
"action.timeline_focus.used": "Используется",
|
||||
"menu.palette.load.empty": "Чисто",
|
||||
"switches.lock": "Заблокировать",
|
||||
"camera_angle.isometric_right": "Изометрическое право",
|
||||
"camera_angle.isometric_left": "Изометрическое лево",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides": "Стороны рендера",
|
||||
"settings.render_sides.desc": "Выбирете какая част ребра будет зарендерена",
|
||||
"settings.render_sides.auto": "Авто",
|
||||
"settings.render_sides.front": "Снаружи",
|
||||
"settings.render_sides.double": "Внутри и снаружи",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
47
lang/sv.json
47
lang/sv.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "Mall",
|
||||
"dialog.create_texture.resolution": "Upplösning",
|
||||
"dialog.input.title": "Inmatning",
|
||||
"dialog.update.title": "Uppdateringar",
|
||||
"dialog.update.refresh": "Försök igen",
|
||||
"dialog.update.up_to_date": "Blockbench är uppdaterad!",
|
||||
"dialog.update.connecting": "Ansluter till servern",
|
||||
"dialog.settings.settings": "Inställningar",
|
||||
"dialog.settings.keybinds": "Tangentbindningar",
|
||||
"dialog.settings.about": "Om",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "Exportera",
|
||||
"settings.language": "Språk",
|
||||
"settings.language.desc": "Gränssnittsspråk. Starta om Bockbench för att tillämpa ändringar.",
|
||||
"settings.show_actions": "Visningsåtgärder",
|
||||
"settings.show_actions.desc": "Visa varje åtgärd i statusfältet",
|
||||
"settings.backup_interval": "Säkerhetskopierings intervall",
|
||||
"settings.backup_interval.desc": "Intervall av den automatiska säkerhetskopieringen i minuter",
|
||||
"settings.origin_size": "Rotations ursprung",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "Öppna Blockbenchs inställningsdialogruta.",
|
||||
"action.plugins_window": "Plugins...",
|
||||
"action.plugins_window.desc": "Öppna pluginaffärfönstret",
|
||||
"action.update_window": "Uppdateringar...",
|
||||
"action.update_window.desc": "Sök efter Blockbench uppdateringar.",
|
||||
"action.reset_keybindings": "Återställ tangentbindningar",
|
||||
"action.reset_keybindings.desc": "Återställ alla tangentbindningar till Blockbenchs standardtangentbindningar",
|
||||
"action.reset_layout": "Återställ layout",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "Texturer måste vara fyrkantiga",
|
||||
"message.unsaved_texture.title": "Osparad textur",
|
||||
"message.unsaved_texture.message": "Alla osparade ändringar till denna textur kommer att försvinna. Vill du fortsätta?",
|
||||
"dialog.update.no_connection": "Ingen internetanslutning",
|
||||
"dialog.update.latest": "Senaste version",
|
||||
"dialog.update.installed": "Installerad version",
|
||||
"dialog.update.update": "Uppdatera",
|
||||
"action.vertex_snap_mode.move": "Flytta",
|
||||
"action.vertex_snap_mode.scale": "Skala",
|
||||
"action.open_model_folder": "Öppna modellmapp",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "Använd för partiklar",
|
||||
"message.update_notification.title": "En uppdatering är tillgänglig ",
|
||||
"message.update_notification.message": "Den nya Blockbench versionen \"%0\" är tillgänglig. Vill du installera den nu?",
|
||||
"message.update_notification.install": "Installera",
|
||||
"message.update_notification.later": "Senare",
|
||||
"message.untextured": "Denna ytan har ingen textur",
|
||||
"dialog.toolbar_edit.title": "Anpassa verktygsfältet",
|
||||
"keybindings.reset": "Återställ",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "Rotation",
|
||||
"timeline.position": "Position",
|
||||
"timeline.scale": "Skala",
|
||||
"menu.timeline.add": "Lägg till keyframe",
|
||||
"menu.keyframe.quaternion": "Kvartärperiod",
|
||||
"panel.animations": "Animationer",
|
||||
"panel.keyframe": "Keyframe",
|
||||
@ -800,8 +785,8 @@
|
||||
"mode.start": "Start",
|
||||
"mode.start.new": "Ny",
|
||||
"mode.start.recent": "Nyligen",
|
||||
"format.free": "Free Model",
|
||||
"format.free.desc": "Model without restrictions for Unity etc.",
|
||||
"format.free": "Generic Model",
|
||||
"format.free.desc": "Model without restrictions for game engines, rendering etc.",
|
||||
"format.java_block": "Java Block/Item",
|
||||
"format.java_block.desc": "Block model for Java Edition. Size and rotations are limited.",
|
||||
"format.bedrock": "Bedrock Model",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
|
||||
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
|
||||
"timeline.timeline": "Instruktioner",
|
||||
"menu.palette.load": "Load Palette",
|
||||
"menu.palette.load.default": "Default",
|
||||
"panel.color.picker": "Picker",
|
||||
"panel.color.palette": "Palette",
|
||||
@ -1114,5 +1098,30 @@
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides.double": "Inside and Outside",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
51
lang/zh.json
51
lang/zh.json
@ -151,10 +151,6 @@
|
||||
"dialog.create_texture.template": "模板",
|
||||
"dialog.create_texture.resolution": "分辨率",
|
||||
"dialog.input.title": "输入",
|
||||
"dialog.update.title": "更新",
|
||||
"dialog.update.refresh": "重试",
|
||||
"dialog.update.up_to_date": "Blockbench 已是最新版本!",
|
||||
"dialog.update.connecting": "正在连接到服务器",
|
||||
"dialog.settings.settings": "设置",
|
||||
"dialog.settings.keybinds": "快捷键",
|
||||
"dialog.settings.about": "关于",
|
||||
@ -202,8 +198,6 @@
|
||||
"settings.category.export": "导出",
|
||||
"settings.language": "语言",
|
||||
"settings.language.desc": "界面语言,重启 Blockbench 以应用更改",
|
||||
"settings.show_actions": "显示操作",
|
||||
"settings.show_actions.desc": "在状态栏中显示所有操作",
|
||||
"settings.backup_interval": "自动备份时间间隔",
|
||||
"settings.backup_interval.desc": "自动备份时间间隔(以分钟为单位)",
|
||||
"settings.origin_size": "三轴长度",
|
||||
@ -326,8 +320,6 @@
|
||||
"action.settings_window.desc": "打开 Blockbench 设置对话框。",
|
||||
"action.plugins_window": "插件……",
|
||||
"action.plugins_window.desc": "打开插件商店页面",
|
||||
"action.update_window": "更新……",
|
||||
"action.update_window.desc": "检查 Blockbench 更新。",
|
||||
"action.reset_keybindings": "重置快捷键",
|
||||
"action.reset_keybindings.desc": "将所有快捷键重置为 Blockbench 默认值",
|
||||
"action.reset_layout": "重置布局",
|
||||
@ -536,10 +528,6 @@
|
||||
"message.square_textures": "贴图必须是方形的",
|
||||
"message.unsaved_texture.title": "未保存的贴图",
|
||||
"message.unsaved_texture.message": "对此贴图的所有未保存更改都将丢失。你想继续吗?",
|
||||
"dialog.update.no_connection": "无网络连接",
|
||||
"dialog.update.latest": "最新版本",
|
||||
"dialog.update.installed": "已安装的版本",
|
||||
"dialog.update.update": "更新",
|
||||
"action.vertex_snap_mode.move": "移动",
|
||||
"action.vertex_snap_mode.scale": "缩放",
|
||||
"action.open_model_folder": "打开模型文件夹",
|
||||
@ -549,8 +537,6 @@
|
||||
"menu.texture.particle": "用作粒子贴图",
|
||||
"message.update_notification.title": "有新的更新",
|
||||
"message.update_notification.message": "新的 Blockbench 版本“%0”可用。你想现在安装吗?",
|
||||
"message.update_notification.install": "安装",
|
||||
"message.update_notification.later": "稍后",
|
||||
"message.untextured": "这个面没有材质纹理",
|
||||
"dialog.toolbar_edit.title": "自定义工具栏",
|
||||
"keybindings.reset": "重启",
|
||||
@ -635,7 +621,6 @@
|
||||
"timeline.rotation": "旋转",
|
||||
"timeline.position": "位置",
|
||||
"timeline.scale": "缩放",
|
||||
"menu.timeline.add": "添加关键帧",
|
||||
"menu.keyframe.quaternion": "四元数",
|
||||
"panel.animations": "动画",
|
||||
"panel.keyframe": "关键帧",
|
||||
@ -970,7 +955,6 @@
|
||||
"action.add_keyframe.desc": "自动添加关键帧,按下 Shift 键强制使用默认值",
|
||||
"action.bring_up_all_animations.desc": "将所有修改后的动画置入到时间轴内",
|
||||
"timeline.timeline": "使用说明",
|
||||
"menu.palette.load": "加载调色板",
|
||||
"menu.palette.load.default": "默认",
|
||||
"panel.color.picker": "选色器",
|
||||
"panel.color.palette": "调色板",
|
||||
@ -1110,9 +1094,34 @@
|
||||
"switches.lock": "锁",
|
||||
"camera_angle.isometric_right": "等距右",
|
||||
"camera_angle.isometric_left": "等距左",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.render_sides.desc": "Select which side of a face is rendered",
|
||||
"settings.render_sides.auto": "Auto",
|
||||
"settings.render_sides.front": "Outside",
|
||||
"settings.render_sides.double": "Inside and Outside"
|
||||
"settings.render_sides": "渲染边框",
|
||||
"settings.render_sides.desc": "选择要渲染的面",
|
||||
"settings.render_sides.auto": "自动设置",
|
||||
"settings.render_sides.front": "外围",
|
||||
"settings.render_sides.double": "内部与外围",
|
||||
"generic.enable": "Enable",
|
||||
"generic.disable": "Disable",
|
||||
"generic.redacted": "Redacted",
|
||||
"dialog.project.layered_textures": "Layered Textures",
|
||||
"dialog.select_texture.import_all": "Import All",
|
||||
"dialog.skin.layer_template": "Layer Texture",
|
||||
"about.version.up_to_date": "Up to date",
|
||||
"about.version.update_available": "Version %0 is available",
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamer Mode",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.jump_to_timeline_start": "Jump to Animation Start",
|
||||
"action.jump_to_timeline_end": "Jump to Animation End",
|
||||
"menu.help.updating": "Updating (%0%)",
|
||||
"menu.help.update_ready": "Relaunch to Update",
|
||||
"menu.help.update_failed": "Update Failed",
|
||||
"menu.animation.loop.once": "Play Once",
|
||||
"menu.animation.loop.hold": "Hold On Last Frame",
|
||||
"menu.animation.loop.loop": "Loop",
|
||||
"interface.streamer_mode_on": "Streamer Mode Enabled"
|
||||
}
|
112
lib/CanvasFrame.js
Normal file
112
lib/CanvasFrame.js
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Utility to modify images with a canvas
|
||||
*/
|
||||
|
||||
class CanvasFrame {
|
||||
constructor(a, b) {
|
||||
if (a && a.nodeName == 'CANVAS') {
|
||||
if (a.getContext('2d')) {
|
||||
this.canvas = a;
|
||||
} else {
|
||||
this.createCanvas(a.width, a.height)
|
||||
this.loadFromImage(a)
|
||||
}
|
||||
|
||||
} else if (a && a.nodeName == 'IMG') {
|
||||
this.createCanvas(a.naturalWidth, a.naturalHeight)
|
||||
this.loadFromImage(a)
|
||||
|
||||
} else if (a && b) {
|
||||
this.createCanvas(a, b)
|
||||
}
|
||||
this.ctx = this.canvas.getContext('2d')
|
||||
}
|
||||
get width() {return this.canvas.width;}
|
||||
get height() {return this.canvas.height;}
|
||||
|
||||
createCanvas(w, h) {
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = w;
|
||||
this.canvas.height = h;
|
||||
this.ctx = this.canvas.getContext('2d')
|
||||
}
|
||||
replace(layer) {
|
||||
this.canvas
|
||||
}
|
||||
async loadFromURL(url) {
|
||||
let img = new Image()
|
||||
img.src = url;
|
||||
await new Promise((resolve, reject) => {
|
||||
img.onload = function() {
|
||||
resolve()
|
||||
}
|
||||
img.onerror = reject;
|
||||
})
|
||||
}
|
||||
loadFromImage(img) {
|
||||
if (img.naturalWidth) {
|
||||
this.canvas.width = img.naturalWidth;
|
||||
this.canvas.height = img.naturalHeight;
|
||||
}
|
||||
this.ctx.drawImage(img, 0, 0)
|
||||
}
|
||||
loadFromCanvas(img) {
|
||||
this.canvas.width = image.naturalWidth;
|
||||
this.canvas.height = image.naturalHeight;
|
||||
this.ctx.drawImage(img, 0, 0)
|
||||
}
|
||||
autoCrop() {
|
||||
// Based on code by remy, licensed under MIT
|
||||
// https://gist.github.com/remy/784508
|
||||
|
||||
let copy = document.createElement('canvas').getContext('2d');
|
||||
let pixels = this.ctx.getImageData(0, 0, this.width, this.height);
|
||||
let i;
|
||||
let bound = {
|
||||
top: null,
|
||||
left: null,
|
||||
right: null,
|
||||
bottom: null
|
||||
};
|
||||
let x, y;
|
||||
|
||||
for (i = 0; i < pixels.data.length; i += 4) {
|
||||
if (pixels.data[i+3] !== 0) {
|
||||
x = (i / 4) % this.width;
|
||||
y = ~~((i / 4) / this.width);
|
||||
|
||||
if (bound.top === null) {
|
||||
bound.top = y;
|
||||
}
|
||||
|
||||
if (bound.left === null) {
|
||||
bound.left = x;
|
||||
} else if (x < bound.left) {
|
||||
bound.left = x;
|
||||
}
|
||||
|
||||
if (bound.right === null) {
|
||||
bound.right = x;
|
||||
} else if (bound.right < x) {
|
||||
bound.right = x;
|
||||
}
|
||||
|
||||
if (bound.bottom === null) {
|
||||
bound.bottom = y;
|
||||
} else if (bound.bottom < y) {
|
||||
bound.bottom = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var trimHeight = bound.bottom - bound.top,
|
||||
trimWidth = bound.right - bound.left,
|
||||
trimmed = this.ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
|
||||
|
||||
copy.canvas.width = trimWidth;
|
||||
copy.canvas.height = trimHeight;
|
||||
copy.putImageData(trimmed, 0, 0);
|
||||
this.canvas = copy.canvas;
|
||||
this.ctx = copy;
|
||||
}
|
||||
}
|
131
main.js
131
main.js
@ -1,6 +1,8 @@
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
const { arch, platform } = require('os');
|
||||
|
||||
let orig_win;
|
||||
|
||||
@ -26,35 +28,71 @@ function createWindow(second_instance) {
|
||||
if (!orig_win) orig_win = win;
|
||||
var index_path = path.join(__dirname, 'index.html')
|
||||
if (process.platform === 'darwin') {
|
||||
var template = [{
|
||||
label: 'File',
|
||||
submenu: [{
|
||||
label: 'Quit',
|
||||
accelerator: 'CmdOrCtrl+Q',
|
||||
click: function() {
|
||||
app.quit();
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
label: 'Edit',
|
||||
submenu: [{
|
||||
label: 'Cut',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
selector: 'cut:'
|
||||
}, {
|
||||
label: 'Copy',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
selector: 'copy:'
|
||||
}, {
|
||||
label: 'Paste',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
selector: 'paste:'
|
||||
}, {
|
||||
label: 'Select All',
|
||||
accelerator: 'CmdOrCtrl+A',
|
||||
selector: 'selectAll:'
|
||||
}]
|
||||
}]
|
||||
|
||||
let template = [
|
||||
{
|
||||
"label": "Blockbench",
|
||||
"submenu": [
|
||||
{
|
||||
"role": "hide"
|
||||
},
|
||||
{
|
||||
"role": "hideothers"
|
||||
},
|
||||
{
|
||||
"role": "unhide"
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"label": "Quit",
|
||||
"accelerator": "Command+Q"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Edit",
|
||||
"submenu": [
|
||||
{
|
||||
"role": "cut"
|
||||
},
|
||||
{
|
||||
"role": "copy"
|
||||
},
|
||||
{
|
||||
"role": "paste"
|
||||
},
|
||||
{
|
||||
"role": "selectall"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Window",
|
||||
"role": "window",
|
||||
"submenu": [
|
||||
{
|
||||
"label": "Toggle Full Screen",
|
||||
"accelerator": "Ctrl+Command+F"
|
||||
},
|
||||
{
|
||||
"role": "minimize"
|
||||
},
|
||||
{
|
||||
"role": "close"
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"role": "front"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
var osxMenu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(osxMenu)
|
||||
} else {
|
||||
@ -84,8 +122,39 @@ app.on('second-instance', function (event, argv, cwd) {
|
||||
})
|
||||
|
||||
app.commandLine.appendSwitch('ignore-gpu-blacklist')
|
||||
app.commandLine.appendSwitch('enable-accelerated-video')
|
||||
|
||||
app.on('ready', createWindow)
|
||||
|
||||
|
||||
app.on('ready', () => {
|
||||
|
||||
createWindow()
|
||||
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
autoUpdater.autoDownload = false;
|
||||
|
||||
autoUpdater.on('update-available', (a) => {
|
||||
console.log('update-available', a)
|
||||
ipcMain.on('allow-auto-update', () => {
|
||||
autoUpdater.downloadUpdate()
|
||||
})
|
||||
orig_win.webContents.send('update-available');
|
||||
})
|
||||
autoUpdater.on('update-downloaded', (a) => {
|
||||
console.log('update-downloaded', a)
|
||||
orig_win.webContents.send('update-downloaded', a)
|
||||
})
|
||||
autoUpdater.on('error', (a) => {
|
||||
console.log('update-error', a)
|
||||
orig_win.webContents.send('update-error', a)
|
||||
})
|
||||
autoUpdater.on('download-progress', (a) => {
|
||||
console.log('update-progress', a)
|
||||
orig_win.webContents.send('update-progress', a)
|
||||
})
|
||||
|
||||
autoUpdater.checkForUpdates()
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
|
1630
package-lock.json
generated
Normal file
1630
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "Blockbench",
|
||||
"description": "Model editing and animation software",
|
||||
"version": "3.5.4",
|
||||
"license": "MIT",
|
||||
"version": "3.6.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"author": {
|
||||
"name": "JannisX11",
|
||||
"email": "info@blockbench.net"
|
||||
@ -14,12 +14,20 @@
|
||||
},
|
||||
"main": "main.js",
|
||||
"build": {
|
||||
"afterSign": "scripts/notarize.js",
|
||||
"appId": "blockbench",
|
||||
"productName": "Blockbench",
|
||||
"artifactName": "${productName}_${arch}_${version}.${ext}",
|
||||
"publish": [
|
||||
{
|
||||
"provider": "github"
|
||||
}
|
||||
],
|
||||
"mac": {
|
||||
"category": "macOS.application",
|
||||
"target": "dmg"
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "build/entitlements.mac.plist",
|
||||
"entitlementsInherit": "build/entitlements.mac.plist"
|
||||
},
|
||||
"files": [
|
||||
"assets/",
|
||||
@ -39,7 +47,6 @@
|
||||
],
|
||||
"dmg": {
|
||||
"artifactName": "${productName}_${version}.${ext}",
|
||||
"backgroundColor": "#282c34",
|
||||
"window": {
|
||||
"x": 200,
|
||||
"y": 100,
|
||||
@ -71,17 +78,26 @@
|
||||
"appImage"
|
||||
],
|
||||
"category": "3DGraphics"
|
||||
}
|
||||
},
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": "bbmodel",
|
||||
"name": "Blockbench Project",
|
||||
"role": "Editor"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "electron .",
|
||||
"dist": "electron-builder --publish=always",
|
||||
"win64": "electron-builder -w --ia32 --publish=always",
|
||||
"win32": "electron-builder -w --x64 --publish=always",
|
||||
"dist": "electron-builder",
|
||||
"beta": "electron-builder --windows portable"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "8.2.1",
|
||||
"electron-builder": "^21.2.0"
|
||||
"electron": "8.2.4",
|
||||
"electron-builder": "^21.2.0",
|
||||
"electron-notarize": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-updater": "^4.3.1"
|
||||
}
|
||||
}
|
||||
|
15
scripts/notarize.js
Normal file
15
scripts/notarize.js
Normal file
@ -0,0 +1,15 @@
|
||||
const { notarize } = require('electron-notarize');
|
||||
|
||||
exports.default = async function notarizing(context) {
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
if (electronPlatformName !== 'darwin') return;
|
||||
|
||||
const appName = context.packager.appInfo.productFilename;
|
||||
|
||||
return await notarize({
|
||||
appBundleId: 'net.blockbench.blockbench',
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLEID,
|
||||
appleIdPassword: process.env.APPLEIDPASS,
|
||||
});
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user