diff -Nru mm3d-1.3.13/ChangeLog mm3d-1.3.14/ChangeLog --- mm3d-1.3.13/ChangeLog 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/ChangeLog 2023-04-23 07:02:24.000000000 +0000 @@ -1,8 +1,35 @@ Maverick Model 3D releases published by Zack Middleton. +Changes for 1.3.14 (2023-04-23) + General + Enable Qt HiDPI support by default and fix a few layout issues + Add Offset by Normal command to move vertex along averge normal + Make Duplicate command keep all joint influences + Make Edge Divide command set group and texture coords + Make Select Vertex tool automatically select and unselect triangles + Select new face made by Make Face From Vertices + Make texture coord window to reset map scheme on selection change + Fix texture coord window displaying last texture if no triangle has a texture + Merge Model / Import Animations + Add support for frame animations to Import Animations + Make Merge Model copy frame animation FPS + Make Merge Model and Import Animations copy looping setting + Fix Merge Model and Import Animations to set skeletal animation FPS on the correct animation + Background Image + Fix model using background image with Canvas mode Flat + Fix model viewports not updating immediately after setting background image + Fix drawing left/right brackground image in some cases + Fix background image not blending in some cases + Model Formats + cal3d + Add support for exporting cal3d .cfg files + mm3d + Fix writing background image filename + GNU/Linux + Update Flatpak runtime to org.kde.Platform 5.15-22.08 + Changes for 1.3.13 (2021-12-20) General - Add GameMaker Studio .d3d model import/export Add Clear Rotation/Translation Keyframes to Animation menu Add Base Point to Model Merge Add filename to Plugins window @@ -12,7 +39,7 @@ Make copy/paste skeleton animation frame copy interpolated keyframes Make paste animation frame select what was paste Make new animations default to non-looping - Switch from QGLWidget to QOpenGLWidget (needed for Wayland on Linux, breaks Windows with OpenGL 1.1) + Switch from QGLWidget to QOpenGLWidget (needed for Wayland on GNU/Linux, breaks Windows with OpenGL 1.1) Generate HTML manual using C instead of Perl with HTML::Template module Fix merged points in frame animations Fix crash if merging model when existing has a 0-frame animation @@ -26,6 +53,8 @@ Fix Qt translations (qt_xx.qm) not being used Fix hundreds of compiler warnings Model Formats + d3d (new) + Add GameMaker Studio .d3d model import/export iqe Remove option to disable saving points in animations (IQM SDK would use identity, not bind pose) md2 @@ -42,12 +71,12 @@ obj Fix crash if some MTL keywords are before newmtl Fix crash for out of bounds texcoord index - Linux + GNU/Linux Add AppStream metadata and install icons into modern file path Add ability to build as a Flatpak Don't create 'shared' plugins symlink anymore (to allow multiple install paths) Rename mimetype from application/x-mm3d to model/x-mm3d - Fix locating Qt translations on Linux + Fix locating Qt translations on GNU/Linux Windows Support UTF-16 paths for install path and appdata on Windows Make building using MinGW on Debian use POSIX thread model so it uses the same GCC run-time as Qt @@ -56,7 +85,7 @@ macOS Add system and Qt translations to macOS AppBundle Add `make appbundle` to Makefile.generic - Add support for cross-compiling from Linux using osxcross + Add support for cross-compiling from GNU/Linux using osxcross Renamed macOS configure `make mm3d.app` target to `make appbundle` Build Note Moved autosetup.sh to autogen.sh to match defacto naming convention diff -Nru mm3d-1.3.13/configure.ac mm3d-1.3.14/configure.ac --- mm3d-1.3.13/configure.ac 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/configure.ac 2023-04-23 07:02:24.000000000 +0000 @@ -9,8 +9,8 @@ dnl Makefile.am (for Contents/PlugIns/mm3d/x.x) dnl plugins/Makefile.am (for plugins/x.x) -AC_INIT([mm3d], [1.3.13]) -AM_INIT_AUTOMAKE +AC_INIT([mm3d], [1.3.14]) +AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) diff -Nru mm3d-1.3.13/debian/changelog mm3d-1.3.14/debian/changelog --- mm3d-1.3.13/debian/changelog 2021-12-22 04:30:37.000000000 +0000 +++ mm3d-1.3.14/debian/changelog 2023-06-12 07:51:11.000000000 +0000 @@ -1,3 +1,18 @@ +mm3d (1.3.14-2) unstable; urgency=medium + + * Upload to unstable. + * d/control: rename Recommends to Suggests. + + -- Gürkan Myczko Mon, 12 Jun 2023 09:51:11 +0200 + +mm3d (1.3.14-1) experimental; urgency=medium + + * New upstream version. + * Bump standards version to 4.6.2. + * d/copyright: bump years. + + -- Gürkan Myczko Sun, 23 Apr 2023 14:26:21 +0200 + mm3d (1.3.13-1) unstable; urgency=medium * New upstream version. diff -Nru mm3d-1.3.13/debian/control mm3d-1.3.14/debian/control --- mm3d-1.3.13/debian/control 2021-12-22 04:30:37.000000000 +0000 +++ mm3d-1.3.14/debian/control 2023-06-12 07:51:11.000000000 +0000 @@ -3,8 +3,16 @@ Priority: optional Maintainer: Debian Multimedia Maintainers Uploaders: Gürkan Myczko -Build-Depends: debhelper-compat (= 13), qtchooser, qtbase5-dev, qt5-qmake, libqt5opengl5-desktop-dev, pkg-config, libhtml-template-perl, qttools5-dev-tools -Standards-Version: 4.6.0 +Build-Depends: + debhelper-compat (= 13), + qtchooser, + qtbase5-dev, + qt5-qmake, + libqt5opengl5-desktop-dev, + pkg-config, + libhtml-template-perl, + qttools5-dev-tools +Standards-Version: 4.6.2 Rules-Requires-Root: no Vcs-Git: https://salsa.debian.org/multimedia-team/mm3d.git Vcs-Browser: https://salsa.debian.org/multimedia-team/mm3d @@ -13,7 +21,7 @@ Package: mm3d Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Recommends: blender, yafray, wings3d +Suggests: blender, yafray, wings3d Description: OpenGL based 3D model editor This is an OpenGL based 3D model editor that works with triangle-based models. It supports multi-level undo, skeletal animations, simple texturing, diff -Nru mm3d-1.3.13/debian/copyright mm3d-1.3.14/debian/copyright --- mm3d-1.3.13/debian/copyright 2021-12-22 04:30:37.000000000 +0000 +++ mm3d-1.3.14/debian/copyright 2023-04-23 12:27:28.000000000 +0000 @@ -8,7 +8,7 @@ Johannes Kroll (Texture reload, Snap Together commands) Ainsley Preira (various bug fixes, feature enhancements) Russel Valentine (initial MD3 filter) - 2008-2021 Zack Middleton + 2008-2023 Zack Middleton License: GPL-2-or-later License: GPL-2-or-later @@ -30,5 +30,5 @@ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". Files: debian/* -Copyright: 2007-2008,2018-2021 Gürkan Myczko +Copyright: 2007-2008,2018-2023 Gürkan Myczko License: GPL-2-or-later diff -Nru mm3d-1.3.13/desktop/moe.clover.mm3d.metainfo.xml mm3d-1.3.14/desktop/moe.clover.mm3d.metainfo.xml --- mm3d-1.3.13/desktop/moe.clover.mm3d.metainfo.xml 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/desktop/moe.clover.mm3d.metainfo.xml 2023-04-23 07:02:24.000000000 +0000 @@ -37,6 +37,7 @@ mm3d + diff -Nru mm3d-1.3.13/doc/html/Makefile.am mm3d-1.3.14/doc/html/Makefile.am --- mm3d-1.3.13/doc/html/Makefile.am 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/doc/html/Makefile.am 2023-04-23 07:02:24.000000000 +0000 @@ -42,6 +42,7 @@ olh_iqeprompt.htm \ olh_quakemd3prompt.htm \ olh_smdprompt.htm \ + olh_offsetwin.htm \ olh_painttexturewin.htm \ olh_pointwin.htm \ olh_pluginwin.htm \ @@ -100,6 +101,7 @@ olh_iqeprompt.html \ olh_quakemd3prompt.html \ olh_smdprompt.html \ + olh_offsetwin.html \ olh_painttexturewin.html \ olh_pointwin.html \ olh_pluginwin.html \ diff -Nru mm3d-1.3.13/doc/html/olh_commands.htm mm3d-1.3.14/doc/html/olh_commands.htm --- mm3d-1.3.13/doc/html/olh_commands.htm 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/doc/html/olh_commands.htm 2023-04-23 07:02:24.000000000 +0000 @@ -12,6 +12,7 @@
  • Snap Vertices Together
  • Make Face From Vertices
  • Select Free Vertices
  • +
  • Offset by Normal
  • @@ -211,6 +212,22 @@

    Keyboard shortcuts

    +
      +
    • None +
    + + +

    Offset by Normal

    + +

    Overview

    +

    + Offset by Normal opens a window to interactively move the + selected vertices along the vertex normal. This only affects + vertices that are connected to a triangle. See the + Offset by Normal Window for details. +

    + +

    Keyboard shortcuts

    • None
    diff -Nru mm3d-1.3.13/doc/html/olh_index.htm mm3d-1.3.14/doc/html/olh_index.htm --- mm3d-1.3.13/doc/html/olh_index.htm 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/doc/html/olh_index.htm 2023-04-23 07:02:24.000000000 +0000 @@ -93,6 +93,7 @@
  • Snap Vertices Together
  • Make Face From Vertices
  • Select Free Vertices
  • +
  • Offset by Normal
  • diff -Nru mm3d-1.3.13/doc/html/olh_offsetwin.htm mm3d-1.3.14/doc/html/olh_offsetwin.htm --- mm3d-1.3.13/doc/html/olh_offsetwin.htm 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/doc/html/olh_offsetwin.htm 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,38 @@ +

    Offset by Normal Window

    + +

    + The Offset by Normal Window is used to interactively move the + selected vertices along the vertex normal. This only affects + vertices that are connected to a triangle. + It is made up of a text entry box for the max distance with a slider + and a text entry box for the percent value. +

    + +

    + The vertex normal is the averaged direction of connected triangles. + It is not affected by the group smoothing and max angle. +

    + +

    + The offset to move the selected vertexes is calculated by the + max distance scaled by the percent value. The percent value slider + allows for better interactivity. +

    + +

    + The max distance is the value to move when the slider is set to 100%. +

    + +

    + The percent value ranges from -100 to 100 and starts at 0. + A value of zero is the starting shape of the selected + mesh. + You can drag the slider left to decrease the value, or drag it right to + increase the value. You can also change the value by typing a new + value into the text box next to the slider. +

    + +

    + Press Ok to keep your changes or press Cancel + to ignore any changes. +

    diff -Nru mm3d-1.3.13/doc/html/olh_offsetwin.page mm3d-1.3.14/doc/html/olh_offsetwin.page --- mm3d-1.3.13/doc/html/olh_offsetwin.page 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/doc/html/olh_offsetwin.page 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,2 @@ +PAGE_TITLE=Offset by Normal Window +PAGE_CONTENT= -Copyright © 2015-2021, Zack Middleton +Copyright © 2015-2023, Zack Middleton diff -Nru mm3d-1.3.13/.github/workflows/build.yml mm3d-1.3.14/.github/workflows/build.yml --- mm3d-1.3.13/.github/workflows/build.yml 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/.github/workflows/build.yml 2023-04-23 07:02:24.000000000 +0000 @@ -56,7 +56,10 @@ linux-flatpak: name: Flatpak (Linux, GCC) - runs-on: ubuntu-latest + # flatpak-builder fails to download glu on ubuntu-22.04 + # (glu specified in mm3d-flatpak.yml) + # see https://github.com/flatpak/flatpak-builder/issues/468 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 with: @@ -66,7 +69,6 @@ sudo apt update sudo apt install flatpak flatpak-builder flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo - flatpak install --user -y org.kde.Platform//5.15 flathub org.kde.Sdk//5.15 - name: Set version for the Flatpak run: | # if not a tag, add version @@ -75,7 +77,7 @@ fi cat desktop/moe.clover.mm3d.metainfo.xml - name: flatpak-builder - run: flatpak-builder --repo=flatpak-repo --state-dir=flatpak-state flatpak-build mm3d-flatpak.yaml + run: flatpak-builder --user --install-deps-from=flathub --repo=flatpak-repo --state-dir=flatpak-state flatpak-build mm3d-flatpak.yaml - name: flatpak build-bundle run: flatpak build-bundle flatpak-repo moe.clover.mm3d-$(git describe|sed 's/^v\([0-9]\)/\1/').flatpak moe.clover.mm3d - name: flatpak install diff -Nru mm3d-1.3.13/Makefile.generic mm3d-1.3.14/Makefile.generic --- mm3d-1.3.13/Makefile.generic 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/Makefile.generic 2023-04-23 07:02:24.000000000 +0000 @@ -519,6 +519,7 @@ ${B}/qtui/ms3dprompt.base.h \ ${B}/qtui/objprompt.base.h \ ${B}/qtui/smdprompt.base.h \ + ${B}/qtui/offsetwin.base.h \ ${B}/qtui/pluginwin.base.h \ ${B}/qtui/statusbar.base.h \ ${B}/qtui/texturecoord.base.h \ @@ -575,6 +576,7 @@ ${B}/implui/ms3dprompt.moc.cc \ ${B}/implui/objprompt.moc.cc \ ${B}/implui/smdprompt.moc.cc \ + ${B}/implui/offsetwin.moc.cc \ ${B}/implui/pluginwin.moc.cc \ ${B}/tools/polytoolwidget.moc.cc \ ${B}/tools/projtoolwidget.moc.cc \ @@ -642,6 +644,7 @@ ${B}/implui/ms3dprompt.moc.o \ ${B}/implui/objprompt.moc.o \ ${B}/implui/smdprompt.moc.o \ + ${B}/implui/offsetwin.moc.o \ ${B}/implui/pluginwin.moc.o \ ${B}/tools/polytoolwidget.moc.o \ ${B}/tools/projtoolwidget.moc.o \ @@ -752,6 +755,8 @@ ${B}/implui/objprompt.o \ ${B}/implui/smdprompt.o \ ${B}/implui/pluginwin.o \ + ${B}/commands/offsetcmd.o \ + ${B}/implui/offsetwin.o \ ${B}/tools/polytool.o \ ${B}/tools/polytoolwidget.o \ ${B}/tools/projtoolwidget.o \ @@ -862,6 +867,7 @@ ${B}/doc/html/olh_iqeprompt.html \ ${B}/doc/html/olh_quakemd3prompt.html \ ${B}/doc/html/olh_smdprompt.html \ + ${B}/doc/html/olh_offsetwin.html \ ${B}/doc/html/olh_painttexturewin.html \ ${B}/doc/html/olh_pointwin.html \ ${B}/doc/html/olh_pluginwin.html \ @@ -1174,11 +1180,11 @@ CFBundlePackageType APPL CFBundleShortVersionString -1.3.13 +1.3.14 CFBundleSignature ???? CFBundleVersion -1.3.13 +1.3.14 CGDisableCoalescedUpdates LSMinimumSystemVersion diff -Nru mm3d-1.3.13/mm3d-flatpak.yaml mm3d-1.3.14/mm3d-flatpak.yaml --- mm3d-1.3.13/mm3d-flatpak.yaml 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/mm3d-flatpak.yaml 2023-04-23 07:02:24.000000000 +0000 @@ -1,9 +1,13 @@ # # Flatpak manifest # +# For building the flatpak, first ensure flathub repo is added for installing the KDE runtime. +# +# flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +# # To build and install the Flatpak (requires flatpak and flatpak-builder programs): # -# flatpak-builder --user --install --force-clean --state-dir=flatpak-state flatpak-build mm3d-flatpak.yaml +# flatpak-builder --user --install --install-deps-from=flathub --force-clean --state-dir=flatpak-state flatpak-build mm3d-flatpak.yaml # # After it's installed you can remove "flatpak-state" and "flatpak-build" directories. # @@ -13,10 +17,23 @@ # # flatpak uninstall --user moe.clover.mm3d # +# +# Releases are built labeled as "stable" branch using the following: +# +# flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +# flatpak-builder --default-branch=stable --user --install-deps-from=flathub --force-clean --repo=flatpak-repo --state-dir=flatpak-state flatpak-build mm3d-flatpak.yaml +# flatpak build-bundle flatpak-repo moe.clover.mm3d-$(git describe|sed 's/^v\([0-9]\)/\1/').flatpak moe.clover.mm3d stable +# +# The release can be installed using: +# +# flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +# flatpak install --user -y moe.clover.mm3d-*.flatpak +# +# app-id: moe.clover.mm3d runtime: org.kde.Platform -runtime-version: '5.15' +runtime-version: '5.15-22.08' sdk: org.kde.Sdk command: mm3d finish-args: @@ -36,8 +53,8 @@ - "--disable-static" sources: - type: archive - url: https://mesa.freedesktop.org/archive/glu/glu-9.0.1.tar.xz - sha256: fb5a4c2dd6ba6d1c21ab7c05129b0769544e1d68e1e3b0ffecb18e73c93055bc + url: https://mesa.freedesktop.org/archive/glu/glu-9.0.2.tar.xz + sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4 cleanup: - "/include" - "/lib/*.a" diff -Nru mm3d-1.3.13/mm3d-win32-installer.nsi mm3d-1.3.14/mm3d-win32-installer.nsi --- mm3d-1.3.13/mm3d-win32-installer.nsi 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/mm3d-win32-installer.nsi 2023-04-23 07:02:24.000000000 +0000 @@ -20,8 +20,8 @@ ; See the COPYING file for full license text. -!define VERSION "1.3.13" -!define FILE_VERSION "1_3_13" +!define VERSION "1.3.14" +!define FILE_VERSION "1_3_14" Name "Maverick Model 3D ${VERSION}" OutFile "mm3d-${FILE_VERSION}-win32-installer.exe" diff -Nru mm3d-1.3.13/README mm3d-1.3.14/README --- mm3d-1.3.13/README 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -This is the README file for Maverick Model 3D - -Maverick Model 3D is a 3D model editor. It was written and tested on Linux. -It is reported to run on other Unix-like operating systems. It also runs -on Windows. See INSTALL.WIN32 for Windows-specific instructions. - -It is based on Misfit Model 3D that was developed by Kevin Worcester from 2004 -to 2009. Maverick Model 3D is maintained by Zack Middleton (zturtleman). - -The home page is here: - https://clover.moe/mm3d - -The original project's home page is here: - http://www.misfitcode.com/misfitmodel3d/ - -Maverick Model 3D requires Qt (5.x) and OpenGL support. See the INSTALL file -for details on where to get these packages. - -This program uses autoconf and automake for building from source. What this -means is that if you are lucky you can install this program with these -easy steps: - - ./autogen.sh - ./configure - make - sudo make install - -This will build a 'mm3d' executable and install it in /usr/local/bin. -Documentation will be in /usr/local/share/doc/mm3d. - -For more detailed installation instructions, see the INSTALL file. -See INSTALL.WIN32 for Windows-specific instructions. - -## Debian/Ubuntu - -Build dependencies: - - sudo apt install autoconf automake make gcc g++ qtbase5-dev qtbase5-dev-tools qttools5-dev-tools libgl1-mesa-dev - -qttranslations5-l10n can be used at run-time. - -## Fedora - -Build dependencies: - - sudo dnf install autoconf automake make gcc gcc-c++ qt5-qtbase-devel qt5-linguist mesa-libGLU-devel - -qt5-qttranslations can be used at run-time. - -## Arch Linux - -Build dependencies: - - sudo pacman -S autoconf automake make gcc qt5-base qt5-tools glu - -qt5-translations can be used at run-time. - -## macOS - -To build a "Maverick Model 3D.app" AppBundle on macOS 10.14+, -install homebrew from http://brew.sh and run the following commands. - -(I haven't tested these build steps as my MacBook Pro is limited to -macOS 10.11 and Qt 5.12+ no longer supports it.) - - brew install autoconf automake qt@5 - ./autogen.sh - ./configure --with-Qt-dir=/usr/local/Cellar/qt/5.15.2 --with-macosx-version-min=10.13 - make - make appbundle - ---with-macosx-version-min should be set to the value in -/usr/local/Cellar/qt/5.15.2/mkspecs/macx-clang/qmake.conf diff -Nru mm3d-1.3.13/README.md mm3d-1.3.14/README.md --- mm3d-1.3.13/README.md 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/README.md 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,72 @@ +Maverick Model 3D +----------------- + +Maverick Model 3D is a 3D model editor. It was written and tested on Linux. +It is reported to run on other Unix-like operating systems. It also runs +on Windows. + +It is based on [Misfit Model 3D](http://www.misfitcode.com/misfitmodel3d/) +that was developed by Kevin Worcester from 2004 to 2009. Maverick Model 3D +is maintained by Zack Middleton (zturtleman). + +The home page is here: + https://clover.moe/mm3d + +Maverick Model 3D requires Qt (5.x) and OpenGL support. See the INSTALL file +for details on where to get these packages. + +This program uses autoconf and automake for building from source. What this +means is that if you are lucky you can install this program with these +easy steps: + + ./autogen.sh + ./configure + make + sudo make install + +This will build a 'mm3d' executable and install it in /usr/local/bin. +Documentation will be in /usr/local/share/doc/mm3d. + +For more detailed installation instructions, see the INSTALL file. +See INSTALL.WIN32 for Windows-specific instructions. + +## Debian/Ubuntu + +Build dependencies: + + sudo apt install autoconf automake make gcc g++ qtbase5-dev qtbase5-dev-tools qttools5-dev-tools libgl1-mesa-dev + +qttranslations5-l10n can be used at run-time. + +## Fedora + +Build dependencies: + + sudo dnf install autoconf automake make gcc gcc-c++ qt5-qtbase-devel qt5-linguist mesa-libGLU-devel + +qt5-qttranslations can be used at run-time. + +## Arch Linux + +Build dependencies: + + sudo pacman -S autoconf automake make gcc qt5-base qt5-tools glu + +qt5-translations can be used at run-time. + +## macOS + +To build a "Maverick Model 3D.app" AppBundle on macOS 10.14+, +install homebrew from http://brew.sh and run the following commands. + +(I haven't tested these build steps as my MacBook Pro is limited to +macOS 10.11 and Qt 5.12+ no longer supports it.) + + brew install autoconf automake qt@5 + ./autogen.sh + ./configure --with-Qt-dir=/usr/local/Cellar/qt/5.15.2 --with-macosx-version-min=10.13 + make + make appbundle + +--with-macosx-version-min should be set to the value in +/usr/local/Cellar/qt/5.15.2/mkspecs/macx-clang/qmake.conf diff -Nru mm3d-1.3.13/src/commands/dupcmd.cc mm3d-1.3.14/src/commands/dupcmd.cc --- mm3d-1.3.13/src/commands/dupcmd.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/commands/dupcmd.cc 2023-04-23 07:02:24.000000000 +0000 @@ -64,6 +64,38 @@ list::iterator lit; + if ( !joints.empty() ) + { + // Duplicated joints + log_debug( "Duplicating %" PORTuSIZE " joints\n", joints.size() ); + for ( lit = joints.begin(); lit != joints.end(); lit++ ) + { + int parent = model->getBoneJointParent( *lit ); + + // TODO this will not work if parent joint comes after child + // joint. That shouldn't happen... but... + if ( model->isBoneJointSelected( parent ) ) + { + parent = jointMap[ parent ]; + } + + // If joint is root joint, assign duplicated joint to be child + // of original + if ( parent == -1 ) + { + parent = 0; + } + + double coord[3]; + double rot[3] = { 0, 0, 0 }; + model->getBoneJointCoords( *lit, coord ); + + int nj = model->addBoneJoint( model->getBoneJointName( *lit ), + coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], parent ); + jointMap[ *lit ] = nj; + } + } + if ( !tri.empty() ) { model_status( model, StatusNormal, STATUSTIME_SHORT, "%s", qApp->translate( "Command", "Selected primitives duplicated" ).toUtf8().data() ); @@ -83,6 +115,22 @@ model->setVertexFree( nv, true ); } + Model::InfluenceList il; + Model::InfluenceList::iterator it; + model->getVertexInfluences( *lit, il ); + + for ( it = il.begin(); it != il.end(); it++ ) + { + int joint = it->m_boneId; + + if ( model->isBoneJointSelected( joint ) ) + { + joint = jointMap[ joint ]; + } + + model->addVertexInfluence( nv, joint, it->m_type, it->m_weight ); + } + vertMap[ *lit ] = nv; } @@ -132,70 +180,36 @@ } - if ( !joints.empty() ) - { - - // Duplicated joints - log_debug( "Duplicating %" PORTuSIZE " joints\n", joints.size() ); - for ( lit = joints.begin(); lit != joints.end(); lit++ ) - { - int parent = model->getBoneJointParent( *lit ); - - // TODO this will not work if parent joint comes after child - // joint. That shouldn't happen... but... - if ( model->isBoneJointSelected( parent ) ) - { - parent = jointMap[ parent ]; - } - - // If joint is root joint, assign duplicated joint to be child - // of original - if ( parent == -1 ) - { - parent = 0; - } - - double coord[3]; - double rot[3] = { 0, 0, 0 }; - model->getBoneJointCoords( *lit, coord ); - - int nj = model->addBoneJoint( model->getBoneJointName( *lit ), - coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], parent ); - jointMap[ *lit ] = nj; - - // Assign duplicated vertices to duplicated bone joints - list vertlist = model->getBoneJointVertices( *lit ); - list::iterator vit; - for ( vit = vertlist.begin(); vit != vertlist.end(); vit++ ) - { - if ( model->isVertexSelected( *vit ) ) - { - model->setVertexBoneJoint( vertMap[ *vit ], nj ); - } - } - } - } - if ( !points.empty() ) { // Duplicated points log_debug( "Duplicating %" PORTuSIZE " points\n", points.size() ); for ( lit = points.begin(); lit != points.end(); lit++ ) { - int parent = model->getPointBoneJoint( *lit ); - - if ( model->isBoneJointSelected( parent ) ) - { - parent = jointMap[ parent ]; - } - double coord[3]; double rot[3] = { 0, 0, 0 }; model->getPointCoords( *lit, coord ); model->getPointRotation( *lit, rot ); int np = model->addPoint( model->getPointName( *lit ), - coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], parent ); + coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], -1 ); + + Model::InfluenceList il; + Model::InfluenceList::iterator it; + model->getPointInfluences( *lit, il ); + + for ( it = il.begin(); it != il.end(); it++ ) + { + int joint = it->m_boneId; + + if ( model->isBoneJointSelected( joint ) ) + { + joint = jointMap[ joint ]; + } + + model->addPointInfluence( np, joint, it->m_type, it->m_weight ); + } + pointMap[ *lit ] = np; } } diff -Nru mm3d-1.3.13/src/commands/edgedivcmd.cc mm3d-1.3.14/src/commands/edgedivcmd.cc --- mm3d-1.3.13/src/commands/edgedivcmd.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/commands/edgedivcmd.cc 2023-04-23 07:02:24.000000000 +0000 @@ -98,6 +98,12 @@ newVertex = model->addVertex( coord1[0], coord1[1], coord1[2] ); } + float oldST[3][2]; + for ( int i = 0; i < 3; i++ ) + { + model->getTextureCoords( tri, i, oldST[i][0], oldST[i][1] ); + } + int g = model->getTriangleGroup( tri ); int vert[3]; @@ -108,13 +114,39 @@ int newTri = model->addTriangle( vert[0], vert[1], vert[2] ); if ( g >= 0 ) { - model->addTriangleToGroup( newTri, g ); + model->addTriangleToGroup( g, newTri ); } vert[ a ] = tv[a]; vert[ b ] = newVertex; vert[ c ] = tv[c]; model->setTriangleVertices( tri, vert[0], vert[1], vert[2] ); + + float st[3][2]; + for ( int i = 0; i < 2; i++ ) + { + st[a][i] = ( oldST[a][i] + oldST[b][i] ) / 2.0f; + st[b][i] = oldST[b][i]; + st[c][i] = oldST[c][i]; + } + + for ( int i = 0; i < 3; i++ ) + { + model->setTextureCoords( newTri, i, st[i][0], st[i][1] ); + } + + for ( int i = 0; i < 2; i++ ) + { + st[a][i] = oldST[a][i]; + st[b][i] = ( oldST[a][i] + oldST[b][i] ) / 2.0f; + st[c][i] = oldST[c][i]; + } + + for ( int i = 0; i < 3; i++ ) + { + model->setTextureCoords( tri, i, st[i][0], st[i][1] ); + } + split++; } } diff -Nru mm3d-1.3.13/src/commands/makefacecmd.cc mm3d-1.3.14/src/commands/makefacecmd.cc --- mm3d-1.3.13/src/commands/makefacecmd.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/commands/makefacecmd.cc 2023-04-23 07:02:24.000000000 +0000 @@ -82,7 +82,9 @@ it++; v3 = *it; - model->addTriangle( v1, v2, v3 ); + int tri = model->addTriangle( v1, v2, v3 ); + model->selectTriangle( tri ); + return true; } else diff -Nru mm3d-1.3.13/src/commands/Makefile.am mm3d-1.3.14/src/commands/Makefile.am --- mm3d-1.3.13/src/commands/Makefile.am 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/commands/Makefile.am 2023-04-23 07:02:24.000000000 +0000 @@ -16,6 +16,7 @@ invertcmd.h \ invnormalcmd.h \ makefacecmd.h \ + offsetcmd.h \ pastecmd.h \ rotatetexcmd.h \ selectfreecmd.h \ @@ -43,6 +44,7 @@ invertcmd.cc \ invnormalcmd.cc \ makefacecmd.cc \ + offsetcmd.cc \ pastecmd.cc \ rotatetexcmd.cc \ selectfreecmd.cc \ diff -Nru mm3d-1.3.13/src/commands/offsetcmd.cc mm3d-1.3.14/src/commands/offsetcmd.cc --- mm3d-1.3.13/src/commands/offsetcmd.cc 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/src/commands/offsetcmd.cc 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,57 @@ +/* Maverick Model 3D + * + * Copyright (c) 2004-2007 Kevin Worcester + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * See the COPYING file for full license text. + */ + + +#include "menuconf.h" +#include "offsetcmd.h" + +#include "offsetwin.h" +#include "log.h" + +#include +#include + +OffsetCommand::OffsetCommand() +{ +} + +OffsetCommand::~OffsetCommand() +{ +} + +bool OffsetCommand::activated( int arg, Model * model ) +{ + OffsetWin * win = new OffsetWin( model, NULL ); + win->show(); + return true; +} + +const char * OffsetCommand::getPath() +{ + return GEOM_VERTICES_MENU; +} + +const char * OffsetCommand::getName( int arg ) +{ + return QT_TRANSLATE_NOOP( "Command", "Offset by Normal..." ); +} + diff -Nru mm3d-1.3.13/src/commands/offsetcmd.h mm3d-1.3.14/src/commands/offsetcmd.h --- mm3d-1.3.13/src/commands/offsetcmd.h 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/src/commands/offsetcmd.h 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,57 @@ +/* Maverick Model 3D + * + * Copyright (c) 2004-2007 Kevin Worcester + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * See the COPYING file for full license text. + */ + + +#ifndef __OFFSETCMD_H +#define __OFFSETCMD_H + +#include "command.h" + +#include + +class OffsetCommand : public Command +{ + public: + OffsetCommand(); + virtual ~OffsetCommand(); + + int getCommandCount() { return 1; }; + const char * getPath(); + const char * getName( int arg ); + + bool activated( int arg, Model * model ); + bool isPrimitive() { return true; }; + + protected: + void getConnected( + Model * model, int vert, + std::list & conList, + std::list & triList); + void addToList( std::list & l, int ignore, int val ); + int createMissingTriangle( Model * model, unsigned int v, + std::list & conList, std::list & triList ); + int triangleCount( Model * model, + unsigned int v1, unsigned int v2, + std::list & triList, int & tri ); +}; + +#endif // __CAPCMD_H diff -Nru mm3d-1.3.13/src/depui/modelviewport.cc mm3d-1.3.14/src/depui/modelviewport.cc --- mm3d-1.3.13/src/depui/modelviewport.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/depui/modelviewport.cc 2023-04-23 07:02:24.000000000 +0000 @@ -252,8 +252,13 @@ h = 1; } - m_viewportWidth = w; - m_viewportHeight = h; + // FIXME?: I think Qt 5.6 (or later) changed resizeGL() behavior from + // always being pixels to points that need to be scaled but I don't + // have convient access to test old Qt versions. So using w and h or + // scaling them should potentially have a Qt version check. + + m_viewportWidth = w * devicePixelRatioF(); + m_viewportHeight = h * devicePixelRatioF(); adjustViewport(); } @@ -860,6 +865,7 @@ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glEnable( GL_TEXTURE_2D ); + glEnable( GL_BLEND ); glBegin( GL_QUADS ); @@ -955,6 +961,8 @@ } glEnd(); + + glDisable( GL_BLEND ); } } } diff -Nru mm3d-1.3.13/src/depui/texwidget.cc mm3d-1.3.14/src/depui/texwidget.cc --- mm3d-1.3.13/src/depui/texwidget.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/depui/texwidget.cc 2023-04-23 07:02:24.000000000 +0000 @@ -186,8 +186,13 @@ if ( h == 0 ) h = 1; - m_viewportWidth = w; - m_viewportHeight = h; + // FIXME?: I think Qt 5.6 (or later) changed resizeGL() behavior from + // always being pixels to points that need to be scaled but I don't + // have convient access to test old Qt versions. So using w and h or + // scaling them should potentially have a Qt version check. + + m_viewportWidth = w * devicePixelRatioF(); + m_viewportHeight = h * devicePixelRatioF(); updateViewport(); } diff -Nru mm3d-1.3.13/src/implui/aboutwin.cc mm3d-1.3.14/src/implui/aboutwin.cc --- mm3d-1.3.13/src/implui/aboutwin.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/aboutwin.cc 2023-04-23 07:02:24.000000000 +0000 @@ -33,7 +33,7 @@ "

    " VERSION_STRING "


    " \ "https://clover.moe/mm3d

    " \ "Copyright © 2004-2008, Kevin Worcester
    " \ - "Copyright © 2009-2021 Zack Middleton

    " \ + "Copyright © 2009-2023 Zack Middleton

    " \ "" AboutWin::AboutWin( QWidget * parent ) diff -Nru mm3d-1.3.13/src/implui/backgroundwin.cc mm3d-1.3.14/src/implui/backgroundwin.cc --- mm3d-1.3.13/src/implui/backgroundwin.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/backgroundwin.cc 2023-04-23 07:02:24.000000000 +0000 @@ -24,6 +24,7 @@ #include "backgroundwin.h" #include "backgroundselect.h" +#include "viewpanel.h" #include "model.h" #include "log.h" #include "decalmgr.h" @@ -41,9 +42,10 @@ using std::list; using std::map; -BackgroundWin::BackgroundWin( Model * model, QWidget * parent ) +BackgroundWin::BackgroundWin( Model * model, ViewPanel * viewPanel, QWidget * parent ) : QDialog( parent ), - m_model( model ) + m_model( model ), + m_viewPanel( viewPanel ) { setAttribute( Qt::WA_DeleteOnClose ); setupUi( this ); @@ -79,6 +81,10 @@ void BackgroundWin::accept() { + if ( m_viewPanel ) { + m_viewPanel->modelUpdatedEvent(); + } + m_model->operationComplete( tr( "Background Image", "operation complete" ).toUtf8() ); QDialog::accept(); } diff -Nru mm3d-1.3.13/src/implui/backgroundwin.h mm3d-1.3.14/src/implui/backgroundwin.h --- mm3d-1.3.13/src/implui/backgroundwin.h 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/backgroundwin.h 2023-04-23 07:02:24.000000000 +0000 @@ -28,6 +28,7 @@ #include +class ViewPanel; class Model; class BackgroundSelect; @@ -36,7 +37,7 @@ Q_OBJECT public: - BackgroundWin( Model *, QWidget * parent = NULL ); + BackgroundWin( Model *, ViewPanel * viewPanel, QWidget * parent = NULL ); virtual ~BackgroundWin(); public slots: @@ -48,6 +49,7 @@ protected: Model * m_model; + ViewPanel * m_viewPanel; BackgroundSelect * m_bgSelect[6]; }; diff -Nru mm3d-1.3.13/src/implui/Makefile.am mm3d-1.3.14/src/implui/Makefile.am --- mm3d-1.3.13/src/implui/Makefile.am 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/Makefile.am 2023-04-23 07:02:24.000000000 +0000 @@ -40,6 +40,7 @@ mview.h \ newanim.h \ objprompt.h \ + offsetwin.h \ painttexturewin.h \ paintwidget.h \ pluginwin.h \ @@ -98,6 +99,7 @@ mview.moc.cc \ newanim.moc.cc \ objprompt.moc.cc \ + offsetwin.moc.cc \ pluginwin.moc.cc \ smdprompt.moc.cc \ spherifywin.moc.cc \ @@ -152,6 +154,7 @@ mview.cc \ newanim.cc \ objprompt.cc \ + offsetwin.cc \ painttexturewin.cc \ paintwidget.cc \ pluginwin.cc \ diff -Nru mm3d-1.3.13/src/implui/offsetwin.cc mm3d-1.3.14/src/implui/offsetwin.cc --- mm3d-1.3.13/src/implui/offsetwin.cc 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/src/implui/offsetwin.cc 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,147 @@ +/* Maverick Model 3D + * + * Copyright (c) 2004-2007 Kevin Worcester + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * See the COPYING file for full license text. + */ + + +#include "offsetwin.h" +#include "helpwin.h" +#include "model.h" +#include "glmath.h" +#include "decalmgr.h" +#include "log.h" + +#include +#include +#include + +#include +#include + + +OffsetWin::OffsetWin( Model * model, QWidget * parent ) + : QDialog( parent, Qt::WindowFlags() ), + m_model( model ), + m_editing( false ) +{ + setupUi( this ); + setModal( true ); + + setAttribute( Qt::WA_DeleteOnClose ); + + m_valueSlider->setMinimum( -100 ); + m_valueSlider->setMaximum( 100 ); + + m_valueEdit->setText( QString("0") ); + m_rangeEdit->setText( QString("10.00") ); + + OffsetPosition ov; + std::list vertList; + m_model->getSelectedVertices( vertList ); + std::list::iterator it; + for ( it = vertList.begin(); it != vertList.end(); it++ ) + { + ov.vert = (*it); + m_model->getVertexCoords( ov.vert, ov.coords ); + m_model->getAverageNormal( ov.vert, ov.normal ); + + // vertex not connected to a face has no normal + if ( ov.normal[0] == 0.0f && ov.normal[1] == 0.0f && ov.normal[2] == 0.0f ) { + continue; + } + + m_positions.push_back( ov ); + } +} + +OffsetWin::~OffsetWin() +{ +} + +void OffsetWin::showHelp() +{ + HelpWin * win = new HelpWin( "olh_offsetwin.html", true ); + win->show(); +} + +void OffsetWin::valueSliderChanged( int v ) +{ + log_debug( "changed\n" ); + + if ( v > 100 ) + { + v = 100; + } + if ( v < -100 ) + { + v = -100; + } + + double percent = (double) v / 100.0; + double dist = m_range * percent; + + double coords[3] = { 0.0, 0.0, 0.0 }; + OffsetPositionList::iterator it; + for ( it = m_positions.begin(); it != m_positions.end(); it++ ) + { + coords[0] = (*it).coords[0] + (*it).normal[0] * dist; + coords[1] = (*it).coords[1] + (*it).normal[1] * dist; + coords[2] = (*it).coords[2] + (*it).normal[2] * dist; + + m_model->moveVertex( (*it).vert, coords[0], coords[1], coords[2] ); + } + + DecalManager::getInstance()->modelUpdated( m_model ); + + if ( ! m_editing ) + { + QString str = QString::asprintf( "%d", v ); + m_valueEdit->setText( str ); + } +} + +void OffsetWin::valueEditChanged( const QString & str ) +{ + m_editing = true; + float v = str.toDouble(); + m_valueSlider->setValue( (int) v ); + m_editing = false; +} + +void OffsetWin::rangeEditChanged( const QString & str ) +{ + m_range = str.toDouble(); + + valueSliderChanged( m_valueSlider->value() ); +} + +void OffsetWin::accept() +{ + m_model->operationComplete( tr( "Offset by Normal", "operation complete" ).toUtf8() ); + DecalManager::getInstance()->modelUpdated( m_model ); + QDialog::accept(); +} + +void OffsetWin::reject() +{ + m_model->undoCurrent(); + DecalManager::getInstance()->modelUpdated( m_model ); + QDialog::reject(); +} diff -Nru mm3d-1.3.13/src/implui/offsetwin.h mm3d-1.3.14/src/implui/offsetwin.h --- mm3d-1.3.13/src/implui/offsetwin.h 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/src/implui/offsetwin.h 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,70 @@ +/* Maverick Model 3D + * + * Copyright (c) 2004-2007 Kevin Worcester + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * See the COPYING file for full license text. + */ + +#ifndef __OFFSETWIN_H +#define __OFFSETWIN_H + +#include "offsetwin.base.h" +#include "model.h" + +#include + +class Model; + +class OffsetWin : public QDialog, public Ui::OffsetWinBase +{ + Q_OBJECT + + public: + OffsetWin( Model * model, QWidget * parent = NULL ); + virtual ~OffsetWin(); + + public slots: + void rangeEditChanged( const QString & ); + void valueEditChanged( const QString & ); + void valueSliderChanged( int ); + + void accept(); + void reject(); + + protected: + virtual void showHelp(); + + typedef struct _OffsetPosition_t + { + int vert; + double coords[3]; + float normal[3]; + } OffsetPosition; + typedef std::list OffsetPositionList; + + Model * m_model; + double m_range; + OffsetPositionList m_positions; + + // We don't want to update the edit box if the user is typing in it + // So we set this to true when editing. When we update the slider, + // our slot will check this value. If false, it will update the edit box + bool m_editing; +}; + +#endif // __SPHERIFYWIN_H diff -Nru mm3d-1.3.13/src/implui/qtmain.cc mm3d-1.3.14/src/implui/qtmain.cc --- mm3d-1.3.13/src/implui/qtmain.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/qtmain.cc 2023-04-23 07:02:24.000000000 +0000 @@ -116,6 +116,8 @@ // (It must be set before QApplication is created) QCoreApplication::setAttribute( Qt::AA_UseDesktopOpenGL ); + QCoreApplication::setAttribute( Qt::AA_EnableHighDpiScaling ); + s_app = new ModelApp( argc, argv ); #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) diff -Nru mm3d-1.3.13/src/implui/texturecoord.cc mm3d-1.3.14/src/implui/texturecoord.cc --- mm3d-1.3.13/src/implui/texturecoord.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/texturecoord.cc 2023-04-23 07:02:24.000000000 +0000 @@ -53,7 +53,7 @@ m_inUndo( false ), m_ignoreChange( false ), m_currentDirection( 0 ), - m_currentMapScheme( 2 ) // if you change this, change the setChecked line below also + m_currentMapScheme( 0 ) { setupUi( this ); @@ -103,8 +103,6 @@ m_selectButton->setChecked( true ); m_textureWidget->setMouseOperation( TextureWidget::MouseSelect ); - m_groupButton->setChecked( true ); // if you change this, change m_currentMapScheme also - g_prefs.setDefault( "ui_texcoord_lines_color", 0xffffff ); g_prefs.setDefault( "ui_texcoord_selection_color", 0xff0000 ); @@ -180,6 +178,12 @@ void TextureCoord::initWindow() { + m_currentMapScheme = MapSchemeGroup; + m_currentDirection = 0; + m_triangleButton->setChecked( false ); + m_quadButton->setChecked( false ); + m_groupButton->setChecked( true ); + m_textureWidget->clearCoordinates(); bool foundTexture = false; @@ -204,6 +208,7 @@ if ( !foundTexture ) { log_error( "no group selected\n" ); + m_textureFrame->textureChangedEvent( 0 ); } useGroupCoordinates(); @@ -351,7 +356,7 @@ float s[3]; float t[3]; - if ( m_currentMapScheme == 2 ) + if ( m_currentMapScheme == MapSchemeGroup ) { list::iterator it; for( it = trilist.begin(); it != trilist.end(); it++ ) diff -Nru mm3d-1.3.13/src/implui/viewwin.cc mm3d-1.3.14/src/implui/viewwin.cc --- mm3d-1.3.13/src/implui/viewwin.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/implui/viewwin.cc 2023-04-23 07:02:24.000000000 +0000 @@ -315,7 +315,6 @@ m_statusBar = new StatusBar( m_model, mainWidget ); mainWidget->addWidgetToLayout( m_statusBar ); m_statusBar->setText( tr( "Press F1 for help using any window" ).toUtf8() ); - m_statusBar->setMaximumHeight( 30 ); m_animWin = new AnimWindow( m_model, false, this ); m_animWin->setObjectName( "mainwin_animwin" ); @@ -2551,15 +2550,15 @@ void ViewWindow::pluginWindowEvent() { - // pluginWin will delete itself view WDestructiveClose + // PluginWindow will delete itself PluginWindow * pluginWin = new PluginWindow(); pluginWin->show(); } void ViewWindow::backgroundWindowEvent() { - // pluginWin will delete itself view WDestructiveClose - BackgroundWin * win = new BackgroundWin( m_model ); + // BackgroundWin will delete itself + BackgroundWin * win = new BackgroundWin( m_model, m_viewPanel ); win->show(); } diff -Nru mm3d-1.3.13/src/libmm3d/cal3dfilter.cc mm3d-1.3.14/src/libmm3d/cal3dfilter.cc --- mm3d-1.3.13/src/libmm3d/cal3dfilter.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/cal3dfilter.cc 2023-04-23 07:02:24.000000000 +0000 @@ -337,6 +337,10 @@ // Assume XML file return Model::ERROR_UNSUPPORTED_VERSION; } + else if ( strcasecmp( ext, "cfg" ) == 0 ) + { + return writeCfgFile( filename, model, o ); + } // Assume Cal3D master file return writeCal3dFile( filename, model, o ); @@ -1971,6 +1975,196 @@ //------------------------------------------------------------------ // Format write functions +Model::ModelErrorE Cal3dFilter::writeCfgFile( const char * filename, Model * model, ModelFilter::Options * o ) +{ + Model::ModelErrorE err = Model::ERROR_NONE; + m_dst = openOutput( filename, err ); + DestCloser fc( m_dst ); + + if ( err != Model::ERROR_NONE ) + return err; + + std::string base = m_modelPath + "/"; + + // Use dynamic cast to determine if the object is of the proper type + // If not, create new one that we will delete later. + // + // We need to create one to make sure that the default options we + // use in the filter match the default options presented to the + // user in the dialog box. + m_options = dynamic_cast< Cal3dOptions *>( o ); + release_ptr freeOptions = NULL; + if ( !m_options ) + { + freeOptions = static_cast( getDefaultOptions() ); + m_options = freeOptions.get(); + } + + m_model->updateMetaData( "cal3d_single_mesh_file", + m_options->m_singleMeshFile ? "1" : "0" ); + m_model->updateMetaData( "cal3d_xml_material", + m_options->m_xmlMatFile ? "1" : "0" ); + + m_dst->writeString( "#\n# cal3d model configuration file\n#\n" ); + + m_dst->writeString( "# File written by Maverick Model 3D\n" ); + m_dst->writeString( "# https://clover.com/mm3d\n\n" ); + + char value[64]; + if ( m_model->getMetaData( "cal3d_path", value, sizeof(value) ) ) + { + m_dst->writePrintf( "path=%s\n", value ); + } + if ( m_model->getMetaData( "cal3d_scale", value, sizeof(value) ) ) + { + m_dst->writePrintf( "scale=%s\n", value ); + } + if ( m_model->getMetaData( "cal3d_rotate", value, sizeof(value) ) ) + { + m_dst->writePrintf( "rotate=%s\n", value ); + } + + m_dst->writeString( "\n# --- Skeleton ---\n" ); + std::string skelFile = replaceExtension( m_modelBaseName.c_str(), "csf" ); + m_dst->writePrintf( "skeleton = %s\n\n", skelFile.c_str() ); + writeSkeletonFile( (base + skelFile).c_str(), model ); + + // To write animations: + // + // * Make a map of filenames written (case-sensitive) + // and map of animations written. + // + // * Run through meta data and write file if not already + // in map. + // + // * Run through animations. If any not written, write them + // and create an animation line in the Cal3D file. + + typedef std::map AnimFileMap; + AnimFileMap fileWritten; + std::vector animWritten; + + animWritten.resize( model->getAnimCount( MODE ) ); + + m_dst->writePrintf( "# --- Animations ---\n" ); + std::string animFile; + + char keyStr[PATH_MAX]; + char valueStr[PATH_MAX]; + unsigned int mtcount = model->getMetaDataCount(); + for ( unsigned int mt = 0; mt < mtcount; mt++ ) + { + model->getMetaData( mt, keyStr, PATH_MAX, valueStr, PATH_MAX ); + if ( strncmp(keyStr, "animation_", 10 ) == 0 ) + { + animFile = valueStr; + std::string animName = removeExtension( valueStr ); + int a = findAnimation( animName ); + if ( a >= 0 && fileWritten.find(animFile) == fileWritten.end() ) + { + writeAnimationFile( (base + animFile).c_str(), model, a ); + animWritten[a] = true; + fileWritten[animFile] = true; + } + m_dst->writePrintf( "animation = %s\n", animFile.c_str() ); + } + } + + unsigned int acount = model->getAnimCount( MODE ); + for ( unsigned int a = 0; a < acount; a++ ) + { + if ( animWritten[a] == 0 ) + { + const char * animName = model->getAnimName( MODE, a ); + animFile = animName; + animFile = addExtension( animFile, "caf" ); + m_dst->writePrintf( "animation = %s\n", animFile.c_str() ); + writeAnimationFile( (base + animFile).c_str(), model, a ); + animWritten[a] = 1; + } + } + m_dst->writeString( "\n" ); + + // Create meshes split on groups, with UVs and + // normals unique to each vertex + MeshList ml; + mesh_create_list( ml, model ); + + m_dst->writeString( "# --- Meshes ---\n" ); + if ( (m_options == NULL) || m_options->m_singleMeshFile ) + { + std::string meshFile = replaceExtension( m_modelBaseName.c_str(), "cmf" ); + m_dst->writePrintf( "mesh_file = %s\n", meshFile.c_str() ); + writeMeshListFile( (base + meshFile).c_str(), model, ml ); + } + else + { + std::string meshName; + std::string meshFile; + + unsigned int meshCount = ml.size(); + unsigned int meshNum; + + typedef std::map FileMeshMap; + FileMeshMap fmm; + + string groupName; + for ( meshNum = 0; meshNum < meshCount; meshNum++ ) + { + groupName = m_model->getGroupName(ml[meshNum].group); + _strtolower( groupName ); + fmm[ groupName ].push_back( ml[meshNum] ); + } + + // Write the meshes for each group + for ( FileMeshMap::const_iterator fmm_it = fmm.begin(); + fmm_it != fmm.end(); fmm_it++ ) + { + // Get a count of how many meshes make up this group + // (probably 1, but you never know) + string groupName = fmm_it->first; + const MeshList & groupMeshList = fmm_it->second; + + // Create mesh name and filename strings + string meshName = groupName; + string meshFile = groupName + ".cmf"; + + _escapeCal3dName(meshName); + _escapeFileName(meshFile); + + // Write mesh file + m_dst->writePrintf( "mesh = %s\n", meshFile.c_str() ); + writeMeshListFile( (base + meshFile).c_str(), model, groupMeshList ); + } + } + + m_dst->writeString( "\n# --- Materials ---\n" ); + std::string matFile; + unsigned int mcount = model->getTextureCount(); + for ( unsigned int m = 0; m < mcount; m++ ) + { + const char * matName = model->getTextureName( m ); + matFile = matName; + if ( m_options && !m_options->m_xmlMatFile ) + { + matFile += ".crf"; + writeMaterialFile( (base + matFile).c_str(), model, m ); + } + else + { + matFile += ".xrf"; + writeXMaterialFile( (base + matFile).c_str(), model, m ); + } + m_dst->writePrintf( "material = %s\n", matFile.c_str() ); + } + m_dst->writeString( "\n" ); + + m_options = NULL; + + model->operationComplete( transll( QT_TRANSLATE_NOOP( "LowLevel", "Set meta data for Cal3D export" ) ).c_str() ); + + return err; +} Model::ModelErrorE Cal3dFilter::writeCal3dFile( const char * filename, Model * model, ModelFilter::Options * o ) { diff -Nru mm3d-1.3.13/src/libmm3d/cal3dfilter.h mm3d-1.3.14/src/libmm3d/cal3dfilter.h --- mm3d-1.3.13/src/libmm3d/cal3dfilter.h 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/cal3dfilter.h 2023-04-23 07:02:24.000000000 +0000 @@ -146,6 +146,7 @@ std::string readLineFile( const char * str ); // binary sub file writes + Model::ModelErrorE writeCfgFile( const char * filename, Model * model, ModelFilter::Options * o ); Model::ModelErrorE writeCal3dFile( const char * filename, Model * model, ModelFilter::Options * o ); Model::ModelErrorE writeSkeletonFile( const char * filename, Model * model ); Model::ModelErrorE writeMeshFile( const char * filename, Model * model ); diff -Nru mm3d-1.3.13/src/libmm3d/md3filter.cc mm3d-1.3.14/src/libmm3d/md3filter.cc --- mm3d-1.3.13/src/libmm3d/md3filter.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/md3filter.cc 2023-04-23 07:02:24.000000000 +0000 @@ -2082,7 +2082,7 @@ saveMatrix = getMatrixFromPoint( a, t, rootTag ).getInverse(); } list::iterator vit; - double dmax[4] = { DBL_MIN, DBL_MIN, DBL_MIN, 1 }; + double dmax[4] = { -DBL_MAX, -DBL_MAX, -DBL_MAX, 1 }; double dmin[4] = { DBL_MAX, DBL_MAX, DBL_MAX, 1 }; for ( mlit = meshes.begin(); mlit != meshes.end(); mlit++ ) { diff -Nru mm3d-1.3.13/src/libmm3d/md3filter.h mm3d-1.3.14/src/libmm3d/md3filter.h --- mm3d-1.3.13/src/libmm3d/md3filter.h 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/md3filter.h 2023-04-23 07:02:24.000000000 +0000 @@ -39,7 +39,6 @@ #define MD3_MAX_TRIANGLES 8192 #define MD3_XYZ_SCALE (1.0/64) #define DBL_MAX 1e+37 -#define DBL_MIN -1e+37 #include "modelfilter.h" #include "mesh.h" diff -Nru mm3d-1.3.13/src/libmm3d/mm3dfilter.cc mm3d-1.3.14/src/libmm3d/mm3dfilter.cc --- mm3d-1.3.13/src/libmm3d/mm3dfilter.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/mm3dfilter.cc 2023-04-23 07:02:24.000000000 +0000 @@ -2682,7 +2682,7 @@ char * filedup = strdup( fileStr.c_str() ); replaceSlash( filedup ); - utf8chrtrunc( filedup, fileStr.size()-1 ); + utf8chrtrunc( filedup, fileStr.size() ); m_dst->write( backSize ); m_dst->write( cb.flags ); diff -Nru mm3d-1.3.13/src/libmm3d/model.cc mm3d-1.3.14/src/libmm3d/model.cc --- mm3d-1.3.13/src/libmm3d/model.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/model.cc 2023-04-23 07:02:24.000000000 +0000 @@ -4020,6 +4020,22 @@ } } +bool Model::getAverageNormal( unsigned v, float *normal ) const +{ + if ( v < m_vertices.size() ) + { + normal[0] = m_vertices[v]->m_normal[0]; + normal[1] = m_vertices[v]->m_normal[1]; + normal[2] = m_vertices[v]->m_normal[2]; + + return true; + } + else + { + return false; + } +} + bool Model::getBoneVector( unsigned joint, double * vec, const double * coord ) const { if ( joint >= m_joints.size() ) @@ -4083,6 +4099,15 @@ { LOG_PROFILE(); + std::vector::iterator vert_it; + for ( vert_it = m_vertices.begin(); vert_it != m_vertices.end(); ++vert_it ) + { + Vertex * vert = *vert_it; + vert->m_normal[0] = 0.0; + vert->m_normal[1] = 0.0; + vert->m_normal[2] = 0.0; + } + vector< vector > acl_normmap; acl_normmap.resize( m_vertices.size() ); @@ -4119,6 +4144,16 @@ tri->m_flatNormals[1] = B; tri->m_flatNormals[2] = C; + m_vertices[tri->m_vertexIndices[0]]->m_normal[0] += tri->m_flatNormals[0]; + m_vertices[tri->m_vertexIndices[0]]->m_normal[1] += tri->m_flatNormals[1]; + m_vertices[tri->m_vertexIndices[0]]->m_normal[2] += tri->m_flatNormals[2]; + m_vertices[tri->m_vertexIndices[1]]->m_normal[0] += tri->m_flatNormals[0]; + m_vertices[tri->m_vertexIndices[1]]->m_normal[1] += tri->m_flatNormals[1]; + m_vertices[tri->m_vertexIndices[1]]->m_normal[2] += tri->m_flatNormals[2]; + m_vertices[tri->m_vertexIndices[2]]->m_normal[0] += tri->m_flatNormals[0]; + m_vertices[tri->m_vertexIndices[2]]->m_normal[1] += tri->m_flatNormals[1]; + m_vertices[tri->m_vertexIndices[2]]->m_normal[2] += tri->m_flatNormals[2]; + // Accumulate for smooth normal, weighted by face angle for ( int vert = 0; vert < 3; vert++ ) { @@ -4177,6 +4212,33 @@ } } + for ( vert_it = m_vertices.begin(); vert_it != m_vertices.end(); ++vert_it ) + { + Vertex * vert = *vert_it; + double A = vert->m_normal[0]; + double B = vert->m_normal[1]; + double C = vert->m_normal[2]; + double len = sqrt((A * A) + (B * B) + (C * C)); + + if ( len > 0 ) + { + A = A / len; + B = B / len; + C = C / len; + } + else + { + // vertex not connected to triangle + A = 0.0; + B = 0.0; + C = 0.0; + } + + vert->m_normal[0] = A; + vert->m_normal[1] = B; + vert->m_normal[2] = C; + } + // Apply accumulated normals to triangles for ( unsigned g = 0; g < m_groups.size(); g++ ) diff -Nru mm3d-1.3.13/src/libmm3d/model_draw.cc mm3d-1.3.14/src/libmm3d/model_draw.cc --- mm3d-1.3.13/src/libmm3d/model_draw.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/model_draw.cc 2023-04-23 07:02:24.000000000 +0000 @@ -1009,14 +1009,14 @@ else { _defaultMaterial(); - glDisable( GL_TEXTURE_2D ); - glColor3f( 0.9, 0.9, 0.9 ); } } else { _defaultMaterial(); + glDisable( GL_TEXTURE_2D ); + glColor3f( 0.9, 0.9, 0.9 ); } glEnable( GL_LIGHT0 ); @@ -1175,6 +1175,9 @@ } } +#ifdef MM3D_EDIT + glDisable( GL_CULL_FACE ); +#endif glDisable( GL_TEXTURE_2D ); } } diff -Nru mm3d-1.3.13/src/libmm3d/model.h mm3d-1.3.14/src/libmm3d/model.h --- mm3d-1.3.13/src/libmm3d/model.h 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/model.h 2023-04-23 07:02:24.000000000 +0000 @@ -292,6 +292,7 @@ void sprint( std::string & dest ); double m_coord[3]; // Absolute vertex location + double m_normal[3]; // Average normal without group smoothing/maxAngle double m_kfCoord[3]; // Animated position bool m_selected; bool m_visible; @@ -1238,6 +1239,9 @@ bool getFlatNormal( unsigned triangleNum, float *normal ) const; float cosToPoint( unsigned triangleNum, double * point ) const; + // This does not apply the group smoothing/maxAngle, for those get triangle vertex normals. + bool getAverageNormal( unsigned vertexIndex, float *normal ) const; + void calculateNormals(); void calculateSkelNormals(); void calculateFrameNormals( unsigned anim ); diff -Nru mm3d-1.3.13/src/libmm3d/model_ops.cc mm3d-1.3.14/src/libmm3d/model_ops.cc --- mm3d-1.3.13/src/libmm3d/model_ops.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/model_ops.cc 2023-04-23 07:02:24.000000000 +0000 @@ -1028,47 +1028,53 @@ return false; } - unsigned count = model->getAnimCount( ANIMMODE_SKELETAL ); - unsigned ac1 = getAnimCount( ANIMMODE_SKELETAL ); - - if ( count == 0 ) + if ( model->getAnimCount( ANIMMODE_SKELETAL ) == 0 && model->getAnimCount( ANIMMODE_FRAME ) == 0 ) { - msg_warning( transll( QT_TRANSLATE_NOOP( "LowLevel", "Model contains no skeletal animations")).c_str() ); + msg_warning( transll( QT_TRANSLATE_NOOP( "LowLevel", "Model contains no animations")).c_str() ); return false; } + bool canAdd = canAddOrDelete(); + forceAddOrDelete( true ); + unsigned j1 = getBoneJointCount(); unsigned j2 = model->getBoneJointCount(); - - std::string mismatchWarn = transll( QT_TRANSLATE_NOOP( "LowLevel", "Model skeletons do not match" )); - if ( j1 != j2 ) + std::string skelMismatch = transll( QT_TRANSLATE_NOOP( "LowLevel", "Model skeletons do not match" )); + bool mergeSkeletal = model->getAnimCount( ANIMMODE_SKELETAL ) > 0; + if ( mergeSkeletal ) { - msg_warning( mismatchWarn.c_str() ); - return false; - } - - for ( unsigned j = 0; j < j1; j++ ) - { - if ( m_joints[ j ]->m_parent != model->m_joints[j]->m_parent ) + if ( j1 != j2 ) { - msg_warning( mismatchWarn.c_str() ); - return false; + msg_warning( skelMismatch.c_str() ); + mergeSkeletal = false; + } + else + { + for ( unsigned j = 0; j < j1; j++ ) + { + if ( m_joints[ j ]->m_parent != model->m_joints[j]->m_parent ) + { + msg_warning( skelMismatch.c_str() ); + mergeSkeletal = false; + } + } } } - bool canAdd = canAddOrDelete(); - forceAddOrDelete( true ); - // Do skeletal add + if ( mergeSkeletal ) { + unsigned count = model->getAnimCount( ANIMMODE_SKELETAL ); + for ( unsigned n = 0; n < count; n++ ) { unsigned framecount = model->getAnimFrameCount( ANIMMODE_SKELETAL, n ); unsigned index = addAnimation( ANIMMODE_SKELETAL, model->getAnimName( ANIMMODE_SKELETAL, n ) ); setAnimFrameCount( ANIMMODE_SKELETAL, index, framecount ); - setAnimFPS( ANIMMODE_SKELETAL, n, model->getAnimFPS( ANIMMODE_SKELETAL, n ) ); + setAnimFPS( ANIMMODE_SKELETAL, index, model->getAnimFPS( ANIMMODE_SKELETAL, n ) ); + setAnimLooping( ANIMMODE_SKELETAL, index, model->getAnimLooping( ANIMMODE_SKELETAL, n ) ); SkelAnim * sa = model->m_skelAnims[n]; @@ -1078,13 +1084,77 @@ { Keyframe * kf = sa->m_jointKeyframes[j][k]; - setSkelAnimKeyframe( ac1 + n, kf->m_frame, j, kf->m_isRotation, + setSkelAnimKeyframe( index, kf->m_frame, j, kf->m_isRotation, kf->m_parameter[0], kf->m_parameter[1], kf->m_parameter[2] ); } } } } + unsigned v1 = getVertexCount(); + unsigned v2 = model->getVertexCount(); + + unsigned p1 = getPointCount(); + unsigned p2 = model->getPointCount(); + + bool mergeFrame = model->getAnimCount( ANIMMODE_FRAME ) > 0; + + if ( mergeFrame ) + { + if ( v1 != v2 ) + { + msg_warning( transll( QT_TRANSLATE_NOOP( "LowLevel", "Model vertex counts do not match" )).c_str() ); + mergeFrame = false; + } + else if ( p1 != p2 ) + { + msg_warning( transll( QT_TRANSLATE_NOOP( "LowLevel", "Model point counts do not match" )).c_str() ); + mergeFrame = false; + } + } + + if ( mergeFrame ) + { + unsigned count = model->getAnimCount( ANIMMODE_FRAME ); + unsigned vertexcount = model->getVertexCount(); + unsigned pointcount = model->getPointCount(); + + for ( unsigned n = 0; n < count; n++ ) + { + unsigned framecount = model->getAnimFrameCount( ANIMMODE_FRAME, n ); + + unsigned index = addAnimation( ANIMMODE_FRAME, model->getAnimName( ANIMMODE_FRAME, n ) ); + setAnimFrameCount( ANIMMODE_FRAME, index, framecount ); + setAnimFPS( ANIMMODE_FRAME, index, model->getAnimFPS( ANIMMODE_FRAME, n ) ); + setAnimLooping( ANIMMODE_FRAME, index, model->getAnimLooping( ANIMMODE_FRAME, n ) ); + + for ( unsigned j = 0; j < framecount; j++ ) + { + for ( unsigned k = 0; k < vertexcount; k++ ) + { + double parameter[3]; + + model->getFrameAnimVertexCoords( n, j, k, + parameter[0], parameter[1], parameter[2] ); + + setFrameAnimVertexCoords( index, j, k, + parameter[0], parameter[1], parameter[2] ); + } + + for ( unsigned k = 0; k < pointcount; k++ ) + { + double parameter[3]; + + model->getFrameAnimPointCoords( n, j, k, + parameter[0], parameter[1], parameter[2] ); + + setFrameAnimPointCoords( index, j, k, + parameter[0], parameter[1], parameter[2] ); + } + } + } + } + invalidateNormals(); forceAddOrDelete( canAdd && m_frameAnims.empty() ); @@ -1493,6 +1563,8 @@ unsigned index = addAnimation( ANIMMODE_FRAME, model->getAnimName( ANIMMODE_FRAME, n ) ); setAnimFrameCount( ANIMMODE_FRAME, index, framecount ); + setAnimFPS( ANIMMODE_FRAME, index, model->getAnimFPS( ANIMMODE_FRAME, n ) ); + setAnimLooping( ANIMMODE_FRAME, index, model->getAnimLooping( ANIMMODE_FRAME, n ) ); unsigned f; @@ -1601,7 +1673,8 @@ unsigned index = addAnimation( ANIMMODE_SKELETAL, model->getAnimName( ANIMMODE_SKELETAL, n ) ); setAnimFrameCount( ANIMMODE_SKELETAL, index, framecount ); - setAnimFPS( ANIMMODE_SKELETAL, n, model->getAnimFPS( ANIMMODE_SKELETAL, n ) ); + setAnimFPS( ANIMMODE_SKELETAL, index, model->getAnimFPS( ANIMMODE_SKELETAL, n ) ); + setAnimLooping( ANIMMODE_SKELETAL, index, model->getAnimLooping( ANIMMODE_SKELETAL, n ) ); SkelAnim * sa = model->m_skelAnims[n]; @@ -1611,7 +1684,7 @@ { Keyframe * kf = sa->m_jointKeyframes[j][k]; - setSkelAnimKeyframe( ac1 + n, kf->m_frame, j + jointbase, kf->m_isRotation, + setSkelAnimKeyframe( index, kf->m_frame, j + jointbase, kf->m_isRotation, kf->m_parameter[0], kf->m_parameter[1], kf->m_parameter[2] ); } } diff -Nru mm3d-1.3.13/src/libmm3d/model_select.cc mm3d-1.3.14/src/libmm3d/model_select.cc --- mm3d-1.3.13/src/libmm3d/model_select.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/libmm3d/model_select.cc 2023-04-23 07:02:24.000000000 +0000 @@ -451,6 +451,12 @@ Vector vert; + unsigned i; + for ( i = 0; i < m_vertices.size(); i++ ) + { + m_vertices[i]->m_marked2 = false; + } + for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_selected != select ) @@ -471,13 +477,56 @@ && vert[0] >= x1 && vert[0] <= x2 && vert[1] >= y1 && vert[1] <= y2 ) { - if ( test ) - m_vertices[v]->m_selected = test->shouldSelect( m_vertices[v] ) ? select : m_vertices[v]->m_selected; - else + if ( !test || test->shouldSelect( m_vertices[v] ) ) + { m_vertices[v]->m_selected = select; + m_vertices[v]->m_marked2 = true; + } + } + } + } + + for ( unsigned t = 0; t < m_triangles.size(); t++ ) + { + if ( m_triangles[t]->m_visible ) + { + bool vertexChanged = false; + int count = 0; + + for ( int v = 0; v < 3; v++ ) + { + if ( m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_marked2 ) { + vertexChanged = true; + } + + if ( m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_selected ) + { + count++; + } + } + + if ( !vertexChanged ) + { + continue; + } + + if ( select ) + { + if ( count == 3 ) + { + m_triangles[t]->m_selected = true; + } + } + else + { + if ( count != 3 ) + { + m_triangles[t]->m_selected = false; + } } } } + endSelectionDifference(); return true; diff -Nru mm3d-1.3.13/src/mm3dcore/version.h mm3d-1.3.14/src/mm3dcore/version.h --- mm3d-1.3.13/src/mm3dcore/version.h 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/mm3dcore/version.h 2023-04-23 07:02:24.000000000 +0000 @@ -37,12 +37,12 @@ // plugins/Makefile.am (for plugins/x.x) #ifndef VERSION -#define VERSION "1.3.13" +#define VERSION "1.3.14" #endif #define VERSION_MAJOR 1 #define VERSION_MINOR 3 -#define VERSION_PATCH 13 +#define VERSION_PATCH 14 // Set to 0 for stable releases (even minor version) and 1 for // development versions (odd minor version) diff -Nru mm3d-1.3.13/src/qtui/Makefile.am mm3d-1.3.14/src/qtui/Makefile.am --- mm3d-1.3.13/src/qtui/Makefile.am 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/qtui/Makefile.am 2023-04-23 07:02:24.000000000 +0000 @@ -24,6 +24,7 @@ helpwin.ui \ iqeprompt.ui \ jointwin.ui \ + offsetwin.ui \ pointwin.ui \ painttexturewin.ui \ projectionwin.ui \ @@ -81,6 +82,7 @@ ms3dprompt.base.h \ newanim.base.h \ objprompt.base.h \ + offsetwin.base.h \ pluginwin.base.h \ smdprompt.base.h \ statusbar.base.h \ diff -Nru mm3d-1.3.13/src/qtui/offsetwin.ui mm3d-1.3.14/src/qtui/offsetwin.ui --- mm3d-1.3.13/src/qtui/offsetwin.ui 1970-01-01 00:00:00.000000000 +0000 +++ mm3d-1.3.14/src/qtui/offsetwin.ui 2023-04-23 07:02:24.000000000 +0000 @@ -0,0 +1,292 @@ + + + OffsetWinBase + + + + 0 + 0 + 500 + 129 + + + + Offset by Normal + + + + 6 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Max Distance + + + false + + + + + + + + 120 + 32767 + + + + 20 + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Percent + + + false + + + + + + + 100 + + + Qt::Horizontal + + + + + + + + 120 + 32767 + + + + + + + 20 + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 16 + 16 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Press F1 for help + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 60 + 20 + + + + + + + + Ok + + + + + + + Cancel + + + + + + + + + + m_valueEdit + m_okButton + m_cancelButton + + + + + m_okButton + clicked() + OffsetWinBase + accept() + + + 20 + 20 + + + 20 + 20 + + + + + m_cancelButton + clicked() + OffsetWinBase + reject() + + + 20 + 20 + + + 20 + 20 + + + + + m_valueSlider + valueChanged(int) + OffsetWinBase + valueSliderChanged(int) + + + 20 + 20 + + + 20 + 20 + + + + + m_valueEdit + textChanged(QString) + OffsetWinBase + valueEditChanged(QString) + + + 20 + 20 + + + 20 + 20 + + + + + m_rangeEdit + textChanged(QString) + OffsetWinBase + rangeEditChanged(QString) + + + 20 + 20 + + + 20 + 20 + + + + + diff -Nru mm3d-1.3.13/src/qtui/texturecoord.ui mm3d-1.3.14/src/qtui/texturecoord.ui --- mm3d-1.3.13/src/qtui/texturecoord.ui 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/qtui/texturecoord.ui 2023-04-23 07:02:24.000000000 +0000 @@ -416,45 +416,44 @@ Map Scheme - - - - 11 - 20 - 91 - 21 - - - - Triangle - - - - - - 11 - 47 - 91 - 21 - - - - Quad - - - - - - 11 - 74 - 91 - 21 - - - - Group - - + + + 6 + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Triangle + + + + + + + Quad + + + + + + + Group + + + + diff -Nru mm3d-1.3.13/src/stdcmds.cc mm3d-1.3.14/src/stdcmds.cc --- mm3d-1.3.13/src/stdcmds.cc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/stdcmds.cc 2023-04-23 07:02:24.000000000 +0000 @@ -41,6 +41,7 @@ #include "invnormalcmd.h" #include "subdividecmd.h" #include "makefacecmd.h" +#include "offsetcmd.h" #include "rotatetexcmd.h" #include "weldcmd.h" #include "unweldcmd.h" @@ -85,6 +86,9 @@ cmd = new SelectFreeCommand(); cmdMgr->registerCommand( cmd ); + cmd = new OffsetCommand(); + cmdMgr->registerCommand( cmd ); + // Faces cmd = new EdgeTurnCommand(); diff -Nru mm3d-1.3.13/src/win_resource.rc mm3d-1.3.14/src/win_resource.rc --- mm3d-1.3.13/src/win_resource.rc 2021-12-20 08:37:45.000000000 +0000 +++ mm3d-1.3.14/src/win_resource.rc 2023-04-23 07:02:24.000000000 +0000 @@ -25,8 +25,8 @@ A ICON "mm3d.ico" CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "win_manifest.xml" -#define VER_PRODUCTVERSION 1,3,13,0 -#define VER_PRODUCTVERSION_STR "1.3.13\0" +#define VER_PRODUCTVERSION 1,3,14,0 +#define VER_PRODUCTVERSION_STR "1.3.14\0" #ifndef DEBUG #define VER_DEBUG 0 @@ -59,7 +59,7 @@ VALUE "InternalName", "mm3d.x86" #endif // Copyright symbol (©) in Windows codepage 1252 is \xA9 - VALUE "LegalCopyright", "Copyright \xA9 2004-2008 Kevin Worcester, Copyright \xA9 2009-2021 Zack Middleton." + VALUE "LegalCopyright", "Copyright \xA9 2004-2008 Kevin Worcester, Copyright \xA9 2009-2023 Zack Middleton." END END