├── CONTRIBUTORS.md ├── install ├── win-install │ ├── nifskope.svnrev.in │ ├── inst.ico │ ├── nif_file.ico │ ├── makeexe.sh │ ├── makeexe.bat │ ├── nifskope-mingw-static.nsi │ ├── nifskope-mingw-dynamic.nsi │ └── nifskope-fedora-mingw-dynamic.nsi └── linux-install │ ├── vnd.gamebryo-kf.xml │ ├── vnd.gamebryo-nif.xml │ ├── vnd.gamebryo-kfm.xml │ └── nifskope.desktop ├── res ├── icon.rc ├── qt.conf ├── icon.ico ├── skel.dat ├── icon │ ├── add.png │ ├── axes.png │ ├── bulb.png │ ├── flip.png │ ├── glow.png │ ├── load.png │ ├── node.png │ ├── play.png │ ├── redo.png │ ├── save.png │ ├── sun.png │ ├── undo.png │ ├── close.png │ ├── cloud.png │ ├── expand.png │ ├── handle.png │ ├── hidden.png │ ├── light.png │ ├── marker.png │ ├── pause.png │ ├── undock.png │ ├── bulb-off.png │ ├── collapse.png │ ├── cubemap.png │ ├── img_flag.png │ ├── img_link.png │ ├── load-view.png │ ├── normals.png │ ├── save-view.png │ ├── sizegrip.png │ ├── skinned.png │ ├── specular.png │ ├── textures.png │ ├── tonemap.png │ ├── color_wheel.png │ ├── constraint.png │ ├── cube-top-16.png │ ├── img_update.png │ ├── lightcolor.png │ ├── perspective.png │ ├── repeat-all.png │ ├── screenshot.png │ ├── silhouette.png │ ├── view-active.png │ ├── collision-ball.png │ ├── cube-front-16.png │ ├── cube-side-16.png │ ├── orthographic.png │ ├── repeat-single.png │ ├── select-object.png │ ├── select-verts.png │ ├── vertex-colors.png │ ├── button_view_walk.png │ ├── hidden-disabled.png │ ├── light-rot-vertical.png │ └── light-rot-horizontal.png ├── nifskope.icns ├── nifskope.png ├── img │ ├── havok_logo.png │ └── qhull_cone.gif ├── shaders │ ├── skybox.prog │ ├── lines.prog │ ├── selection.prog │ ├── default.prog │ ├── wireframe.prog │ ├── lines.frag │ ├── particles.prog │ ├── normals.prog │ ├── uvedit.prog │ ├── f76_effectshader.prog │ ├── fo4_effectshader.prog │ ├── sk_effectshader.prog │ ├── stf_default.prog │ ├── f76_default.prog │ ├── ob_default.prog │ ├── sk_default.prog │ ├── sk_multilayer.prog │ ├── uvedit.vert │ ├── fo4_default.prog │ ├── lines.geom │ ├── sk_msn.prog │ ├── lines.vert │ ├── uniforms.glsl │ ├── normals.geom │ ├── skybox.vert │ ├── selection.frag │ ├── particles.vert │ ├── drawline.glsl │ ├── sk_msn.vert │ ├── sk_effectshader.vert │ ├── wireframe.vert │ ├── bonetransform.glsl │ ├── particles.geom │ ├── stf_default.vert │ ├── f76_default.vert │ ├── sk_default.vert │ ├── skybox.frag │ ├── ob_default.vert │ ├── wireframe.geom │ ├── fo4_default.vert │ ├── default.vert │ ├── selection.vert │ ├── sk_effectshader.frag │ └── uvedit.frag └── style.qss ├── scripts ├── run.sh └── build_and_run.sh ├── .gitattributes ├── src ├── xml │ └── xmlconfig.h ├── ui │ ├── about_dialog.h │ ├── widgets │ │ ├── ddspreview.h │ │ ├── lightingwidget.h │ │ ├── refrbrowser.h │ │ ├── groupbox.h │ │ ├── inspect.h │ │ ├── groupbox.cpp │ │ ├── floatedit.h │ │ ├── filebrowser.h │ │ └── refrbrowser.cpp │ ├── settingsdialog.h │ ├── checkablemessagebox.h │ └── settingspane.h ├── lib │ ├── nvtristripwrapper.h │ ├── qhull.h │ └── nvtristripwrapper.cpp ├── spells │ ├── transform.h │ ├── tangentspace.h │ ├── misc.h │ ├── texture.h │ ├── skeleton.h │ ├── stringpalette.h │ ├── simplify.h │ ├── fo3only.cpp │ └── bounds.cpp ├── gl │ ├── bsshape.h │ ├── BSMesh.h │ ├── glparticles.h │ ├── glmesh.h │ ├── renderer.h │ ├── icontrollable.h │ └── glmarker.h ├── io │ └── MeshFile.h ├── message.h ├── qt5compat.hpp ├── bsamodel.h └── model │ ├── nifproxymodel.h │ └── undocommands.h ├── .editorconfig ├── lib ├── libfo76utils │ ├── README.mman-win32 │ ├── scripts │ │ ├── crctable.cpp │ │ ├── cdb_class_sort.py │ │ ├── plotsrgb.py │ │ ├── make_lut.cpp │ │ └── plotpoly.py │ ├── LICENSE │ ├── src │ │ ├── downsamp.hpp │ │ ├── bptc-tables.h │ │ ├── pbr_lut.hpp │ │ ├── jsonread.hpp │ │ ├── bits.c │ │ ├── mman.h │ │ ├── bits.h │ │ └── zlib.hpp │ └── README.detex ├── coacd.h ├── meshlet.h └── miniball │ ├── Seb_point.h │ ├── example.C │ └── Seb_debug.h ├── .gitmodules ├── .gitignore ├── .github └── workflows │ ├── qt5.yml │ └── qt5release.yml ├── .travis.yml ├── appveyor.yml ├── TROUBLESHOOTING.md ├── LICENSE.md └── README_GLTF.md /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install/win-install/nifskope.svnrev.in: -------------------------------------------------------------------------------- 1 | $WCREV$ -------------------------------------------------------------------------------- /res/icon.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "icon.ico" 2 | -------------------------------------------------------------------------------- /res/qt.conf: -------------------------------------------------------------------------------- 1 | [Platforms] 2 | WindowsArguments = dpiawareness=1 3 | -------------------------------------------------------------------------------- /res/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon.ico -------------------------------------------------------------------------------- /res/skel.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/skel.dat -------------------------------------------------------------------------------- /scripts/run.sh: -------------------------------------------------------------------------------- 1 | echo "Running executable..." 2 | ./release/NifSkope.exe 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh eol=lf 2 | *.bat eol=crlf 3 | *.cpp eol=auto 4 | *.h eol=auto 5 | -------------------------------------------------------------------------------- /res/icon/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/add.png -------------------------------------------------------------------------------- /res/icon/axes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/axes.png -------------------------------------------------------------------------------- /res/icon/bulb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/bulb.png -------------------------------------------------------------------------------- /res/icon/flip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/flip.png -------------------------------------------------------------------------------- /res/icon/glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/glow.png -------------------------------------------------------------------------------- /res/icon/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/load.png -------------------------------------------------------------------------------- /res/icon/node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/node.png -------------------------------------------------------------------------------- /res/icon/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/play.png -------------------------------------------------------------------------------- /res/icon/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/redo.png -------------------------------------------------------------------------------- /res/icon/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/save.png -------------------------------------------------------------------------------- /res/icon/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/sun.png -------------------------------------------------------------------------------- /res/icon/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/undo.png -------------------------------------------------------------------------------- /res/nifskope.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/nifskope.icns -------------------------------------------------------------------------------- /res/nifskope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/nifskope.png -------------------------------------------------------------------------------- /res/icon/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/close.png -------------------------------------------------------------------------------- /res/icon/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/cloud.png -------------------------------------------------------------------------------- /res/icon/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/expand.png -------------------------------------------------------------------------------- /res/icon/handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/handle.png -------------------------------------------------------------------------------- /res/icon/hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/hidden.png -------------------------------------------------------------------------------- /res/icon/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/light.png -------------------------------------------------------------------------------- /res/icon/marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/marker.png -------------------------------------------------------------------------------- /res/icon/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/pause.png -------------------------------------------------------------------------------- /res/icon/undock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/undock.png -------------------------------------------------------------------------------- /res/icon/bulb-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/bulb-off.png -------------------------------------------------------------------------------- /res/icon/collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/collapse.png -------------------------------------------------------------------------------- /res/icon/cubemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/cubemap.png -------------------------------------------------------------------------------- /res/icon/img_flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/img_flag.png -------------------------------------------------------------------------------- /res/icon/img_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/img_link.png -------------------------------------------------------------------------------- /res/icon/load-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/load-view.png -------------------------------------------------------------------------------- /res/icon/normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/normals.png -------------------------------------------------------------------------------- /res/icon/save-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/save-view.png -------------------------------------------------------------------------------- /res/icon/sizegrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/sizegrip.png -------------------------------------------------------------------------------- /res/icon/skinned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/skinned.png -------------------------------------------------------------------------------- /res/icon/specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/specular.png -------------------------------------------------------------------------------- /res/icon/textures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/textures.png -------------------------------------------------------------------------------- /res/icon/tonemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/tonemap.png -------------------------------------------------------------------------------- /res/img/havok_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/img/havok_logo.png -------------------------------------------------------------------------------- /res/img/qhull_cone.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/img/qhull_cone.gif -------------------------------------------------------------------------------- /res/icon/color_wheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/color_wheel.png -------------------------------------------------------------------------------- /res/icon/constraint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/constraint.png -------------------------------------------------------------------------------- /res/icon/cube-top-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/cube-top-16.png -------------------------------------------------------------------------------- /res/icon/img_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/img_update.png -------------------------------------------------------------------------------- /res/icon/lightcolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/lightcolor.png -------------------------------------------------------------------------------- /res/icon/perspective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/perspective.png -------------------------------------------------------------------------------- /res/icon/repeat-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/repeat-all.png -------------------------------------------------------------------------------- /res/icon/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/screenshot.png -------------------------------------------------------------------------------- /res/icon/silhouette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/silhouette.png -------------------------------------------------------------------------------- /res/icon/view-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/view-active.png -------------------------------------------------------------------------------- /res/icon/collision-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/collision-ball.png -------------------------------------------------------------------------------- /res/icon/cube-front-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/cube-front-16.png -------------------------------------------------------------------------------- /res/icon/cube-side-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/cube-side-16.png -------------------------------------------------------------------------------- /res/icon/orthographic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/orthographic.png -------------------------------------------------------------------------------- /res/icon/repeat-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/repeat-single.png -------------------------------------------------------------------------------- /res/icon/select-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/select-object.png -------------------------------------------------------------------------------- /res/icon/select-verts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/select-verts.png -------------------------------------------------------------------------------- /res/icon/vertex-colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/vertex-colors.png -------------------------------------------------------------------------------- /install/win-install/inst.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/install/win-install/inst.ico -------------------------------------------------------------------------------- /res/icon/button_view_walk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/button_view_walk.png -------------------------------------------------------------------------------- /res/icon/hidden-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/hidden-disabled.png -------------------------------------------------------------------------------- /install/win-install/nif_file.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/install/win-install/nif_file.ico -------------------------------------------------------------------------------- /res/icon/light-rot-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/light-rot-vertical.png -------------------------------------------------------------------------------- /res/icon/light-rot-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo76utils/nifskope/HEAD/res/icon/light-rot-horizontal.png -------------------------------------------------------------------------------- /res/shaders/skybox.prog: -------------------------------------------------------------------------------- 1 | # skybox shader 2 | 3 | # never enabled on models 4 | 5 | shaders skybox.vert skybox.frag 6 | -------------------------------------------------------------------------------- /res/shaders/lines.prog: -------------------------------------------------------------------------------- 1 | # line shader 2 | 3 | # never enabled on models by default 4 | 5 | shaders lines.vert lines.geom lines.frag 6 | -------------------------------------------------------------------------------- /res/shaders/selection.prog: -------------------------------------------------------------------------------- 1 | # selection shader 2 | 3 | # never enabled on models by default 4 | 5 | shaders selection.vert selection.frag 6 | -------------------------------------------------------------------------------- /res/shaders/default.prog: -------------------------------------------------------------------------------- 1 | # Default shader for Morrowind and other games 2 | 3 | check BSVersion == 0 4 | 5 | shaders default.vert default.frag 6 | -------------------------------------------------------------------------------- /res/shaders/wireframe.prog: -------------------------------------------------------------------------------- 1 | # wireframe shader 2 | 3 | # never enabled on models by default 4 | 5 | shaders wireframe.vert wireframe.geom lines.frag 6 | -------------------------------------------------------------------------------- /res/shaders/lines.frag: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | in vec4 C; 4 | 5 | out vec4 fragColor; 6 | 7 | void main() 8 | { 9 | fragColor = C; 10 | } 11 | -------------------------------------------------------------------------------- /res/shaders/particles.prog: -------------------------------------------------------------------------------- 1 | # Particle shader 2 | 3 | # never enabled on models by default 4 | 5 | shaders particles.vert particles.geom default.frag 6 | -------------------------------------------------------------------------------- /res/shaders/normals.prog: -------------------------------------------------------------------------------- 1 | # shader for drawing normals and tangents 2 | 3 | # never enabled on models by default 4 | 5 | shaders wireframe.vert normals.geom lines.frag 6 | -------------------------------------------------------------------------------- /res/shaders/uvedit.prog: -------------------------------------------------------------------------------- 1 | # shader for rendering the texture and grid in the UV editor 2 | 3 | # never enabled on models by default 4 | 5 | shaders uvedit.vert uvedit.frag 6 | -------------------------------------------------------------------------------- /scripts/build_and_run.sh: -------------------------------------------------------------------------------- 1 | echo "Running qmake6..." 2 | qmake6 NifSkope.pro 3 | 4 | echo "Building project..." 5 | make -j8 6 | 7 | echo "Running executable..." 8 | ./release/NifSkope.exe 9 | -------------------------------------------------------------------------------- /res/shaders/f76_effectshader.prog: -------------------------------------------------------------------------------- 1 | # effect shader 2 | 3 | # Fallout 76 4 | check BSVersion >= 151 5 | check BSVersion < 170 6 | check BSEffectShaderProperty 7 | 8 | shaders f76_default.vert f76_effectshader.frag 9 | -------------------------------------------------------------------------------- /res/shaders/fo4_effectshader.prog: -------------------------------------------------------------------------------- 1 | # effect shader 2 | 3 | # Fallout 4 4 | check BSVersion >= 130 5 | check BSVersion <= 139 6 | check BSEffectShaderProperty 7 | 8 | shaders fo4_default.vert fo4_effectshader.frag 9 | -------------------------------------------------------------------------------- /src/xml/xmlconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef XMLCONFIG_H 2 | #define XMLCONFIG_H 3 | 4 | #include 5 | 6 | #define XMLTMPL QLatin1String("#T#") 7 | #define XMLARG QLatin1String("#ARG#") 8 | 9 | #endif // XMLCONFIG_H 10 | -------------------------------------------------------------------------------- /res/shaders/sk_effectshader.prog: -------------------------------------------------------------------------------- 1 | # normal mapping, vertex colors -> emissive 2 | 3 | # Skyrim 4 | check BSVersion >= 83 5 | check BSVersion <= 100 6 | check BSEffectShaderProperty 7 | 8 | shaders sk_effectshader.vert sk_effectshader.frag 9 | -------------------------------------------------------------------------------- /res/shaders/stf_default.prog: -------------------------------------------------------------------------------- 1 | # default shader 2 | 3 | # Starfield 4 | check BSVersion >= 170 5 | check BSGeometry 6 | checkgroup begin or 7 | check BSLightingShaderProperty 8 | check BSEffectShaderProperty 9 | checkgroup end 10 | 11 | shaders stf_default.vert stf_default.frag 12 | -------------------------------------------------------------------------------- /install/linux-install/vnd.gamebryo-kf.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamebryo game engine animation 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{h,cpp}] 4 | indent_size = 4 5 | indent_style = tab 6 | 7 | [*.{pro,pri}] 8 | indent_size = 4 9 | indent_style = tab 10 | 11 | [*.ui] 12 | indent_size = 1 13 | indent_style = space 14 | 15 | [*.{frag,prog,vert}] 16 | indent_size = 4 17 | indent_style = tab 18 | -------------------------------------------------------------------------------- /install/linux-install/vnd.gamebryo-nif.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamebryo (NetImmerse) game engine mesh 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /install/linux-install/vnd.gamebryo-kfm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gamebryo (NetImmerse) game engine animation 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /install/linux-install/nifskope.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=NifSkope 3 | Comment=Edit nif files 4 | Exec=nifskope 5 | Icon=nifskope 6 | Terminal=false 7 | Type=Application 8 | Categories=Graphics;3DGraphics;Qt; 9 | Encoding=UTF-8 10 | MimeType=application/vnd.gamebryo-nif;application/vnd.gamebryo-kf;application/vnd.gamebryo-kfm; 11 | -------------------------------------------------------------------------------- /res/shaders/f76_default.prog: -------------------------------------------------------------------------------- 1 | # default shader 2 | 3 | # Fallout 76 4 | check BSVersion >= 151 5 | check BSVersion < 170 6 | check BSLightingShaderProperty 7 | checkgroup begin or 8 | check BSTriShape 9 | check BSSubIndexTriShape 10 | check BSMeshLODTriShape 11 | checkgroup end 12 | 13 | shaders f76_default.vert f76_default.frag 14 | -------------------------------------------------------------------------------- /lib/libfo76utils/README.mman-win32: -------------------------------------------------------------------------------- 1 | mman-win32 2 | ========== 3 | 4 | mman library for Windows. mirror of https://code.google.com/p/mman-win32/ 5 | 6 | A light implementation of the mmap functions for MinGW. 7 | 8 | The mmap-win32 library implements a wrapper for mmap functions around the memory mapping Windows API. 9 | 10 | License: MIT License 11 | -------------------------------------------------------------------------------- /src/ui/about_dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef ABOUT_H 2 | #define ABOUT_H 3 | 4 | #include "ui_about_dialog.h" 5 | 6 | #include 7 | 8 | 9 | class AboutDialog : public QDialog 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | AboutDialog( QWidget * parent = nullptr ); 15 | 16 | private: 17 | Ui::AboutDialog ui; 18 | }; 19 | 20 | 21 | #endif // ABOUT_H 22 | -------------------------------------------------------------------------------- /res/shaders/ob_default.prog: -------------------------------------------------------------------------------- 1 | # Oblivion and Fallout 3/New Vegas 2 | 3 | check BSVersion < 83 4 | check BSVersion > 0 5 | 6 | checkgroup begin or 7 | check NiTexturingProperty 8 | check BSShaderPPLightingProperty 9 | check BSShaderNoLightingProperty 10 | check Lighting30ShaderProperty 11 | check TallGrassShaderProperty 12 | checkgroup end 13 | 14 | shaders ob_default.vert ob_default.frag 15 | -------------------------------------------------------------------------------- /res/shaders/sk_default.prog: -------------------------------------------------------------------------------- 1 | # default shader 2 | 3 | # Skyrim 4 | check BSVersion >= 83 5 | check BSVersion <= 100 6 | check BSLightingShaderProperty 7 | check BSLightingShaderProperty/Shader Type != 11 8 | checkgroup begin or 9 | check NiTriBasedGeomData/Has Normals == 1 10 | check BSTriShape/Vertex Desc & 0x800000000000 11 | checkgroup end 12 | 13 | shaders sk_default.vert sk_default.frag 14 | -------------------------------------------------------------------------------- /res/shaders/sk_multilayer.prog: -------------------------------------------------------------------------------- 1 | # multi-layer parallax 2 | 3 | # Skyrim 4 | check BSVersion >= 83 5 | check BSVersion <= 100 6 | check BSLightingShaderProperty 7 | check BSLightingShaderProperty/Shader Type == 11 8 | checkgroup begin or 9 | check NiTriBasedGeomData/Has Normals == 1 10 | check BSTriShape/Vertex Desc & 0x800000000000 11 | checkgroup end 12 | 13 | shaders sk_default.vert sk_multilayer.frag 14 | -------------------------------------------------------------------------------- /res/shaders/uvedit.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec2 texCoord; 4 | 5 | uniform vec4 viewScaleAndOffset; 6 | 7 | layout ( location = 7 ) in vec2 multiTexCoord0; 8 | 9 | void main() 10 | { 11 | vec2 offs = multiTexCoord0; 12 | 13 | gl_Position = vec4( offs * vec2( 2.0, -2.0 ) + vec2( -1.0, 1.0 ), vec2( 1.0 ) ); 14 | 15 | texCoord = offs * viewScaleAndOffset.xy + viewScaleAndOffset.zw; 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/nvtristripwrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef NVTRISTRIP_WRAPPER_H 2 | #define NVTRISTRIP_WRAPPER_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | class Triangle; 9 | 10 | QVector > stripify( const QVector & triangles, bool stitch = true ); 11 | QVector triangulate( const QVector & strips ); 12 | QVector triangulate( const QVector< QVector > & strips ); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /res/shaders/fo4_default.prog: -------------------------------------------------------------------------------- 1 | # default shader 2 | 3 | # Fallout 4 4 | check BSVersion >= 130 5 | check BSVersion <= 139 6 | check BSLightingShaderProperty 7 | #check BSLightingShaderProperty/Shader Type != 1 8 | #check BSLightingShaderProperty/Shader Type != 16 9 | check BSLightingShaderProperty/Shader Type != 18 10 | checkgroup begin or 11 | check BSTriShape 12 | check BSSubIndexTriShape 13 | check BSMeshLODTriShape 14 | checkgroup end 15 | 16 | shaders fo4_default.vert fo4_default.frag 17 | -------------------------------------------------------------------------------- /res/shaders/lines.geom: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | layout ( lines ) in; 4 | layout ( triangle_strip, max_vertices = 4 ) out; 5 | 6 | #include "uniforms.glsl" 7 | 8 | in vec4 vsColor[]; 9 | out vec4 C; 10 | 11 | #include "drawline.glsl" 12 | 13 | void main() 14 | { 15 | C = vec4( vsColor[0].rgb, vsColor[0].a * min( lineWidth, 1.0 ) ); 16 | 17 | vec4 p0 = projectionMatrix * gl_in[0].gl_Position; 18 | vec4 p1 = projectionMatrix * gl_in[1].gl_Position; 19 | 20 | drawLine( p0, p1 ); 21 | } 22 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "qhull"] 2 | path = lib/qhull 3 | url = https://github.com/qhull/qhull.git 4 | [submodule "lib/gli"] 5 | path = lib/gli 6 | url = https://github.com/g-truc/gli.git 7 | [submodule "build/docsys/kfmxml"] 8 | path = build/docsys/kfmxml 9 | url = https://github.com/niftools/kfmxml.git 10 | [submodule "build/docsys/nifxml"] 11 | path = build/docsys/nifxml 12 | url = https://github.com/niftools/nifxml.git 13 | [submodule "lib/meshoptimizer"] 14 | path = lib/meshoptimizer 15 | url = https://github.com/zeux/meshoptimizer.git 16 | -------------------------------------------------------------------------------- /res/shaders/sk_msn.prog: -------------------------------------------------------------------------------- 1 | # model space normal mapping 2 | 3 | # Skyrim 4 | check BSVersion >= 83 5 | check BSVersion <= 130 6 | 7 | checkgroup begin or 8 | # Skyrim 9 | checkgroup begin 10 | check BSLightingShaderProperty 11 | check NiTriBasedGeomData 12 | check NiTriBasedGeomData/Has Normals == 0 13 | checkgroup end 14 | # SSE 15 | checkgroup begin 16 | check BSLightingShaderProperty 17 | check BSTriShape 18 | check not BSTriShape/Vertex Desc & 0x800000000000 19 | checkgroup end 20 | checkgroup end 21 | 22 | shaders sk_msn.vert sk_msn.frag 23 | -------------------------------------------------------------------------------- /res/shaders/lines.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec4 vsColor; 4 | 5 | uniform mat4 modelViewMatrix; 6 | 7 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 8 | uniform vec4 highlightColor; 9 | 10 | layout ( location = 0 ) in vec3 vertexPosition; 11 | layout ( location = 1 ) in vec4 vertexColor; 12 | 13 | void main() 14 | { 15 | vec4 v = vec4( vertexPosition, 1.0 ); 16 | 17 | gl_Position = modelViewMatrix * v; 18 | 19 | vsColor = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 20 | } 21 | -------------------------------------------------------------------------------- /src/spells/transform.h: -------------------------------------------------------------------------------- 1 | #ifndef SP_TRANSFORM_H 2 | #define SP_TRANSFORM_H 3 | 4 | #include "spellbook.h" 5 | 6 | class spApplyTransformation final : public Spell 7 | { 8 | public: 9 | QString name() const override final { return Spell::tr( "Apply" ); } 10 | QString page() const override final { return Spell::tr( "Transform" ); } 11 | 12 | bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final; 13 | static void cast_Starfield( NifModel * nif, const QModelIndex & index ); 14 | QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /res/shaders/uniforms.glsl: -------------------------------------------------------------------------------- 1 | layout ( std140 ) uniform globalUniforms 2 | { 3 | mat3 viewMatrix; // rotation part of view transform 4 | mat3 envMapRotation; // view space to environment map 5 | mat4 projectionMatrix; 6 | vec4 lightSourcePosition[3]; 7 | vec4 lightSourceDiffuse[3]; 8 | vec4 lightSourceAmbient; 9 | float toneMapScale; // 1.0 = full tone mapping 10 | float brightnessScale; 11 | float glowScale; 12 | float glowScaleSRGB; 13 | ivec4 viewportDimensions; // X, Y, width, height 14 | bool doSkinning; 15 | int sceneOptions; 16 | int cubeBgndMipLevel; 17 | int sfParallaxMaxSteps; 18 | float sfParallaxScale; 19 | float sfParallaxOffset; 20 | float unusedUniform1; 21 | float unusedUniform2; 22 | }; 23 | -------------------------------------------------------------------------------- /res/shaders/normals.geom: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | layout ( points ) in; 4 | layout ( triangle_strip, max_vertices = 4 ) out; 5 | 6 | #include "uniforms.glsl" 7 | 8 | uniform int btnSelection; // 0: draw bitangent, 1: draw tangent, 2: draw normal 9 | uniform float normalLineLength; // line length in view space 10 | 11 | in mat3 btnMatrix[]; 12 | 13 | in vec4 vsColor[]; 14 | out vec4 C; 15 | 16 | #include "drawline.glsl" 17 | 18 | void main() 19 | { 20 | C = vec4( vsColor[0].rgb, vsColor[0].a * min( lineWidth, 1.0 ) ); 21 | 22 | vec4 d = vec4( btnMatrix[0][clamp( btnSelection, 0, 2 )] * normalLineLength, 0.0 ); 23 | vec4 p0 = projectionMatrix * ( gl_in[0].gl_Position - d * 0.2 ); 24 | vec4 p1 = projectionMatrix * ( gl_in[0].gl_Position + d * 0.8 ); 25 | 26 | drawLine( p0, p1 ); 27 | } 28 | -------------------------------------------------------------------------------- /src/spells/tangentspace.h: -------------------------------------------------------------------------------- 1 | #ifndef TANGENTSPACE_H 2 | #define TANGENTSPACE_H 3 | 4 | #include "spellbook.h" 5 | 6 | 7 | //! Calculates tangents and bitangents 8 | /*! 9 | * Much fun reading on this can be found at 10 | * http://en.wikipedia.org/wiki/Frenet%E2%80%93Serret_formulas 11 | */ 12 | class spTangentSpace final : public Spell 13 | { 14 | public: 15 | QString name() const override final { return Spell::tr( "Update Tangent Space" ); } 16 | QString page() const override final { return Spell::tr( "Mesh" ); } 17 | 18 | bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final; 19 | QModelIndex cast( NifModel * nif, const QModelIndex & iBlock ) override final; 20 | static void tangentSpaceSFMesh( NifModel * nif, const QModelIndex & index ); 21 | }; 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /res/shaders/skybox.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | flat out mat3 reflMatrix; 7 | 8 | #include "uniforms.glsl" 9 | 10 | uniform bool invertZAxis; 11 | 12 | layout ( location = 0 ) in vec3 vertexPosition; 13 | 14 | void main() 15 | { 16 | vec4 v = vec4( viewMatrix * vertexPosition, 1.0 ); 17 | 18 | ViewDir = vec3(-v.xy, 1.0); 19 | LightDir = lightSourcePosition[0].xyz; 20 | 21 | reflMatrix = envMapRotation; 22 | if ( invertZAxis ) { 23 | reflMatrix[0][2] *= -1.0; 24 | reflMatrix[1][2] *= -1.0; 25 | reflMatrix[2][2] *= -1.0; 26 | } 27 | 28 | if ( projectionMatrix[3][3] == 1.0 ) 29 | gl_Position = vec4(0.0, 0.0, 2.0, 1.0); // orthographic view is not supported 30 | else 31 | gl_Position = vec4( ( projectionMatrix * v ).xy / clamp( projectionMatrix[0][0], 0.001, 1.0 ), 1.0, 1.0 ); 32 | } 33 | -------------------------------------------------------------------------------- /install/win-install/makeexe.sh: -------------------------------------------------------------------------------- 1 | NAME=nifskope 2 | VERSION=`cat ../VERSION` 3 | wcrev=`git log -1 --pretty=format:%h` 4 | if [ "$1" == "" ] 5 | then 6 | extversion=${VERSION}.${wcrev} 7 | else 8 | extversion=${VERSION}-$1.${wcrev} 9 | fi 10 | 11 | rm nifskope-*.exe 12 | echo !define VERSION \"${VERSION}\" > nifversion.nsh 13 | echo !define BUILD_RELEASE_FOLDER \"../release\" >> nifversion.nsh 14 | echo !define DLL_RELEASE_FOLDER \"/usr/i686-w64-mingw32/sys-root/mingw/bin\" >> nifversion.nsh 15 | 16 | cd ../docsys 17 | rm doc/*.html 18 | python nifxml_doc.py 19 | 20 | pushd ../lang 21 | find *.ts -exec lrelease-qt4 {} \; 22 | popd 23 | 24 | cp ../qhull/COPYING.txt ../Qhull_COPYING.TXT 25 | 26 | cd ../win-install 27 | 28 | makensis -V3 ${NAME}-fedora-mingw-dynamic.nsi 29 | mv "${NAME}-${VERSION}-windows.exe" "${NAME}-${extversion}-windows.exe" 30 | 31 | -------------------------------------------------------------------------------- /src/spells/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef SP_MISC_H 2 | #define SP_MISC_H 3 | 4 | #include "spellbook.h" 5 | 6 | 7 | // Brief description is deliberately not autolinked to class Spell 8 | /*! \file misc.h 9 | * \brief Miscellaneous spells header 10 | * 11 | * All classes here inherit from the Spell class. 12 | */ 13 | 14 | //! Removes empty links from a link array 15 | class spCollapseArray final : public Spell 16 | { 17 | public: 18 | QString name() const override final { return Spell::tr( "Collapse" ); } 19 | QString page() const override final { return Spell::tr( "Array" ); } 20 | 21 | bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final; 22 | QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final; 23 | // moved from sanitize.cpp 24 | QModelIndex numCollapser( NifModel * nif, QModelIndex & iNumElem, QModelIndex & iArray ); 25 | }; 26 | 27 | #endif // SP_MISC_H 28 | -------------------------------------------------------------------------------- /src/gl/bsshape.h: -------------------------------------------------------------------------------- 1 | #ifndef BSSHAPE_H 2 | #define BSSHAPE_H 3 | 4 | #include "gl/glshape.h" 5 | 6 | 7 | class NifModel; 8 | class NodeList; 9 | 10 | class BSShape : public Shape 11 | { 12 | 13 | public: 14 | BSShape( Scene * s, const QModelIndex & b ) : Shape( s, b ) { } 15 | 16 | // Node 17 | 18 | void transformShapes() override; 19 | 20 | void drawShapes( NodeList * secondPass = nullptr ) override; 21 | void drawSelection() const override; 22 | 23 | BoundSphere bounds() const override; 24 | 25 | // end Node 26 | 27 | // Shape 28 | 29 | void drawVerts() const; 30 | QModelIndex vertexAt( int ) const override; 31 | QModelIndex triangleAt( int ) const override; 32 | void updateLodLevel() override; 33 | 34 | protected: 35 | BoundSphere dataBound; 36 | 37 | bool isDynamic = false; 38 | 39 | void updateImpl( const NifModel * nif, const QModelIndex & index ) override; 40 | void updateData( const NifModel * nif ) override; 41 | }; 42 | 43 | #endif // BSSHAPE_H 44 | -------------------------------------------------------------------------------- /res/shaders/selection.frag: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | in vec4 C; 4 | 5 | // bit 0 = Scene::selecting 6 | // bit 1 = vertex mode (drawing points instead of triangles) 7 | // bit 2 = triangle selection mode (primitive ID << 15 is added to the color) 8 | // bits 8 to 15 = point size * 8 (0: do not draw smooth points) 9 | uniform int selectionFlags; 10 | 11 | out vec4 fragColor; 12 | 13 | void main() 14 | { 15 | vec4 color = C; 16 | 17 | if ( ( selectionFlags & 2 ) != 0 ) { 18 | // draw points as circles 19 | vec2 d = gl_PointCoord - vec2( 0.5 ); 20 | float r2 = dot( d, d ); 21 | if ( r2 > 0.25 ) 22 | discard; 23 | 24 | // with anti-aliasing if enabled 25 | int p = selectionFlags & 0xFF00; 26 | if ( p != 0 ) 27 | color.a *= clamp( ( 0.5 - sqrt(r2) ) * float( p ) / 2048.0, 0.0, 1.0 ); 28 | } else if ( ( selectionFlags & 4 ) != 0 ) { 29 | color = unpackUnorm4x8( packUnorm4x8( color ) + ( uint( gl_PrimitiveID ) << 15 ) ) + vec4( 0.0005 ); 30 | } 31 | 32 | fragColor = color; 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated 2 | .moc/ 3 | .obj/ 4 | .qrc/ 5 | .ui/ 6 | [Bb]in/ 7 | [Dd]ebug/ 8 | [Rr]elease/ 9 | GeneratedFiles/ 10 | Makefile 11 | Makefile.Debug 12 | Makefile.Release 13 | nifskope_plugin_import.cpp 14 | moc_*.cpp 15 | qrc_*.cpp 16 | ui_*.h 17 | *.tags 18 | 19 | # Intermediate 20 | *.o 21 | *.obj 22 | *.bak 23 | *.ilk 24 | *.log 25 | *.tmp 26 | 27 | # Eclipse project 28 | .project 29 | .cproject 30 | .settings 31 | 32 | # Qt Creator 33 | NifSkope.pro.user 34 | .qmake.stash 35 | 36 | # Binaries 37 | NifSkope 38 | NifSkope.exe 39 | 40 | # VC Project 41 | *.cd 42 | *.filters 43 | *.psess 44 | *.sln 45 | *.sln.docstates 46 | *.suo 47 | *.vcxproj 48 | *.vcxproj.user 49 | *.vcproj 50 | *.vcproj.user 51 | *.vsp 52 | *.vspscc 53 | *.vssscc 54 | *.vspx 55 | 56 | 57 | # VC Cache 58 | .vs/ 59 | ipch/ 60 | *.aps 61 | *.cachefile 62 | *.ncb 63 | *.opendb 64 | *.opensdf 65 | *.sdf 66 | *.VC.db 67 | *.VC.VC.opendb 68 | 69 | # VC Debug 70 | vc100.pdb 71 | 72 | # OS 73 | [Tt]humbs.db 74 | *.DS_Store 75 | 76 | # VSCode 77 | .vscode/ -------------------------------------------------------------------------------- /res/shaders/particles.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 vsLightDir; 4 | out vec3 vsViewDir; 5 | 6 | out vec4 vsColor; 7 | out float vsParticleSize; 8 | 9 | #include "uniforms.glsl" 10 | 11 | uniform mat4 modelViewMatrix; 12 | 13 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 14 | 15 | layout ( location = 0 ) in vec3 vertexPosition; 16 | layout ( location = 1 ) in vec4 vertexColor; 17 | // location 4 (bitangent) is used for sizes because the default is set to vec3(1, 0, 0) 18 | layout ( location = 4 ) in float particleSize; 19 | 20 | void main() 21 | { 22 | vec4 v = modelViewMatrix * vec4( vertexPosition, 1.0 ); 23 | 24 | gl_Position = v; 25 | 26 | if ( projectionMatrix[3][3] == 1.0 ) 27 | vsViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 28 | else 29 | vsViewDir = -v.xyz; 30 | vsLightDir = lightSourcePosition[0].xyz; 31 | 32 | vsColor = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 33 | vsParticleSize = particleSize; 34 | } 35 | -------------------------------------------------------------------------------- /src/spells/texture.h: -------------------------------------------------------------------------------- 1 | #ifndef SPELL_TEXTURE_H 2 | #define SPELL_TEXTURE_H 3 | 4 | #include // Inherited 5 | #include 6 | 7 | 8 | class NifFloatEdit; 9 | class NifModel; 10 | class QGridLayout; 11 | class QListView; 12 | class QAbstractButton; 13 | class QPushButton; 14 | class QStringListModel; 15 | 16 | //! Texture selection dialog for TexFlipController 17 | class TexFlipDialog final : public QDialog 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | TexFlipDialog( NifModel * nif, QModelIndex & index, QWidget * parent = nullptr ); 23 | QStringList flipList(); 24 | 25 | protected: 26 | NifModel * nif; 27 | QModelIndex baseIndex; 28 | NifFloatEdit * startTime; 29 | NifFloatEdit * stopTime; 30 | QStringList flipnames; 31 | QGridLayout * grid; 32 | QListView * listview; 33 | QStringListModel * listmodel; 34 | QPushButton * textureButtons[4]; 35 | 36 | protected slots: 37 | void textureAction( QAbstractButton * button ); 38 | void texIndex( const QModelIndex & idx ); 39 | void listFromNif(); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /lib/libfo76utils/scripts/crctable.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | for (int i = 1; i < argc; i++) 9 | { 10 | char *endp = (char *) 0; 11 | std::uint32_t polynomial = std::uint32_t(std::strtol(argv[i], &endp, 0)); 12 | std::printf("const std::uint32_t crc32Table_%08X[256] =\n", 13 | (unsigned int) polynomial); 14 | std::printf("{\n"); 15 | for (size_t j = 0; j < 256; j++) 16 | { 17 | unsigned int crcValue = (unsigned int) j; 18 | for (size_t k = 0; k < 8; k++) 19 | crcValue = (crcValue >> 1) ^ (polynomial & (0U - (crcValue & 1U))); 20 | if ((j % 6) == 0) 21 | std::fputc(' ', stdout); 22 | std::printf(" 0x%08X", crcValue); 23 | if (j == 255) 24 | std::fputc('\n', stdout); 25 | else if ((j % 6) != 5) 26 | std::fputc(',', stdout); 27 | else 28 | std::printf(",\n"); 29 | } 30 | std::printf("};\n\n"); 31 | } 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /.github/workflows/qt5.yml: -------------------------------------------------------------------------------- 1 | name: Build NifSkope (Qt 5) 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - develop 9 | tags-ignore: 10 | - 'v2*' 11 | 12 | jobs: 13 | build_clang64: 14 | runs-on: windows-latest 15 | name: Build MSYS2-CLANG64 16 | 17 | steps: 18 | - name: 'Checkout' 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | submodules: recursive 23 | 24 | - name: 'Setup MSYS2' 25 | uses: msys2/setup-msys2@v2 26 | with: 27 | msystem: CLANG64 28 | update: true 29 | cache: true 30 | install: 'base-devel mingw-w64-clang-x86_64-gcc msys/p7zip mingw-w64-clang-x86_64-qt5-base mingw-w64-clang-x86_64-qt5-imageformats mingw-w64-clang-x86_64-qt5-tools' 31 | 32 | - name: 'Build with qmake' 33 | shell: msys2 {0} 34 | run: | 35 | qmake NifSkope.pro 36 | make -j 8 37 | 38 | - name: 'Upload Artifacts' 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: build-clang64 42 | path: | 43 | release 44 | -------------------------------------------------------------------------------- /res/shaders/drawline.glsl: -------------------------------------------------------------------------------- 1 | uniform float lineWidth; 2 | 3 | void drawLine( vec4 p0, vec4 p1 ) 4 | { 5 | float p0zw = p0.z + p0.w; 6 | float p1zw = p1.z + p1.w; 7 | if ( !( p0zw > 0.0 && p1zw > 0.0 ) ) { 8 | if ( p0zw > 0.000001 ) 9 | p1 = mix( p0, p1, p0zw / ( p0zw - p1zw ) ); 10 | else if ( p1zw > 0.000001 ) 11 | p0 = mix( p1, p0, p1zw / ( p1zw - p0zw ) ); 12 | else 13 | return; 14 | } 15 | 16 | vec3 p0_ndc = p0.xyz / p0.w; 17 | vec3 p1_ndc = p1.xyz / p1.w; 18 | 19 | vec2 vpScale = vec2( viewportDimensions.zw ) * 0.5; 20 | vec2 vpOffs = vec2( viewportDimensions.xy ) + vpScale; 21 | 22 | vec2 p0_ss = p0_ndc.xy * vpScale; 23 | vec2 p1_ss = p1_ndc.xy * vpScale; 24 | 25 | vec2 d = normalize( p1_ss - p0_ss ) * max( lineWidth * 0.5, 0.5 ); 26 | vec2 n = vec2( -d.y, d.x ) / vpScale; 27 | 28 | gl_Position = vec4( p0_ndc.xy + n, p0_ndc.z, 1.0 ); 29 | EmitVertex(); 30 | gl_Position = vec4( p0_ndc.xy - n, p0_ndc.z, 1.0 ); 31 | EmitVertex(); 32 | gl_Position = vec4( p1_ndc.xy + n, p1_ndc.z, 1.0 ); 33 | EmitVertex(); 34 | gl_Position = vec4( p1_ndc.xy - n, p1_ndc.z, 1.0 ); 35 | EmitVertex(); 36 | 37 | EndPrimitive(); 38 | } 39 | -------------------------------------------------------------------------------- /lib/libfo76utils/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 fo76utils 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/spells/skeleton.h: -------------------------------------------------------------------------------- 1 | #ifndef SPELL_SKELETON_H 2 | #define SPELL_SKELETON_H 3 | 4 | #include // Inherited 5 | 6 | 7 | //! \file skeleton.h SkinPartitionDialog 8 | 9 | class QCheckBox; 10 | class QSpinBox; 11 | 12 | //! Dialog box for skin partitions 13 | class SkinPartitionDialog final : public QDialog 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | //! Constructor 19 | SkinPartitionDialog( int maxInfluences ); 20 | 21 | //! Returns the value of spnPart 22 | int maxBonesPerPartition(); 23 | //! Returns the value of spnVert 24 | int maxBonesPerVertex(); 25 | //! Returns the value of ckTStrip 26 | bool makeStrips(); 27 | //! Returns the value of ckPad 28 | bool padPartitions(); 29 | 30 | protected slots: 31 | //! Sets the minimum value of spnPart to the value of spnVert 32 | void changed(); 33 | 34 | protected: 35 | //! The number of bones per partition 36 | QSpinBox * spnPart; 37 | //! The number of bones per vertex 38 | QSpinBox * spnVert; 39 | //! Whether strips should be made 40 | QCheckBox * ckTStrip; 41 | //! Whether padding should be used 42 | QCheckBox * ckPad; 43 | 44 | //! The maximum number of influences; unused? 45 | int maxInfluences; 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /lib/libfo76utils/scripts/cdb_class_sort.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | if len(sys.argv) != 3: 6 | print("Usage: cdb_class_sort.py INFILE.JSON OUTFILE.JSON") 7 | raise SystemExit(1) 8 | 9 | classes = {} 10 | classBuf = [] 11 | className = None 12 | isClass = False 13 | readingClass = False 14 | 15 | f = open(sys.argv[1], "r") 16 | for l in f: 17 | if l == "\t{\n" and not readingClass: 18 | readingClass = True 19 | if readingClass: 20 | classBuf += [l] 21 | if l.startswith("\t\t\"Name\": \""): 22 | className = l[11:-3] 23 | if l == "\t\t\"Type\": \"\",\n": 24 | isClass = True 25 | elif l.startswith("\t\t\"Type\": \""): 26 | break 27 | if l == "\t},\n": 28 | if className and isClass: 29 | classes[className] = classBuf 30 | classBuf = [] 31 | className = None 32 | isClass = False 33 | readingClass = False 34 | f.close() 35 | 36 | classNames = [] 37 | for i in classes.keys(): 38 | classNames += [i] 39 | classNames.sort() 40 | 41 | f = open(sys.argv[2], "w") 42 | for i in classNames: 43 | for l in classes[i]: 44 | f.write(l) 45 | f.close() 46 | 47 | -------------------------------------------------------------------------------- /res/shaders/sk_msn.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | flat out vec4 A; 9 | out vec4 C; 10 | flat out vec4 D; 11 | 12 | #include "uniforms.glsl" 13 | 14 | uniform mat4 modelViewMatrix; 15 | 16 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 17 | 18 | layout ( location = 0 ) in vec3 vertexPosition; 19 | layout ( location = 1 ) in vec4 vertexColor; 20 | layout ( location = 7 ) in vec2 multiTexCoord0; 21 | 22 | #define BT_POSITION_ONLY 1 23 | #include "bonetransform.glsl" 24 | 25 | void main() 26 | { 27 | vec4 v = vec4( vertexPosition, 1.0 ); 28 | 29 | if ( boneWeights[0].x > 0.0 && doSkinning ) 30 | boneTransform( v ); 31 | 32 | v = modelViewMatrix * v; 33 | gl_Position = projectionMatrix * v; 34 | texCoord = multiTexCoord0; 35 | 36 | if ( projectionMatrix[3][3] == 1.0 ) 37 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 38 | else 39 | ViewDir = -v.xyz; 40 | LightDir = lightSourcePosition[0].xyz; 41 | 42 | A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, toneMapScale ); 43 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 44 | D = vec4( sqrt(lightSourceDiffuse[0].rgb), brightnessScale ); 45 | } 46 | -------------------------------------------------------------------------------- /res/shaders/sk_effectshader.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | out vec3 N; 9 | 10 | out vec4 C; 11 | 12 | #include "uniforms.glsl" 13 | 14 | uniform mat3 normalMatrix; // in row-major order 15 | uniform mat4 modelViewMatrix; 16 | 17 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 18 | 19 | layout ( location = 0 ) in vec3 vertexPosition; 20 | layout ( location = 1 ) in vec4 vertexColor; 21 | layout ( location = 2 ) in vec3 normalVector; 22 | layout ( location = 7 ) in vec2 multiTexCoord0; 23 | 24 | #define BT_NO_TANGENTS 1 25 | #include "bonetransform.glsl" 26 | 27 | void main() 28 | { 29 | vec4 v = vec4( vertexPosition, 1.0 ); 30 | vec3 n = normalVector; 31 | 32 | if ( boneWeights[0].x > 0.0 && doSkinning ) 33 | boneTransform( v, n ); 34 | 35 | v = modelViewMatrix * v; 36 | gl_Position = projectionMatrix * v; 37 | texCoord = multiTexCoord0; 38 | 39 | N = normalize( n * normalMatrix ); 40 | 41 | if ( projectionMatrix[3][3] == 1.0 ) 42 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 43 | else 44 | ViewDir = -v.xyz; 45 | LightDir = lightSourcePosition[0].xyz; 46 | 47 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 48 | } 49 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/downsamp.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DOWNSAMP_HPP_INCLUDED 3 | #define DOWNSAMP_HPP_INCLUDED 4 | 5 | #include "common.hpp" 6 | #include "fp32vec4.hpp" 7 | 8 | // linePtr: line pointer in output buffer 9 | // imageWidth, imageHeight: dimensions of input image 10 | // y: line number on input image 11 | // fmtFlags & 1: input pixel format (0: R8G8B8A8, 1: A2R10G10B10) 12 | // fmtFlags & 2: output pixel format 13 | void downsample2xFilter_Line( 14 | std::uint32_t *linePtr, const std::uint32_t *inBuf, 15 | int imageWidth, int imageHeight, int y, 16 | unsigned char fmtFlags = (USE_PIXELFMT_RGB10A2 * 3)); 17 | 18 | // imageWidth, imageHeight: dimensions of input image 19 | // pitch: number of elements per line in outBuf 20 | void downsample2xFilter( 21 | std::uint32_t *outBuf, const std::uint32_t *inBuf, 22 | int imageWidth, int imageHeight, int pitch, 23 | unsigned char fmtFlags = (USE_PIXELFMT_RGB10A2 * 3)); 24 | 25 | void downsample4xFilter_Line( 26 | std::uint32_t *linePtr, const std::uint32_t *inBuf, 27 | int imageWidth, int imageHeight, int y, 28 | unsigned char fmtFlags = (USE_PIXELFMT_RGB10A2 * 3)); 29 | 30 | void downsample4xFilter( 31 | std::uint32_t *outBuf, const std::uint32_t *inBuf, 32 | int imageWidth, int imageHeight, int pitch, 33 | unsigned char fmtFlags = (USE_PIXELFMT_RGB10A2 * 3)); 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /src/ui/widgets/ddspreview.h: -------------------------------------------------------------------------------- 1 | #ifndef DDSPREVIEW_H_INCLUDED 2 | #define DDSPREVIEW_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ddstxt16.hpp" 9 | #include "gamemanager.h" 10 | 11 | class DDSTexturePreview : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | protected: 16 | const DDSTexture16 * t = nullptr; 17 | // bit 0 = normal map, bit 1 = signed format, bit 2 = invert cube map Z axis 18 | unsigned short textureFlags = 0; 19 | unsigned short defaultSize = 512; 20 | float mipLevel = 0.0f; 21 | 22 | static void threadFunction( DDSTexturePreview * p, std::uint32_t * imgBuf, int w, int h, int y0, int y1 ); 23 | 24 | public: 25 | DDSTexturePreview( QWidget * parent = nullptr ); 26 | virtual ~DDSTexturePreview(); 27 | 28 | void setTexture( const DDSTexture16 * txt, bool isNormalMap, bool invertCubeMapZAxis ); 29 | 30 | QSize sizeHint() const override; 31 | 32 | protected: 33 | void paintEvent( QPaintEvent * ) override; 34 | }; 35 | 36 | class DDSTextureInfo : public QWidget 37 | { 38 | Q_OBJECT 39 | 40 | protected: 41 | DDSTexturePreview * textureView = nullptr; 42 | DDSTexture16 * t = nullptr; 43 | 44 | public: 45 | DDSTextureInfo( Game::GameManager::GameResources & gameResources, const QString & filePath, 46 | QWidget * parent = nullptr ); 47 | virtual ~DDSTextureInfo(); 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /install/win-install/makeexe.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Quick build script to create the installer for release. 3 | rem Run this batch file from buildenv, see https://github.com/amorilia/buildenv 4 | rem Call it as "buildenv.bat C:\Python27 mingw 32 workspace" 5 | 6 | setlocal 7 | 8 | set NAME=nifskope 9 | set VERSION=1.1.1 10 | if not "%1" == "" set VERSION=%VERSION%-%1 11 | set REVISION= 12 | 13 | rem Check that required tools are in PATH 14 | for %%i in (git.exe, python.exe, lrelease.exe, makensis.exe) do if not exist "%%~$PATH:i" ( 15 | echo.%%i not found in path 16 | exit /B 1 17 | ) 18 | 19 | 20 | for /f "delims=| usebackq" %%i in (`"git.exe log -1 --pretty=format:%%h"`) do set REVISION=%%i 21 | 22 | del %NAME%-%VERSION%.%REVISION%-windows.exe > nul 23 | 24 | echo !define VERSION "%VERSION%.%REVISION%" > nifversion.nsh 25 | echo !define BUILD_RELEASE_FOLDER "..\..\NifSkope-build-desktop\release" >> nifversion.nsh 26 | echo !define DLL_RELEASE_FOLDER "%QTDIR%\bin" >> nifversion.nsh 27 | 28 | cd ..\docsys 29 | del doc\*.html 30 | 31 | python.exe nifxml_doc.py 32 | 33 | pushd ..\lang 34 | for %%i in (*.ts) do call lrelease.exe %%i 35 | popd 36 | 37 | rem copy qhull's COPYING.TXT 38 | copy ..\qhull\COPYING.TXT ..\Qhull_COPYING.TXT 39 | 40 | cd ..\win-install 41 | 42 | makensis.exe /v3 %NAME%-mingw-dynamic.nsi 43 | 44 | endlocal 45 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/bptc-tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015 Harm Hanemaaijer 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | */ 18 | 19 | extern const uint8_t detex_bptc_table_P2[64 * 16]; 20 | extern const uint8_t detex_bptc_table_P3[64 * 16]; 21 | 22 | extern const uint8_t detex_bptc_table_anchor_index_second_subset[64]; 23 | extern const uint8_t detex_bptc_table_anchor_index_second_subset_of_three[64]; 24 | extern const uint8_t detex_bptc_table_anchor_index_third_subset[64]; 25 | 26 | extern const uint16_t detex_bptc_table_aWeight2[4]; 27 | extern const uint16_t detex_bptc_table_aWeight3[8]; 28 | extern const uint16_t detex_bptc_table_aWeight4[16]; 29 | 30 | -------------------------------------------------------------------------------- /src/ui/widgets/lightingwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef LIGHTINGWIDGET_H 2 | #define LIGHTINGWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | class GLView; 10 | 11 | namespace Ui { 12 | class LightingWidget; 13 | } 14 | 15 | class LightingWidget : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | LightingWidget( GLView * ogl, QWidget * parent = nullptr); 21 | ~LightingWidget(); 22 | 23 | void setDefaults(); 24 | void setActions( QVector actions ); 25 | 26 | public slots: 27 | void saveSettings(); 28 | 29 | private: 30 | std::unique_ptr ui; 31 | 32 | enum 33 | { 34 | BRIGHT = 1440, 35 | POS = 720, 36 | 37 | DirMin = 0, 38 | DirMax = BRIGHT, 39 | LightColorMin = 0, 40 | LightColorMax = BRIGHT, 41 | 42 | AmbientMin = 0, 43 | AmbientMax = BRIGHT, 44 | EnvMapRotationMin = -POS, 45 | EnvMapRotationMax = POS, 46 | GlowScaleMin = 0, 47 | GlowScaleMax = BRIGHT, 48 | 49 | LightScaleMin = 0, 50 | LightScaleMax = BRIGHT, 51 | ToneMappingMin = 0, 52 | ToneMappingMax = BRIGHT, 53 | 54 | DirDefault = DirMax / 2, 55 | LightColorDefault = POS, 56 | AmbientDefault = AmbientMax / 2, 57 | EnvMapRotationDefault = 0, 58 | GlowScaleDefault = GlowScaleMax / 2, 59 | LightScaleDefault = POS, 60 | ToneMappingDefault = POS 61 | }; 62 | }; 63 | 64 | #endif // LIGHTINGWIDGET_H 65 | -------------------------------------------------------------------------------- /res/shaders/wireframe.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out mat3 btnMatrix; 4 | 5 | out vec4 vsColor; 6 | 7 | #include "uniforms.glsl" 8 | 9 | uniform mat3 normalMatrix; // in row-major order 10 | uniform mat4 modelViewMatrix; 11 | 12 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 13 | uniform vec4 highlightColor; 14 | uniform int selectionParam; // vertex selected (-1: none) 15 | 16 | layout ( location = 0 ) in vec3 vertexPosition; 17 | layout ( location = 1 ) in vec4 vertexColor; 18 | layout ( location = 2 ) in vec3 normalVector; 19 | layout ( location = 3 ) in vec3 tangentVector; 20 | layout ( location = 4 ) in vec3 bitangentVector; 21 | 22 | #include "bonetransform.glsl" 23 | 24 | void main() 25 | { 26 | vec4 v = vec4( vertexPosition, 1.0 ); 27 | vec3 n = normalVector; 28 | vec3 t = tangentVector; 29 | vec3 b = bitangentVector; 30 | 31 | if ( boneWeights[0].x > 0.0 && doSkinning ) 32 | boneTransform( v, n, t, b ); 33 | 34 | gl_Position = modelViewMatrix * v; 35 | 36 | btnMatrix[2] = normalize( n * normalMatrix ); 37 | btnMatrix[1] = normalize( t * normalMatrix ); 38 | btnMatrix[0] = normalize( b * normalMatrix ); 39 | 40 | if ( gl_VertexID == selectionParam ) 41 | vsColor = highlightColor; 42 | else 43 | vsColor = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 44 | } 45 | -------------------------------------------------------------------------------- /src/ui/settingsdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSDIALOG_H 2 | #define SETTINGSDIALOG_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | 10 | //! @file settingsdialog.h SettingsDialog 11 | 12 | class QListWidget; 13 | class QListWidgetItem; 14 | class QPushButton; 15 | class QStackedWidget; 16 | class GLView; 17 | 18 | namespace Ui { 19 | class SettingsDialog; 20 | } 21 | 22 | 23 | class SettingsDialog : public QDialog 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | explicit SettingsDialog( QWidget * parent = nullptr ); 29 | ~SettingsDialog(); 30 | 31 | 32 | static void registerPage( QWidget *, const QString & ); 33 | 34 | QStackedWidget * content; 35 | QListWidget * categories; 36 | 37 | QVariant settingsVersion; 38 | 39 | public slots: 40 | void save(); 41 | void apply(); 42 | void cancel(); 43 | void changePage( QListWidgetItem * current, QListWidgetItem * previous ); 44 | void restoreDefaults(); 45 | void modified(); 46 | 47 | signals: 48 | void loadSettings(); 49 | void saveSettings(); 50 | void localeChanged(); 51 | void update3D(); 52 | void flush3D(); 53 | 54 | private: 55 | std::unique_ptr ui; 56 | 57 | QPushButton * btnSave; 58 | QPushButton * btnApply; 59 | QPushButton * btnCancel; 60 | 61 | bool eventFilter( QObject *, QEvent * ) override final; 62 | void showEvent( QShowEvent * ) override final; 63 | }; 64 | 65 | #endif // SETTINGSDIALOG_H 66 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: cpp 4 | os: 5 | - linux 6 | - osx 7 | addons: 8 | apt: 9 | sources: 10 | - sourceline: 'ppa:beineri/opt-qt571-trusty' 11 | packages: [ 12 | # static analysis 13 | clang-3.6, 14 | # qt5 requirement 15 | qt57-meta-minimal 16 | ] 17 | matrix: 18 | fast_finish: true 19 | include: 20 | - os: linux 21 | env: 22 | ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 " 23 | compiler: clang 24 | allow_failures: 25 | - env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 " 26 | 27 | before_install: 28 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi 29 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get update -qq; fi 30 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi 31 | - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew update; brew install qt@5.7; export PATH="/usr/local/opt/qt@5.7/bin:$PATH"; fi 32 | 33 | install: 34 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq g++-6; fi 35 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-6 90; fi 36 | 37 | script: 38 | - qmake --version 39 | - qmake -makefile NifSkope.pro 40 | - ${ANALYZE}make -j4 41 | 42 | notifications: 43 | email: false 44 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | platform: 4 | - win32 5 | - x64 6 | 7 | configuration: 8 | - debug 9 | - release 10 | 11 | matrix: 12 | fast_finish: true 13 | 14 | os: Visual Studio 2015 15 | 16 | # We want the git revision for versioning, 17 | # so shallow clones don't work. 18 | clone_depth: 1 19 | 20 | clone_folder: C:\projects\nifskope 21 | 22 | install: 23 | - if %PLATFORM%==win32 set QTDIR=C:\Qt\5.7\msvc2015 24 | - if %PLATFORM%==x64 set QTDIR=C:\Qt\5.7\msvc2015_64 25 | - set PATH=%PATH%;%QTDIR%\bin; 26 | 27 | build_script: 28 | - git submodule update --init --recursive # Appveyor doesn't clone recursively. 29 | - qmake CONFIG+=%CONFIGURATION% -Wall -spec win32-msvc2015 -tp vc NifSkope.pro 30 | - msbuild NifSkope.vcxproj /t:Build /p:Configuration=%configuration% /m:2 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 31 | 32 | after_build: 33 | - if %CONFIGURATION%==debug set DEBUG_POSTFIX=_debug 34 | - set BUILD_DIR=%APPVEYOR_BUILD_FOLDER%\bin\%CONFIGURATION% 35 | - set BUILD_NAME=nifskope_%platform%%DEBUG_POSTFIX%.zip 36 | - 7z a %BUILD_NAME% %BUILD_DIR% 37 | - 7z rn %BUILD_NAME% %CONFIGURATION% NifSkope 38 | 39 | test: off 40 | 41 | artifacts: 42 | - path: nifskope_win32.zip 43 | name: nifskope_win32 44 | - path: nifskope_x64.zip 45 | name: nifskope_x64 46 | - path: nifskope_win32_debug.zip 47 | name: nifskope_win32_debug 48 | - path: nifskope_x64_debug.zip 49 | name: nifskope_x64_debug 50 | 51 | -------------------------------------------------------------------------------- /res/shaders/bonetransform.glsl: -------------------------------------------------------------------------------- 1 | layout ( std140 ) uniform skinningUniforms 2 | { 3 | mat3x4 boneTransforms[256]; // bone transforms in row-major order 4 | }; 5 | 6 | layout ( location = 5 ) in vec4 boneWeights[2]; 7 | 8 | #ifdef BT_POSITION_ONLY 9 | void boneTransform( inout vec4 v ) 10 | #elif defined( BT_NO_TANGENTS ) 11 | void boneTransform( inout vec4 v, inout vec3 n ) 12 | #else 13 | void boneTransform( inout vec4 v, inout vec3 n, inout vec3 t, inout vec3 b ) 14 | #endif 15 | { 16 | #if defined( BT_POSITION_ONLY ) || defined( BT_NO_TANGENTS ) 17 | vec3 vTmp = vec3( 0.0 ); 18 | #ifndef BT_POSITION_ONLY 19 | vec3 nTmp = vec3( 0.0 ); 20 | #endif 21 | #else 22 | mat3x4 mTmp = mat3x4( 0.0 ); 23 | #endif 24 | float wSum = 0.0; 25 | for ( int i = 0; i < 8; i++ ) { 26 | float bw = boneWeights[i >> 2][i & 3]; 27 | if ( !( bw > 0.0 ) ) 28 | break; 29 | int bone = int( bw ) & 0xFF; 30 | float w = fract( bw ); 31 | #if defined( BT_POSITION_ONLY ) || defined( BT_NO_TANGENTS ) 32 | mat3x4 m = boneTransforms[bone]; 33 | vTmp += v * m * w; 34 | #ifndef BT_POSITION_ONLY 35 | nTmp += n * mat3( m ) * w; 36 | #endif 37 | #else 38 | mTmp += boneTransforms[bone] * w; 39 | #endif 40 | wSum += w; 41 | } 42 | if ( wSum > 0.0 ) { 43 | #if defined( BT_POSITION_ONLY ) || defined( BT_NO_TANGENTS ) 44 | v = vec4( vTmp / wSum, 1.0 ); 45 | #ifndef BT_POSITION_ONLY 46 | n = nTmp; 47 | #endif 48 | #else 49 | v = vec4( v * mTmp / wSum, 1.0 ); 50 | mat3 r = mat3( mTmp ); 51 | n = n * r; 52 | t = t * r; 53 | b = b * r; 54 | #endif 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/libfo76utils/README.detex: -------------------------------------------------------------------------------- 1 | Detex is a low-level library that can be used to decompress textures and 2 | texture blocks, as well as convert between a variety of pixel formats. It has 3 | been developed using Linux, but is probably usable on other platforms without 4 | too much effort. 5 | 6 | Features include: 7 | 8 | - Decompression of texture blocks compressed using formats including 9 | BC1/DXT1/S3TC, BC2, BC3, BC4/RGTC1, BC5/RGTC2, BC6 (BPTC_FLOAT), BC7 (BPTC), 10 | ETC1 and the ETC2 family. 11 | - Flexible pixel format conversion functions between a variety of formats, 12 | including many uncompressed formats and mapping HDR textures. 13 | - Loading and saving of KTX and DDS texture files. 14 | 15 | The original and complete version is available at https://github.com/hglm/detex 16 | 17 | Copyright (c) 2015 Harm Hanemaaijer 18 | 19 | Permission to use, copy, modify, and/or distribute this software for any 20 | purpose with or without fee is hereby granted, provided that the above 21 | copyright notice and this permission notice appear in all copies. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 24 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 25 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 26 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30 | 31 | -------------------------------------------------------------------------------- /lib/coacd.h: -------------------------------------------------------------------------------- 1 | #ifndef COACD_H_INCLUDED 2 | #define COACD_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QSettings; 9 | 10 | class CoACD 11 | { 12 | public: 13 | float threshold = 0.05f; 14 | int maxConvexHull = -1; 15 | int preprocessMode = 0; // 0 = auto, 1 = on, 2 = off 16 | int prepResolution = 50; 17 | int sampleResolution = 2000; 18 | int mctsNodes = 20; 19 | int mctsIteration = 150; 20 | int mctsMaxDepth = 3; 21 | bool pca = false; 22 | bool merge = false; 23 | bool decimate = true; 24 | int maxCHVertex = 256; 25 | bool extrude = false; 26 | float extrudeMargin = 0.0f; 27 | int apxMode = 0; // 0 = ch, 1 = box 28 | int seed = 0; 29 | 30 | struct Mesh { 31 | std::vector< std::array< double, 3 > > vertices; 32 | std::vector< std::array< int, 3 > > indices; 33 | }; 34 | 35 | std::vector< Mesh > processMesh( const Mesh & m ); 36 | void loadSettings( QSettings & settings ); 37 | void saveSettings( QSettings & settings ); 38 | 39 | // CoACD C library interface 40 | 41 | struct MeshDataC { 42 | double * vertices; 43 | std::uint64_t numVerts; 44 | int * indices; 45 | std::uint64_t numTriangles; 46 | }; 47 | 48 | struct MeshArrayC { 49 | MeshDataC * meshes; 50 | std::uint64_t numMeshes; 51 | }; 52 | 53 | typedef void ( *fnSetLogLevel )( const char * ); 54 | typedef MeshArrayC ( *fnRun )( const MeshDataC *, double, int, int, int, int, int, int, int, bool, bool, 55 | bool, int, bool, double, int, unsigned int ); 56 | typedef void ( *fnFreeMeshArray )( MeshArrayC m ); 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/spells/stringpalette.h: -------------------------------------------------------------------------------- 1 | #ifndef SPELL_STRINGPALETTE_H 2 | #define SPELL_STRINGPALETTE_H 3 | 4 | #include // Inherited 5 | #include 6 | 7 | 8 | //! \file stringpalette.h StringPaletteRegexDialog 9 | 10 | class NifModel; 11 | 12 | class QGridLayout; 13 | class QLineEdit; 14 | class QListView; 15 | class QStringListModel; 16 | class QWidget; 17 | 18 | //! String palette QRegularExpression dialog for spEditStringEntries 19 | class StringPaletteRegexDialog final : public QDialog 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | //! Constructor. Sets widgets and layout. 25 | StringPaletteRegexDialog( NifModel * nif, QPersistentModelIndex & index, QWidget * parent = nullptr ); 26 | 27 | protected: 28 | //! Model used 29 | NifModel * nif; 30 | //! Index of the string palette 31 | QPersistentModelIndex iPalette; 32 | //! Lists the strings in the palette 33 | QListView * listview; 34 | //! Internal representation of the current state of the palette 35 | QStringListModel * listmodel; 36 | //! Original palette 37 | QStringList * originalList; 38 | //! Grid layout 39 | QGridLayout * grid; 40 | //! Regular expression to search for 41 | QLineEdit * search; 42 | //! String to replace with 43 | QLineEdit * replace; 44 | 45 | public slots: 46 | //! Performs regex replacement of \link search \endlink to \link replace \endlink in \link listmodel \endlink 47 | void stringlistRegex(); 48 | //! Set the string palette entries 49 | void setStringList( QStringList & list ); 50 | //! Get the modified string palette 51 | QStringList getStringList(); 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/gl/BSMesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "glshape.h" 3 | #include "glscene.h" 4 | #include "io/MeshFile.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class QByteArray; 12 | class NifModel; 13 | 14 | namespace tinygltf { 15 | class Model; 16 | } 17 | 18 | class BSMesh : public Shape 19 | { 20 | 21 | public: 22 | BSMesh(Scene* s, const QModelIndex& iBlock); 23 | 24 | // Node 25 | 26 | void transformShapes() override; 27 | 28 | void drawShapes( NodeList * secondPass = nullptr ) override; 29 | void drawSelection() const override; 30 | 31 | BoundSphere bounds() const override; 32 | 33 | QString textStats() const override; // TODO (Gavrant): move to Shape 34 | 35 | int meshCount(); 36 | 37 | // end Node 38 | 39 | // Shape 40 | 41 | void drawVerts() const; 42 | QModelIndex getMeshDataIndex() const; 43 | QModelIndex vertexAt( int ) const override; 44 | QModelIndex triangleAt( int ) const override; 45 | 46 | QVector> meshes; 47 | inline const MeshFile * getMeshFile() const 48 | { 49 | if ( meshes.size() > 0 ) { 50 | if ( meshes[0]->lods.size() > 0 ) 51 | return meshes[0].get(); 52 | int l = std::min( int(scene->lodLevel), int(meshes.size()) - 1 ); 53 | if ( l >= 0 ) 54 | return meshes[l].get(); 55 | } 56 | return nullptr; 57 | } 58 | 59 | QVector> gpuLODs; 60 | 61 | protected: 62 | void updateImpl(const NifModel* nif, const QModelIndex& index) override; 63 | void updateData(const NifModel* nif) override; 64 | 65 | BoundSphere dataBound; 66 | 67 | quint32 lodLevel = 0; 68 | }; 69 | -------------------------------------------------------------------------------- /res/shaders/particles.geom: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | layout ( points ) in; 4 | layout ( triangle_strip, max_vertices = 4 ) out; 5 | 6 | #include "uniforms.glsl" 7 | 8 | uniform vec2 particleScale; 9 | 10 | in vec3 vsLightDir[]; 11 | in vec3 vsViewDir[]; 12 | 13 | in vec4 vsColor[]; 14 | in float vsParticleSize[]; 15 | 16 | out vec3 LightDir; 17 | out vec3 ViewDir; 18 | 19 | out vec2 texCoords[9]; 20 | 21 | flat out vec4 A; 22 | out vec4 C; 23 | flat out vec4 D; 24 | 25 | out vec3 N; 26 | 27 | void main() 28 | { 29 | LightDir = vsLightDir[0]; 30 | ViewDir = vsViewDir[0]; 31 | 32 | A = vec4( vec3(1.0), toneMapScale ); 33 | C = vsColor[0]; 34 | D = vec4( vec3(0.0), sqrt(brightnessScale) ); 35 | 36 | N = vec3( 0.0, 0.0, 1.0 ); 37 | 38 | float sx = vsParticleSize[0] * particleScale.x; 39 | float sy = vsParticleSize[0] * particleScale.y; 40 | 41 | for ( int i = 0; i < 9; i++ ) 42 | texCoords[i] = vec2( 1.0, 1.0 ); 43 | gl_Position = projectionMatrix * ( gl_in[0].gl_Position + vec4( sx, sy, 0.0, 0.0 ) ); 44 | EmitVertex(); 45 | for ( int i = 0; i < 9; i++ ) 46 | texCoords[i] = vec2( 0.0, 1.0 ); 47 | gl_Position = projectionMatrix * ( gl_in[0].gl_Position + vec4( -sx, sy, 0.0, 0.0 ) ); 48 | EmitVertex(); 49 | for ( int i = 0; i < 9; i++ ) 50 | texCoords[i] = vec2( 1.0, 0.0 ); 51 | gl_Position = projectionMatrix * ( gl_in[0].gl_Position + vec4( sx, -sy, 0.0, 0.0 ) ); 52 | EmitVertex(); 53 | for ( int i = 0; i < 9; i++ ) 54 | texCoords[i] = vec2( 0.0, 0.0 ); 55 | gl_Position = projectionMatrix * ( gl_in[0].gl_Position + vec4( -sx, -sy, 0.0, 0.0 ) ); 56 | EmitVertex(); 57 | 58 | EndPrimitive(); 59 | } 60 | -------------------------------------------------------------------------------- /res/shaders/stf_default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec4 texCoord; 7 | 8 | out mat3 btnMatrix; 9 | 10 | out vec4 C; 11 | 12 | #include "uniforms.glsl" 13 | 14 | uniform mat3 normalMatrix; // in row-major order 15 | uniform mat4 modelViewMatrix; 16 | 17 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 18 | 19 | layout ( location = 0 ) in vec3 vertexPosition; 20 | layout ( location = 1 ) in vec4 vertexColor; 21 | layout ( location = 2 ) in vec3 normalVector; 22 | layout ( location = 3 ) in vec3 tangentVector; 23 | layout ( location = 4 ) in vec3 bitangentVector; 24 | layout ( location = 7 ) in vec2 multiTexCoord0; 25 | layout ( location = 8 ) in vec2 multiTexCoord1; 26 | 27 | #include "bonetransform.glsl" 28 | 29 | void main() 30 | { 31 | vec4 v = vec4( vertexPosition, 1.0 ); 32 | vec3 n = normalVector; 33 | vec3 t = tangentVector; 34 | vec3 b = bitangentVector; 35 | 36 | if ( boneWeights[0].x > 0.0 && doSkinning ) 37 | boneTransform( v, n, t, b ); 38 | 39 | v = modelViewMatrix * v; 40 | gl_Position = projectionMatrix * v; 41 | texCoord = vec4( multiTexCoord0, multiTexCoord1 ); 42 | 43 | btnMatrix[2] = normalize( n * normalMatrix ); 44 | btnMatrix[1] = normalize( t * normalMatrix ); 45 | btnMatrix[0] = normalize( b * normalMatrix ); 46 | 47 | if ( projectionMatrix[3][3] == 1.0 ) 48 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 49 | else 50 | ViewDir = -v.xyz; 51 | LightDir = lightSourcePosition[0].xyz; 52 | 53 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 54 | } 55 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/pbr_lut.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PBR_LUT_HPP_INCLUDED 3 | #define PBR_LUT_HPP_INCLUDED 4 | 5 | #include "common.hpp" 6 | #include "fp32vec4.hpp" 7 | #include "fp32vec8.hpp" 8 | 9 | class SF_PBR_Tables 10 | { 11 | public: 12 | static inline FloatVector4 Hammersley(int i, int n); 13 | // Returns H vector, assuming normal = (0, 0, 1). a2 = pow(roughness, 4.0) 14 | static FloatVector4 importanceSampleGGX(FloatVector4 xi, float a2); 15 | protected: 16 | std::vector< unsigned char > imageData; 17 | // approximates Fresnel function for n = 1.5, normalized to 0.0 to 1.0 18 | static inline FloatVector8 fresnel_n(FloatVector8 x); 19 | static void threadFunction(unsigned char *outBuf, int width, int nSpec, 20 | int y0, int y1); 21 | public: 22 | SF_PBR_Tables(int width = 512, int nSpec = 4096); 23 | // R = indirect specular F (U = N·V, V = roughness) 24 | // G = indirect specular G 25 | // B = fresnel_n(U) 26 | // A = fresnel_n(V) 27 | inline const std::vector< unsigned char >& getImageData() const 28 | { 29 | return imageData; 30 | } 31 | }; 32 | 33 | inline FloatVector4 SF_PBR_Tables::Hammersley(int i, int n) 34 | { 35 | FloatVector4 xi(0.0f); 36 | xi[0] = float(i) / float(n); 37 | std::uint32_t tmp = std::uint32_t(i); 38 | tmp = ((tmp & 0x55555555U) << 1) | ((tmp >> 1) & 0x55555555U); 39 | tmp = ((tmp & 0x33333333U) << 2) | ((tmp >> 2) & 0x33333333U); 40 | tmp = ((tmp & 0x0F0F0F0FU) << 4) | ((tmp >> 4) & 0x0F0F0F0FU); 41 | tmp = FileBuffer::swapUInt32(tmp); 42 | xi[1] = float(int(tmp >> 1)) * float(0.5 / double(0x40000000)); 43 | return xi; 44 | } 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/io/MeshFile.h: -------------------------------------------------------------------------------- 1 | #ifndef MESHFILE_H_INCLUDED 2 | #define MESHFILE_H_INCLUDED 3 | 4 | #include "data/niftypes.h" 5 | #include "gl/gltools.h" 6 | 7 | #include 8 | 9 | class NifModel; 10 | 11 | 12 | class MeshFile 13 | { 14 | public: 15 | MeshFile( const void * data, size_t size ); 16 | MeshFile( const NifModel * nif, const QString & path ); 17 | // construct from BSMesh structure index, can load .mesh file or internal geometry data 18 | MeshFile( const NifModel * nif, const QModelIndex & index ); 19 | 20 | void clear(); 21 | 22 | void update( const void * data, size_t size ); 23 | void update( const NifModel * nif, const QString & path ); 24 | void update( const NifModel * nif, const QModelIndex & index ); 25 | 26 | void calculateBitangents( QVector & bitangents ) const; 27 | 28 | //! Vertices 29 | QVector positions; 30 | //! Normals 31 | QVector normals; 32 | //! Vertex colors 33 | QVector colors; 34 | //! Tangents 35 | QVector tangents; 36 | //! Bitangents basis (bitangents[i] = cross(normals[i], tangents[i] * bitangentsBasis[i])) 37 | QVector bitangentsBasis; 38 | //! UV coordinate sets 39 | QVector coords1; 40 | QVector coords2; 41 | //! Weights, numVerts * weightsPerVertex elements in (bone << 16) | weight format 42 | QVector weights; 43 | quint8 weightsPerVertex = 0; 44 | //! Triangles 45 | QVector triangles; 46 | //! Skeletal Mesh LOD 47 | QVector> lods; 48 | 49 | private: 50 | bool haveData = false; 51 | public: 52 | inline bool isValid() const 53 | { 54 | return haveData; 55 | } 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/jsonread.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JSONREAD_HPP_INCLUDED 3 | #define JSONREAD_HPP_INCLUDED 4 | 5 | #include "common.hpp" 6 | #include "filebuf.hpp" 7 | 8 | class JSONReader : public FileBuffer 9 | { 10 | public: 11 | enum JSONItemType 12 | { 13 | JSONItemType_Null = 0, 14 | JSONItemType_Boolean = 1, 15 | JSONItemType_Number = 2, 16 | JSONItemType_String = 3, 17 | JSONItemType_Object = 4, 18 | JSONItemType_Array = 5 19 | }; 20 | struct JSONItem 21 | { 22 | // 0: null, 1: boolean, 2: number, 3: string, 4: object, 5: array 23 | int type; 24 | }; 25 | struct JSONBoolean : public JSONItem 26 | { 27 | bool value; 28 | }; 29 | struct JSONNumber : public JSONItem 30 | { 31 | double value; 32 | }; 33 | struct JSONString : public JSONItem 34 | { 35 | std::string value; 36 | }; 37 | struct JSONObject : public JSONItem 38 | { 39 | std::map< std::string, const JSONItem * > children; 40 | }; 41 | struct JSONArray : public JSONItem 42 | { 43 | std::vector< const JSONItem * > children; 44 | }; 45 | protected: 46 | JSONItem *rootObject; 47 | size_t curLine; 48 | std::string curToken; 49 | // returns empty string on EOF 50 | std::string& readToken(); 51 | // returns false if s is empty 52 | bool parseJSONValue(JSONItem*& o, const std::string& s); 53 | void parseJSONData(); 54 | void deleteJSONObjects(JSONItem *p); 55 | public: 56 | JSONReader(const char *fileName); 57 | JSONReader(const unsigned char *fileData, size_t fileSize); 58 | virtual ~JSONReader(); 59 | inline const JSONItem *getData() const 60 | { 61 | return rootObject; 62 | } 63 | }; 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /res/shaders/f76_default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | out mat3 btnMatrix; 9 | 10 | out vec4 C; 11 | 12 | flat out mat3 reflMatrix; 13 | 14 | #include "uniforms.glsl" 15 | 16 | uniform mat3 normalMatrix; // in row-major order 17 | uniform mat4 modelViewMatrix; 18 | 19 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 20 | 21 | layout ( location = 0 ) in vec3 vertexPosition; 22 | layout ( location = 1 ) in vec4 vertexColor; 23 | layout ( location = 2 ) in vec3 normalVector; 24 | layout ( location = 3 ) in vec3 tangentVector; 25 | layout ( location = 4 ) in vec3 bitangentVector; 26 | layout ( location = 7 ) in vec2 multiTexCoord0; 27 | 28 | #include "bonetransform.glsl" 29 | 30 | void main() 31 | { 32 | vec4 v = vec4( vertexPosition, 1.0 ); 33 | vec3 n = normalVector; 34 | vec3 t = tangentVector; 35 | vec3 b = bitangentVector; 36 | 37 | if ( boneWeights[0].x > 0.0 && doSkinning ) 38 | boneTransform( v, n, t, b ); 39 | 40 | v = modelViewMatrix * v; 41 | gl_Position = projectionMatrix * v; 42 | texCoord = multiTexCoord0; 43 | 44 | btnMatrix[2] = normalize( n * normalMatrix ); 45 | btnMatrix[1] = normalize( t * normalMatrix ); 46 | btnMatrix[0] = normalize( b * normalMatrix ); 47 | 48 | reflMatrix = envMapRotation; 49 | reflMatrix[0][2] *= -1.0; 50 | reflMatrix[1][2] *= -1.0; 51 | reflMatrix[2][2] *= -1.0; 52 | 53 | if ( projectionMatrix[3][3] == 1.0 ) 54 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 55 | else 56 | ViewDir = -v.xyz; 57 | LightDir = lightSourcePosition[0].xyz; 58 | 59 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 60 | } 61 | -------------------------------------------------------------------------------- /res/shaders/sk_default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | out mat3 btnMatrix; 9 | 10 | flat out vec4 A; 11 | out vec4 C; 12 | flat out vec4 D; 13 | 14 | #include "uniforms.glsl" 15 | 16 | uniform mat3 normalMatrix; // in row-major order 17 | uniform mat4 modelViewMatrix; 18 | 19 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 20 | 21 | layout ( location = 0 ) in vec3 vertexPosition; 22 | layout ( location = 1 ) in vec4 vertexColor; 23 | layout ( location = 2 ) in vec3 normalVector; 24 | layout ( location = 3 ) in vec3 tangentVector; 25 | layout ( location = 4 ) in vec3 bitangentVector; 26 | layout ( location = 7 ) in vec2 multiTexCoord0; 27 | 28 | #include "bonetransform.glsl" 29 | 30 | void main() 31 | { 32 | vec4 v = vec4( vertexPosition, 1.0 ); 33 | vec3 n = normalVector; 34 | vec3 t = tangentVector; 35 | vec3 b = bitangentVector; 36 | 37 | if ( boneWeights[0].x > 0.0 && doSkinning ) 38 | boneTransform( v, n, t, b ); 39 | 40 | v = modelViewMatrix * v; 41 | gl_Position = projectionMatrix * v; 42 | texCoord = multiTexCoord0; 43 | 44 | btnMatrix[2] = normalize( n * normalMatrix ); 45 | btnMatrix[1] = normalize( t * normalMatrix ); 46 | btnMatrix[0] = normalize( b * normalMatrix ); 47 | 48 | if ( projectionMatrix[3][3] == 1.0 ) 49 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 50 | else 51 | ViewDir = -v.xyz; 52 | LightDir = lightSourcePosition[0].xyz; 53 | 54 | A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, toneMapScale ); 55 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 56 | D = vec4( sqrt(lightSourceDiffuse[0].rgb), brightnessScale ); 57 | } 58 | -------------------------------------------------------------------------------- /src/spells/simplify.h: -------------------------------------------------------------------------------- 1 | #ifndef SPELLS_SIMPLIFY_H_INCLUDED 2 | #define SPELLS_SIMPLIFY_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class NifModel; 14 | 15 | class SimplifyMeshDialog : public QDialog 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | NifModel * nif; 21 | size_t numVerts, numTriangles; 22 | bool batchMode, errorFlag; 23 | protected: 24 | // 12 floats per vertex: position (3), normal (3), UV (2), color (4) 25 | std::vector< float > vertexAttrData; 26 | std::vector< unsigned int > indicesData; 27 | std::vector< unsigned int > newIndicesData; 28 | public: 29 | std::vector< int > blockNumbers; 30 | protected: 31 | std::vector< unsigned int > blockVertexRanges; 32 | std::vector< unsigned int > blockTriangleCounts; 33 | QDoubleSpinBox * targetCount; 34 | QDoubleSpinBox * maxError; 35 | QDoubleSpinBox * minTriangles; 36 | QCheckBox * lockBorders; 37 | QCheckBox * enablePrune; 38 | QDoubleSpinBox * normalWeight; 39 | QDoubleSpinBox * uvWeight; 40 | QDoubleSpinBox * colorWeight; 41 | QLabel * resultTriangles; 42 | QLabel * resultError; 43 | void findBlock( int blockNum ); 44 | bool loadGeometryData(); 45 | int getVertexBlock( unsigned int v ) const; 46 | public: 47 | void storeGeometryData( size_t newTriangleCnt ); 48 | SimplifyMeshDialog( NifModel * nifModel, const QModelIndex & index ); 49 | virtual ~SimplifyMeshDialog(); 50 | inline bool isValid() const 51 | { 52 | return ( numVerts > 0 && numTriangles > 0 && !blockNumbers.empty() && !errorFlag ); 53 | } 54 | public slots: 55 | virtual void updateIndices(); 56 | int exec() override; 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/message.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGE_H 2 | #define MESSAGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | Q_DECLARE_LOGGING_CATEGORY( ns ) 10 | Q_DECLARE_LOGGING_CATEGORY( nsGl ) 11 | Q_DECLARE_LOGGING_CATEGORY( nsIo ) 12 | Q_DECLARE_LOGGING_CATEGORY( nsNif ) 13 | Q_DECLARE_LOGGING_CATEGORY( nsSpell ) 14 | 15 | 16 | class QMessageLogContext; 17 | 18 | class Message : QObject 19 | { 20 | Q_OBJECT 21 | Message(); 22 | ~Message(); 23 | 24 | public: 25 | static QMessageBox* message( QWidget *, const QString &, QMessageBox::Icon ); 26 | static QMessageBox* message( QWidget *, const QString &, const QString &, QMessageBox::Icon ); 27 | static void message( QWidget *, const QString &, const QMessageLogContext *, QMessageBox::Icon ); 28 | 29 | static void append( const QString &, const QString &, QMessageBox::Icon = QMessageBox::Warning ); 30 | static void append( QWidget *, const QString &, const QString &, QMessageBox::Icon = QMessageBox::Warning ); 31 | 32 | static void critical( QWidget *, const QString & ); 33 | static void critical( QWidget *, const QString &, const QString & ); 34 | 35 | static void warning( QWidget *, const QString & ); 36 | static void warning( QWidget *, const QString &, const QString & ); 37 | 38 | static void info( QWidget *, const QString & ); 39 | static void info( QWidget *, const QString &, const QString & ); 40 | }; 41 | 42 | class TestMessage 43 | { 44 | public: 45 | TestMessage( QtMsgType t = QtWarningMsg ) : typ( t ) {} 46 | 47 | template TestMessage & operator<<(T); 48 | 49 | operator QString() const { return s; } 50 | 51 | QtMsgType type() const { return typ; } 52 | 53 | protected: 54 | QString s; 55 | QtMsgType typ; 56 | 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /res/shaders/skybox.frag: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | #include "uniforms.glsl" 4 | 5 | uniform samplerCube CubeMap; 6 | uniform bool hasCubeMap; 7 | 8 | in vec3 LightDir; 9 | in vec3 ViewDir; 10 | 11 | flat in mat3 reflMatrix; 12 | 13 | out vec4 fragColor; 14 | 15 | float LightingFuncGGX_REF( float LdotR, float roughness ) 16 | { 17 | float alpha = roughness * roughness; 18 | // D (GGX normal distribution) 19 | float alphaSqr = alpha * alpha; 20 | // denom = NdotH * NdotH * (alphaSqr - 1.0) + 1.0, 21 | // LdotR = NdotH * NdotH * 2.0 - 1.0 22 | float denom = LdotR * alphaSqr + alphaSqr + max(1.0 - LdotR, 0.0); 23 | // no pi because BRDF -> lighting 24 | return alphaSqr / (denom * denom); 25 | } 26 | 27 | vec3 tonemap(vec3 x, float y) 28 | { 29 | float a = 0.15; 30 | float b = 0.50; 31 | float c = 0.10; 32 | float d = 0.20; 33 | float e = 0.02; 34 | float f = 0.30; 35 | 36 | vec3 z = x * (y * 4.22978723); 37 | z = (z * (a * z + b * c) + d * e) / (z * (a * z + b) + d * f) - e / f; 38 | return z / (y * 0.93333333); 39 | } 40 | 41 | void main() 42 | { 43 | vec3 L = normalize( LightDir ); 44 | vec3 V = normalize( -ViewDir ); 45 | 46 | float VdotL = dot( V, L ); 47 | 48 | vec3 viewWS = reflMatrix * V; 49 | 50 | float m = clamp( float(cubeBgndMipLevel), 0.0, 6.0 ); 51 | 52 | // Environment 53 | vec3 color = lightSourceAmbient.rgb; 54 | if ( hasCubeMap ) { 55 | color *= textureLod( CubeMap, viewWS, m ).rgb; 56 | } else { 57 | color *= 0.08; 58 | } 59 | // Directional light 60 | if ( VdotL > 0.0 ) { 61 | float roughness = ( 5.0 - sqrt( 25.0 - 4.0 * m ) ) / 4.0; 62 | color += lightSourceDiffuse[0].rgb * LightingFuncGGX_REF( VdotL, max(roughness, 0.02) ) * VdotL; 63 | } 64 | 65 | fragColor = vec4( tonemap( color * brightnessScale, toneMapScale ), 0.0 ); 66 | } 67 | -------------------------------------------------------------------------------- /src/spells/fo3only.cpp: -------------------------------------------------------------------------------- 1 | #include "spellbook.h" 2 | 3 | 4 | // Brief description is deliberately not autolinked to class Spell 5 | /*! \file fo3only.cpp 6 | * \brief Fallout 3 specific spells (spFO3FixShapeDataName) 7 | * 8 | * All classes here inherit from the Spell class. 9 | */ 10 | 11 | //! Set the name of the NiGeometryData node to parent name or zero 12 | class spFO3FixShapeDataName final : public Spell 13 | { 14 | public: 15 | QString name() const override final { return Spell::tr( "Fix Geometry Data Names" ); } 16 | QString page() const override final { return Spell::tr( "Sanitize" ); } 17 | bool sanity() const override final { return true; } 18 | 19 | ////////////////////////////////////////////////////////////////////////// 20 | // Valid if nothing or NiGeometryData-based node is selected 21 | bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final 22 | { 23 | //if ( !index.isValid() ) 24 | // return false; 25 | 26 | if ( !nif->checkVersion( 0x14020007, 0x14020007 ) || (nif->getUserVersion() != 11) ) 27 | return false; 28 | 29 | return !index.isValid() || nif->getBlockIndex( index, "NiGeometryData" ).isValid(); 30 | } 31 | 32 | QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final 33 | { 34 | if ( index.isValid() && nif->getBlockIndex( index, "NiGeometryData" ).isValid() ) { 35 | nif->set( index, "Group ID", 0 ); 36 | } else { 37 | // set all blocks 38 | for ( int n = 0; n < nif->getBlockCount(); n++ ) { 39 | QModelIndex iBlock = nif->getBlockIndex( n ); 40 | 41 | if ( nif->getBlockIndex( iBlock, "NiGeometryData" ).isValid() ) { 42 | cast( nif, iBlock ); 43 | } 44 | } 45 | } 46 | 47 | return index; 48 | } 49 | }; 50 | 51 | REGISTER_SPELL( spFO3FixShapeDataName ) 52 | 53 | -------------------------------------------------------------------------------- /res/shaders/ob_default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | flat out vec4 A; 9 | out vec4 C; 10 | flat out vec4 D; 11 | 12 | out mat3 reflMatrix; 13 | 14 | #include "uniforms.glsl" 15 | 16 | uniform mat3 normalMatrix; // in row-major order 17 | uniform mat4 modelViewMatrix; 18 | 19 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 20 | 21 | layout ( location = 0 ) in vec3 vertexPosition; 22 | layout ( location = 1 ) in vec4 vertexColor; 23 | layout ( location = 2 ) in vec3 normalVector; 24 | layout ( location = 3 ) in vec3 tangentVector; 25 | layout ( location = 4 ) in vec3 bitangentVector; 26 | layout ( location = 7 ) in vec2 multiTexCoord0; 27 | 28 | #include "bonetransform.glsl" 29 | 30 | void main() 31 | { 32 | vec4 v = vec4( vertexPosition, 1.0 ); 33 | vec3 n = normalVector; 34 | vec3 t = tangentVector; 35 | vec3 b = bitangentVector; 36 | 37 | if ( boneWeights[0].x > 0.0 && doSkinning ) 38 | boneTransform( v, n, t, b ); 39 | 40 | v = modelViewMatrix * v; 41 | gl_Position = projectionMatrix * v; 42 | texCoord = multiTexCoord0; 43 | 44 | // NOTE: b<->t 45 | mat3 btnMatrix = mat3( normalize(b * normalMatrix), normalize(t * normalMatrix), normalize(n * normalMatrix) ); 46 | btnMatrix = transpose( btnMatrix ); 47 | 48 | reflMatrix = btnMatrix * envMapRotation; 49 | 50 | if ( projectionMatrix[3][3] == 1.0 ) 51 | ViewDir = btnMatrix * vec3(0.0, 0.0, 1.0); // orthographic view 52 | else 53 | ViewDir = btnMatrix * -v.xyz; 54 | LightDir = btnMatrix * lightSourcePosition[0].xyz; 55 | 56 | A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, toneMapScale ); 57 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 58 | D = vec4( sqrt(lightSourceDiffuse[0].rgb), brightnessScale ); 59 | } 60 | -------------------------------------------------------------------------------- /lib/meshlet.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------------- 2 | // DirectXMeshP.h, DirectXMesh.h 3 | // 4 | // DirectX Mesh Geometry Library 5 | // 6 | // Copyright (c) Microsoft Corporation. 7 | // Licensed under the MIT License. 8 | // 9 | // http://go.microsoft.com/fwlink/?LinkID=324981 10 | //------------------------------------------------------------------------------------- 11 | 12 | #ifndef MESHLET_H_INCLUDED 13 | #define MESHLET_H_INCLUDED 14 | 15 | #include "data/niftypes.h" 16 | #include "fp32vec4.hpp" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | namespace DirectX 25 | { 26 | //--------------------------------------------------------------------------------- 27 | constexpr uint32_t UNUSED32 = uint32_t(-1); 28 | 29 | //--------------------------------------------------------------------------------- 30 | // Meshlet Generation 31 | 32 | constexpr size_t MESHLET_DEFAULT_MAX_VERTS = 128u; 33 | constexpr size_t MESHLET_DEFAULT_MAX_PRIMS = 128u; 34 | 35 | constexpr size_t MESHLET_MINIMUM_SIZE = 32u; 36 | constexpr size_t MESHLET_MAXIMUM_SIZE = 256u; 37 | 38 | enum MESHLET_FLAGS : unsigned long 39 | { 40 | MESHLET_DEFAULT = 0x0, 41 | 42 | MESHLET_WIND_CW = 0x1, 43 | // Vertices are clock-wise (defaults to CCW) 44 | }; 45 | 46 | struct Meshlet 47 | { 48 | uint32_t VertCount; 49 | uint32_t VertOffset; 50 | uint32_t PrimCount; 51 | uint32_t PrimOffset; 52 | }; 53 | 54 | int ComputeMeshlets( 55 | const Triangle* triangles, size_t nFaces, const Vector3* positions, size_t nVerts, 56 | std::vector& meshlets, std::vector& primitiveIndices, 57 | size_t maxVerts = MESHLET_DEFAULT_MAX_VERTS, size_t maxPrims = MESHLET_DEFAULT_MAX_PRIMS); 58 | // Generates meshlets for a single subset mesh 59 | 60 | } // namespace DirectX 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /res/shaders/wireframe.geom: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | layout ( triangles ) in; 4 | layout ( triangle_strip, max_vertices = 12 ) out; 5 | 6 | #include "uniforms.glsl" 7 | 8 | uniform float lineWidth; 9 | 10 | in vec4 vsColor[]; 11 | out vec4 C; 12 | 13 | void drawLine( vec4 p0, vec4 p1, vec4 p1Color ) 14 | { 15 | float p0zw = p0.z + p0.w; 16 | float p1zw = p1.z + p1.w; 17 | if ( !( p0zw > 0.0 && p1zw > 0.0 ) ) { 18 | if ( p0zw > 0.000001 ) 19 | p1 = mix( p0, p1, p0zw / ( p0zw - p1zw ) ); 20 | else if ( p1zw > 0.000001 ) 21 | p0 = mix( p1, p0, p1zw / ( p1zw - p0zw ) ); 22 | else 23 | return; 24 | } 25 | 26 | vec3 p0_ndc = p0.xyz / p0.w; 27 | vec3 p1_ndc = p1.xyz / p1.w; 28 | 29 | vec2 vpScale = vec2( viewportDimensions.zw ) * 0.5; 30 | vec2 vpOffs = vec2( viewportDimensions.xy ) + vpScale; 31 | 32 | vec2 p0_ss = p0_ndc.xy * vpScale; 33 | vec2 p1_ss = p1_ndc.xy * vpScale; 34 | 35 | vec2 d = normalize( p1_ss - p0_ss ) * max( lineWidth * 0.5, 0.5 ); 36 | vec2 n = vec2( -d.y, d.x ) / vpScale; 37 | 38 | gl_Position = vec4( p0_ndc.xy + n, p0_ndc.z, 1.0 ); 39 | EmitVertex(); 40 | gl_Position = vec4( p0_ndc.xy - n, p0_ndc.z, 1.0 ); 41 | EmitVertex(); 42 | 43 | C = p1Color; 44 | 45 | gl_Position = vec4( p1_ndc.xy + n, p1_ndc.z, 1.0 ); 46 | EmitVertex(); 47 | gl_Position = vec4( p1_ndc.xy - n, p1_ndc.z, 1.0 ); 48 | EmitVertex(); 49 | 50 | EndPrimitive(); 51 | } 52 | 53 | void main() 54 | { 55 | vec4 p0 = projectionMatrix * gl_in[0].gl_Position; 56 | vec4 p1 = projectionMatrix * gl_in[1].gl_Position; 57 | vec4 p2 = projectionMatrix * gl_in[2].gl_Position; 58 | 59 | float alphaMult = min( lineWidth, 1.0 ); 60 | vec4 c0 = vec4( vsColor[0].rgb, vsColor[0].a * alphaMult ); 61 | C = c0; 62 | 63 | drawLine( p0, p1, vec4( vsColor[1].rgb, vsColor[1].a * alphaMult ) ); 64 | drawLine( p1, p2, vec4( vsColor[2].rgb, vsColor[2].a * alphaMult ) ); 65 | drawLine( p2, p0, c0 ); 66 | } 67 | -------------------------------------------------------------------------------- /res/shaders/fo4_default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoord; 7 | 8 | out mat3 btnMatrix; 9 | 10 | flat out vec4 A; 11 | out vec4 C; 12 | flat out vec4 D; 13 | 14 | flat out mat3 reflMatrix; 15 | 16 | #include "uniforms.glsl" 17 | 18 | uniform mat3 normalMatrix; // in row-major order 19 | uniform mat4 modelViewMatrix; 20 | 21 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 22 | 23 | layout ( location = 0 ) in vec3 vertexPosition; 24 | layout ( location = 1 ) in vec4 vertexColor; 25 | layout ( location = 2 ) in vec3 normalVector; 26 | layout ( location = 3 ) in vec3 tangentVector; 27 | layout ( location = 4 ) in vec3 bitangentVector; 28 | layout ( location = 7 ) in vec2 multiTexCoord0; 29 | 30 | #include "bonetransform.glsl" 31 | 32 | void main() 33 | { 34 | vec4 v = vec4( vertexPosition, 1.0 ); 35 | vec3 n = normalVector; 36 | vec3 t = tangentVector; 37 | vec3 b = bitangentVector; 38 | 39 | if ( boneWeights[0].x > 0.0 && doSkinning ) 40 | boneTransform( v, n, t, b ); 41 | 42 | v = modelViewMatrix * v; 43 | gl_Position = projectionMatrix * v; 44 | texCoord = multiTexCoord0; 45 | 46 | btnMatrix[2] = normalize( n * normalMatrix ); 47 | btnMatrix[1] = normalize( t * normalMatrix ); 48 | btnMatrix[0] = normalize( b * normalMatrix ); 49 | 50 | reflMatrix = envMapRotation; 51 | reflMatrix[0][2] *= -1.0; 52 | reflMatrix[1][2] *= -1.0; 53 | reflMatrix[2][2] *= -1.0; 54 | 55 | if ( projectionMatrix[3][3] == 1.0 ) 56 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 57 | else 58 | ViewDir = -v.xyz; 59 | LightDir = lightSourcePosition[0].xyz; 60 | 61 | A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, toneMapScale ); 62 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 63 | D = vec4( sqrt(lightSourceDiffuse[0].rgb), brightnessScale ); 64 | } 65 | -------------------------------------------------------------------------------- /lib/miniball/Seb_point.h: -------------------------------------------------------------------------------- 1 | // Synopsis: Simple point class 2 | // 3 | // Authors: Martin Kutz , 4 | // Kaspar Fischer 5 | 6 | #ifndef SEB_POINT_H 7 | #define SEB_POINT_H 8 | 9 | #include 10 | #include "Seb_configure.h" 11 | 12 | namespace SEB_NAMESPACE { 13 | 14 | template 15 | class Point 16 | // A simple class representing a d-dimensional point. 17 | { 18 | public: // types: 19 | typedef typename std::vector::const_iterator Const_iterator; 20 | typedef typename std::vector::iterator Iterator; 21 | 22 | public: // construction and destruction: 23 | 24 | Point(int d) 25 | // Constructs a d-dimensional point with undefined coordinates. 26 | : c(d) 27 | { 28 | } 29 | 30 | template 31 | Point(int d,InputIterator first) 32 | // Constructs a d-dimensional point with Cartesian center 33 | // coordinates [first,first+d). 34 | : c(first,first+d) 35 | { 36 | } 37 | 38 | public: // access: 39 | 40 | const Float& operator[](unsigned int i) const 41 | // Returns a const-reference to the i-th coordinate. 42 | { 43 | SEB_ASSERT(0 <= i && i < c.size()); 44 | return c[i]; 45 | } 46 | 47 | Float& operator[](unsigned int i) 48 | // Returns a reference to the i-th coordinate. 49 | { 50 | SEB_ASSERT(0 <= i && i < c.size()); 51 | return c[i]; 52 | } 53 | 54 | Const_iterator begin() const 55 | // Returns a const-iterator to the first of the d Cartesian coordinates. 56 | { 57 | return c.begin(); 58 | } 59 | 60 | Const_iterator end() const 61 | // Returns the past-the-end iterator corresponding to begin(). 62 | { 63 | return c.end(); 64 | } 65 | 66 | private: // member fields: 67 | std::vector c; // Cartesian center coordinates 68 | }; 69 | 70 | } // namespace SEB_NAMESPACE 71 | 72 | #endif // SEB_POINT_H 73 | -------------------------------------------------------------------------------- /lib/libfo76utils/scripts/plotsrgb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | import matplotlib 5 | if sys.platform[:5] == "linux": 6 | matplotlib.use('TkAgg') 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | import math 10 | 11 | x0 = 0.0 12 | x1 = 1.0 13 | y0 = -0.01 14 | y1 = 1.01 15 | 16 | xdata = [] 17 | ydata = [[], [], [], [], [], [], []] 18 | 19 | def fromSRGB(x): 20 | y = x / 12.92 21 | if y > 0.0031308: 22 | y = math.pow((x + 0.055) / 1.055, 2.4) 23 | return y 24 | 25 | def toSRGB(x): 26 | if x > 0.0031308: 27 | return math.pow(x, 1.0 / 2.4) * 1.055 - 0.055 28 | return x * 12.92 29 | 30 | for i in range(1025): 31 | x = (i / 1024.0) * (x1 - x0) + x0 32 | x = max(x, 0.0) 33 | xdata += [x] 34 | ydata[0] += [toSRGB(x)] 35 | y1 = math.sqrt(x) 36 | y1 = (y1 * -0.13942692 + 1.13942692) * y1 37 | ydata[1] += [y1] 38 | ydata[2] += [fromSRGB(x)] 39 | y3 = (x * 0.13945550 + 0.86054450) * x 40 | y3 = y3 * y3 41 | ydata[3] += [y3] 42 | ydata[4] += [x] 43 | y5 = math.sqrt(max(y3, 0.0)) 44 | y5 = (y5 * -0.13942692 + 1.13942692) * y5 45 | ydata[5] += [y5] 46 | y6 = x * x 47 | y6 = (y6 * 0.16916572 + 0.83083428) * y6 48 | ydata[6] += [y6] 49 | 50 | # plot the data 51 | fig = plt.figure() 52 | ax = fig.add_subplot(1, 1, 1) 53 | ax.plot(xdata, ydata[0], color='tab:blue', label='Linear -> sRGB') 54 | ax.plot(xdata, ydata[1], color='tab:red', label='FloatVector4::srgbCompress()') 55 | ax.plot(xdata, ydata[2], color='tab:cyan', label='sRGB -> Linear') 56 | ax.plot(xdata, ydata[3], color='tab:orange', label='FloatVector4::srgbExpand()') 57 | ax.plot(xdata, ydata[4], color='tab:green', label='Linear') 58 | ax.plot(xdata, ydata[5], color='tab:olive', label='sRGB -> Linear -> sRGB') 59 | ax.plot(xdata, ydata[6], color='tab:pink', label='FloatVector4 sRGB bilinear') 60 | 61 | # set the limits 62 | ax.set_xlim([x0, x1]) 63 | ax.set_ylim([y0, y1]) 64 | ax.grid(True) 65 | plt.legend() 66 | 67 | # display the plot 68 | plt.show() 69 | 70 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/bits.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015 Harm Hanemaaijer 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | */ 18 | 19 | #include "detex.h" 20 | #include "bits.h" 21 | 22 | uint32_t detexBlock128ExtractBits(detexBlock128 *block, int nu_bits) { 23 | uint32_t value = 0; 24 | for (int i = 0; i < nu_bits; i++) { 25 | if (block->index < 64) { 26 | int shift = block->index - i; 27 | if (shift < 0) 28 | value |= (block->data0 & ((uint64_t)1 << block->index)) << (- shift); 29 | else 30 | value |= (block->data0 & ((uint64_t)1 << block->index)) >> shift; 31 | } 32 | else { 33 | int shift = ((block->index - 64) - i); 34 | if (shift < 0) 35 | value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) << (- shift); 36 | else 37 | value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) >> shift; 38 | } 39 | block->index++; 40 | } 41 | // if (block->index > 128) 42 | // printf("Block overflow (%d)\n", block->index); 43 | return value; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /res/shaders/default.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec3 LightDir; 4 | out vec3 ViewDir; 5 | 6 | out vec2 texCoords[9]; 7 | 8 | flat out vec4 A; 9 | out vec4 C; 10 | flat out vec4 D; 11 | 12 | out vec3 N; 13 | 14 | #include "uniforms.glsl" 15 | 16 | uniform mat3 normalMatrix; // in row-major order 17 | uniform mat4 modelViewMatrix; 18 | 19 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 20 | 21 | layout ( location = 0 ) in vec3 vertexPosition; 22 | layout ( location = 1 ) in vec4 vertexColor; 23 | layout ( location = 2 ) in vec3 normalVector; 24 | layout ( location = 7 ) in vec2 multiTexCoord0; 25 | layout ( location = 8 ) in vec2 multiTexCoord1; 26 | layout ( location = 9 ) in vec2 multiTexCoord2; 27 | layout ( location = 10 ) in vec2 multiTexCoord3; 28 | layout ( location = 11 ) in vec2 multiTexCoord4; 29 | layout ( location = 12 ) in vec2 multiTexCoord5; 30 | layout ( location = 13 ) in vec2 multiTexCoord6; 31 | layout ( location = 14 ) in vec2 multiTexCoord7; 32 | layout ( location = 15 ) in vec2 multiTexCoord8; 33 | 34 | #define BT_NO_TANGENTS 1 35 | #include "bonetransform.glsl" 36 | 37 | void main() 38 | { 39 | vec4 v = vec4( vertexPosition, 1.0 ); 40 | vec3 n = normalVector; 41 | 42 | if ( boneWeights[0].x > 0.0 && doSkinning ) 43 | boneTransform( v, n ); 44 | 45 | v = modelViewMatrix * v; 46 | gl_Position = projectionMatrix * v; 47 | texCoords[0] = multiTexCoord0; 48 | texCoords[1] = multiTexCoord1; 49 | texCoords[2] = multiTexCoord2; 50 | texCoords[3] = multiTexCoord3; 51 | texCoords[4] = multiTexCoord4; 52 | texCoords[5] = multiTexCoord5; 53 | texCoords[6] = multiTexCoord6; 54 | texCoords[7] = multiTexCoord7; 55 | texCoords[8] = multiTexCoord8; 56 | 57 | N = normalize( n * normalMatrix ); 58 | 59 | if ( projectionMatrix[3][3] == 1.0 ) 60 | ViewDir = vec3(0.0, 0.0, 1.0); // orthographic view 61 | else 62 | ViewDir = -v.xyz; 63 | LightDir = lightSourcePosition[0].xyz; 64 | 65 | A = vec4( sqrt(lightSourceAmbient.rgb) * 0.375, toneMapScale ); 66 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 67 | D = sqrt( vec4(lightSourceDiffuse[0].rgb, brightnessScale) ); 68 | } 69 | -------------------------------------------------------------------------------- /src/qt5compat.hpp: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2025, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef QT5COMPAT_HPP_INCLUDED 34 | #define QT5COMPAT_HPP_INCLUDED 35 | 36 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 37 | 38 | // Qt 5 39 | 40 | #ifndef QLatin1StringView 41 | using QLatin1StringView = QLatin1String; 42 | #endif 43 | 44 | #define getQVariantMetaType( v ) QMetaType::Type( v.type() ) 45 | #define getQMouseEventPosition( e ) e->localPos() 46 | 47 | #else 48 | 49 | // Qt 6 50 | 51 | #define getQVariantMetaType( v ) QMetaType::Type( v.typeId() ) 52 | #define getQMouseEventPosition( e ) e->position() 53 | 54 | #endif 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /lib/libfo76utils/scripts/make_lut.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "common.hpp" 3 | #include "filebuf.hpp" 4 | #include "pbr_lut.hpp" 5 | 6 | int main() 7 | { 8 | SF_PBR_Tables t(512); 9 | const std::vector< unsigned char >& buf = t.getImageData(); 10 | std::FILE *f = std::fopen("brdf_1.dds", "wb"); 11 | std::fwrite(buf.data(), 1, buf.size(), f); 12 | std::fclose(f); 13 | f = std::fopen("brdf_2.dds", "wb"); 14 | std::fwrite(buf.data(), 1, 148, f); 15 | size_t n = (buf.size() - 148) / sizeof(std::uint32_t); 16 | unsigned char prvByte = 0; 17 | for (size_t i = 0; i < (n * sizeof(std::uint32_t)); i++) 18 | { 19 | std::uint32_t c = 20 | FileBuffer::readUInt32Fast(buf.data() + 148 + ((i & (n - 1)) << 2)); 21 | unsigned char b; 22 | if (i < n) 23 | { 24 | b = (unsigned char) (c & 0xFF); 25 | } 26 | else if (i < (n * 2)) 27 | { 28 | b = (unsigned char) ((c >> 10) & 0xFF); 29 | } 30 | else if (i < (n * 3)) 31 | { 32 | b = (unsigned char) ((c >> 20) & 0xFF); 33 | } 34 | else 35 | { 36 | b = (unsigned char) (((c >> 8) & 0x03) | ((c >> 16) & 0x0C) 37 | | ((c >> 24) & 0xF0)); 38 | } 39 | std::fputc((b - prvByte) & 0xFF, f); 40 | prvByte = b; 41 | } 42 | std::fclose(f); 43 | std::remove("brdf_2.dds.zlib"); 44 | std::system("zopfli --zlib --i100 brdf_2.dds"); 45 | FileBuffer inFile("brdf_2.dds.zlib"); 46 | std::printf("static const size_t pbr_lut_data_size = %u;\n", 47 | (unsigned int) buf.size()); 48 | std::printf("static const unsigned char pbr_lut_data_zlib[%u] = {\n", 49 | (unsigned int) inFile.size()); 50 | std::string lineBuf; 51 | for (size_t i = 0; i < inFile.size(); i++) 52 | { 53 | if (lineBuf.empty()) 54 | printToString(lineBuf, "\t%u", (unsigned int) inFile[i]); 55 | else 56 | printToString(lineBuf, ", %u", (unsigned int) inFile[i]); 57 | if (lineBuf.size() > 70 || (i + 1) >= inFile.size()) 58 | { 59 | lineBuf += ((i + 1) < inFile.size() ? ",\n" : "\n"); 60 | std::fwrite(lineBuf.c_str(), 1, lineBuf.length(), stdout); 61 | lineBuf.clear(); 62 | } 63 | } 64 | std::printf("};\n"); 65 | return 0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/ui/widgets/refrbrowser.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef REFRBROWSER_H 34 | #define REFRBROWSER_H 35 | 36 | #include // Inherited 37 | #include 38 | 39 | 40 | class NifModel; 41 | class QModelIndex; 42 | 43 | class ReferenceBrowser final : public QTextBrowser 44 | { 45 | Q_OBJECT 46 | 47 | public: 48 | ReferenceBrowser( QWidget * parent = nullptr ); 49 | 50 | public slots: 51 | void setNifModel( NifModel * ); 52 | void setSourceFile( const QString & ); 53 | void browse( const QModelIndex & ); 54 | 55 | private: 56 | NifModel * nif; 57 | bool docFolderPresent; 58 | QDir docFolder; 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /res/style.qss: -------------------------------------------------------------------------------- 1 | /* Variables: 2 | Qt Colors: 3 | palette(base) 4 | palette(alternate-base) 5 | palette(text) 6 | palette(highlight) 7 | palette(highlighted-text) 8 | palette(bright-text) 9 | 10 | Template Variables: 11 | ${theme} = Theme name ("dark", "light") for icon path customization 12 | ${rgb} = Highlight colors in an "R, G, B" string to combine with opacity in rgba() 13 | */ 14 | 15 | 16 | /* Remove light border for dark theme */ 17 | QToolBar { border: 1px solid transparent; } 18 | 19 | /* Fix tooltip display */ 20 | QToolTip { color: #ffffff; background-color: #555; border: 1px solid transparent; } 21 | 22 | /* Fix display of Settings category list */ 23 | QListWidget#categoryList { padding: 10px; } 24 | QListWidget#categoryList::item { height: 20px; padding: 10px; } 25 | QListWidget#categoryList::item::text { padding-left: 10px; } 26 | 27 | /* Fix display of close/undock for dark themes */ 28 | QDockWidget { 29 | titlebar-close-icon: url(:/wnd/close); 30 | titlebar-normal-icon: url(:/wnd/undock); 31 | } 32 | 33 | /* Toolbar Buttons */ 34 | 35 | /* Flyout menus need padding for down arrow */ 36 | #btnFlyoutMenu { padding-left: 2px; padding-right: 10px; } 37 | 38 | /* Fix toolbar button spacing */ 39 | #tRender QToolButton#btnRender:enabled, 40 | #tAnim QToolButton:enabled, 41 | #mLight QAbstractButton { 42 | padding: 1px 1px; 43 | margin: 0px 0px 0px 1px; 44 | border-radius: 2px; 45 | border: 1px solid transparent; 46 | } 47 | 48 | /* Selected toolbar buttons */ 49 | #tRender QToolButton#btnRender:enabled:checked, 50 | #tAnim QToolButton:enabled:checked, 51 | #mLight QAbstractButton:enabled:checked { 52 | border: 1px solid rgba(0, 0, 0, 32); 53 | background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.66, fx:0.5, fy:0.5, stop:0 rgba(255, 255, 255, 0), stop:0.5 rgba(${rgb}, 32), stop:1 rgba(${rgb}, 128)); 54 | } 55 | 56 | /* Hovered toolbar buttons */ 57 | #tRender QToolButton#btnRender:enabled:hover, 58 | #tAnim QToolButton:enabled:hover, 59 | #mLight QAbstractButton:enabled:hover { 60 | border: 1px solid rgba(${rgb}, 255); 61 | background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.66, fx:0.5, fy:0.5, stop:0 rgba(255, 255, 255, 0), stop:0.33 rgba(${rgb}, 64), stop:1 rgba(${rgb}, 128)); 62 | } 63 | -------------------------------------------------------------------------------- /src/lib/qhull.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef _QHULL_H 34 | #define _QHULL_H 35 | 36 | #include 37 | 38 | class Triangle; 39 | class Vector3; 40 | class Vector4; 41 | 42 | //! \file qhull.h Header for computing a convex hull 43 | 44 | //! Computes a convex hull using Qhull, 45 | //! Copyright (c) 1993-2010 C.B. Barber and The Geometry Center. 46 | QVector compute_convex_hull( const QVector & verts, 47 | QVector & hullVerts, 48 | QVector & hullNorms, 49 | float roundError = 0 ); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /res/shaders/selection.vert: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | out vec4 C; 4 | 5 | #include "uniforms.glsl" 6 | 7 | uniform mat4 modelViewMatrix; 8 | 9 | uniform vec4 vertexColorOverride; // components greater than zero replace the vertex color 10 | uniform vec4 highlightColor; 11 | 12 | // bit 0 = Scene::selecting 13 | // bit 1 = vertex mode (drawing points instead of triangles) 14 | // bit 2 = triangle selection mode (primitive ID << 15 is added to the color) 15 | // bit 3 = draw bone weights 16 | // bits 8 to 15 = point size * 8 (0: do not draw smooth points) 17 | uniform int selectionFlags; 18 | // if Scene::selecting == false: vertex selected (-1: none) 19 | // if Scene::selecting == true: value to add to color key (e.g. shapeID << 16) 20 | uniform int selectionParam; 21 | 22 | layout ( location = 0 ) in vec3 vertexPosition; 23 | layout ( location = 1 ) in vec4 vertexColor; 24 | 25 | #define BT_POSITION_ONLY 1 26 | #include "bonetransform.glsl" 27 | 28 | vec4 boneWeightsColor() 29 | { 30 | vec4 vcSum = vec4( 0.0 ); 31 | float wSum = 0.0; 32 | for ( int i = 0; i < 8; i++ ) { 33 | float w = boneWeights[i >> 2][i & 3]; 34 | if ( !( w > 0.0 ) ) 35 | break; 36 | int b = int( w ); 37 | w = fract( w ); 38 | int vc = ( b & 0x0049 ) | ( ( b & 0x0092 ) << 7 ) | ( ( b & 0x0124 ) << 14 ); 39 | vc = ( ( vc & 0x00010101 ) << 7 ) | ( ( vc & 0x00080808 ) << 3 ) | ( ( vc & 0x00404040 ) >> 1 ); 40 | vcSum += unpackUnorm4x8( uint( vc ) ^ 0xE0E0E0E0u ) * w; 41 | wSum += w; 42 | } 43 | if ( wSum > 0.0 ) 44 | vcSum /= wSum; 45 | return vcSum; 46 | } 47 | 48 | void main() 49 | { 50 | if ( ( selectionFlags & 1 ) != 0 ) { 51 | int colorKey = selectionParam + 1; 52 | if ( ( selectionFlags & 2 ) != 0 ) 53 | colorKey = colorKey + gl_VertexID; 54 | C = unpackUnorm4x8( uint( colorKey ) ) + vec4( 0.0005 ); 55 | } else if ( !( gl_VertexID == selectionParam && ( selectionFlags & 2 ) != 0 ) ) { 56 | C = mix( vertexColor, vertexColorOverride, greaterThan( vertexColorOverride, vec4( 0.0 ) ) ); 57 | } else { 58 | C = highlightColor; 59 | } 60 | 61 | vec4 v = vec4( vertexPosition, 1.0 ); 62 | 63 | if ( boneWeights[0].x > 0.0 ) { 64 | if ( doSkinning ) 65 | boneTransform( v ); 66 | if ( ( selectionFlags & 8 ) != 0 ) 67 | C = boneWeightsColor(); 68 | } 69 | 70 | v = projectionMatrix * ( modelViewMatrix * v ); 71 | 72 | gl_Position = v; 73 | } 74 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/mman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sys/mman.h 3 | * mman-win32 4 | */ 5 | 6 | #ifndef _SYS_MMAN_H_ 7 | #define _SYS_MMAN_H_ 8 | 9 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 10 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 11 | #endif 12 | 13 | /* All the headers include this file. */ 14 | #ifndef _MSC_VER 15 | #include <_mingw.h> 16 | #endif 17 | 18 | #if defined(MMAN_LIBRARY_DLL) 19 | /* Windows shared libraries (DLL) must be declared export when building the lib and import when building the 20 | application which links against the library. */ 21 | #if defined(MMAN_LIBRARY) 22 | #define MMANSHARED_EXPORT __declspec(dllexport) 23 | #else 24 | #define MMANSHARED_EXPORT __declspec(dllimport) 25 | #endif /* MMAN_LIBRARY */ 26 | #else 27 | /* Static libraries do not require a __declspec attribute.*/ 28 | #define MMANSHARED_EXPORT 29 | #endif /* MMAN_LIBRARY_DLL */ 30 | 31 | /* Determine offset type */ 32 | #include 33 | #if defined(_WIN64) 34 | typedef int64_t OffsetType; 35 | #else 36 | typedef uint32_t OffsetType; 37 | #endif 38 | 39 | #include 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #define PROT_NONE 0 46 | #define PROT_READ 1 47 | #define PROT_WRITE 2 48 | #define PROT_EXEC 4 49 | 50 | #define MAP_FILE 0 51 | #define MAP_SHARED 1 52 | #define MAP_PRIVATE 2 53 | #define MAP_TYPE 0xf 54 | #define MAP_FIXED 0x10 55 | #define MAP_ANONYMOUS 0x20 56 | #define MAP_ANON MAP_ANONYMOUS 57 | 58 | #define MAP_FAILED ((void *)-1) 59 | 60 | /* Flags for msync. */ 61 | #define MS_ASYNC 1 62 | #define MS_SYNC 2 63 | #define MS_INVALIDATE 4 64 | 65 | /* fildes is expected to be a HANDLE from CreateFile() */ 66 | MMANSHARED_EXPORT void* mmap(void *addr, size_t len, int prot, int flags, uintptr_t fildes, OffsetType off); 67 | MMANSHARED_EXPORT int munmap(void *addr, size_t len); 68 | MMANSHARED_EXPORT int _mprotect(void *addr, size_t len, int prot); 69 | MMANSHARED_EXPORT int msync(void *addr, size_t len, int flags); 70 | MMANSHARED_EXPORT int mlock(const void *addr, size_t len); 71 | MMANSHARED_EXPORT int munlock(const void *addr, size_t len); 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* _SYS_MMAN_H_ */ 78 | -------------------------------------------------------------------------------- /install/win-install/nifskope-mingw-static.nsi: -------------------------------------------------------------------------------- 1 | ; *** REQUIRES MOREINFO PLUGIN *** 2 | ; Download the MoreInfo zip file from http://nsis.sourceforge.net/MoreInfo_plug-in 3 | ; and copy the Plugins\MoreInfo.dll file to your NSIS Plugins folder. 4 | 5 | ; NifSkope Self-Installer for Windows (MinGW static build) 6 | ; (NifTools - http://niftools.sourceforge.net) 7 | ; (NSIS - http://nsis.sourceforge.net) 8 | ; 9 | ; Copyright (c) 2005-2012, NIF File Format Library and Tools 10 | ; All rights reserved. 11 | ; 12 | ; Redistribution and use in source and binary forms, with or without 13 | ; modification, are permitted provided that the following conditions are 14 | ; met: 15 | ; 16 | ; * Redistributions of source code must retain the above copyright 17 | ; notice, this list of conditions and the following disclaimer. 18 | ; * Redistributions in binary form must reproduce the above copyright 19 | ; notice, this list of conditions and the following disclaimer in the 20 | ; documentation ; and/or other materials provided with the 21 | ; distribution. 22 | ; * Neither the name of the NIF File Format Library and Tools project 23 | ; nor the names of its contributors may be used to endorse or promote 24 | ; products derived from this software without specific prior written 25 | ; permission. 26 | ; 27 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 28 | ; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 29 | ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 | ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 31 | ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 | ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 | ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | SetCompressor /SOLID lzma 40 | 41 | !define INSTALLERPOSTFIX "windows" 42 | 43 | !macro InstallHook 44 | ; pack dll files 45 | SetOutPath $INSTDIR 46 | File ..\release\mingwm10.dll 47 | !macroend 48 | 49 | !include "nifskope.nsh" 50 | 51 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/bits.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015 Harm Hanemaaijer 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | */ 18 | 19 | /* Data structure used to extract bits from 128-bit bitstring. */ 20 | 21 | typedef struct { 22 | uint64_t data0; 23 | uint64_t data1; 24 | int index; 25 | } detexBlock128; 26 | 27 | uint32_t detexBlock128ExtractBits(detexBlock128 *block, int nu_bits); 28 | 29 | /* Return bitfield from bit0 to bit1 from 64-bit bitstring. */ 30 | static DETEX_INLINE_ONLY uint32_t detexGetBits64(uint64_t data, int bit0, int bit1) { 31 | return (data & (((uint64_t)1 << bit1) | (((uint64_t)1 << bit1) - 1))) >> bit0; 32 | } 33 | 34 | /* Return reversed bitfield (bit1 to bit0) from 64-bit bitstring. */ 35 | static DETEX_INLINE_ONLY uint32_t detexGetBits64Reversed(uint64_t data, int bit0, int bit1) { 36 | // Assumes bit0 > bit1. 37 | // Reverse the bits. 38 | uint32_t val = 0; 39 | data = data >> bit1; 40 | for (int i = bit1; i <= bit0; i++, data = data >> 1) 41 | val = (val << 1) | (data & 1U); 42 | return val; 43 | } 44 | 45 | /* Clear bit0 to bit1 of 64-bit bitstring. */ 46 | static DETEX_INLINE_ONLY uint64_t detexClearBits64(uint64_t data, int bit0, int bit1) { 47 | uint64_t mask = ~(((uint64_t)1 << (bit1 + 1)) - 1); 48 | mask |= ((uint64_t)1 << bit0) - 1; 49 | return data & mask; 50 | } 51 | 52 | /* Set bit0 to bit1 of 64-bit bitstring. */ 53 | static DETEX_INLINE_ONLY uint64_t detexSetBits64(uint64_t data, int bit0, int bit1, uint64_t val) { 54 | uint64_t d = detexClearBits64(data, bit0, bit1); 55 | d |= val << bit0; 56 | return d; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /lib/libfo76utils/scripts/plotpoly.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | import matplotlib 5 | if sys.platform[:5] == "linux": 6 | matplotlib.use('TkAgg') 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | import math 10 | 11 | x0 = -1.0 12 | x1 = 1.0 13 | y0 = 0.0 14 | y1 = 2.0 15 | 16 | def solveEquationSystem(m): 17 | h = len(m) 18 | w = len(m[0]) 19 | # Gaussian elimination 20 | for i in range(h): 21 | a = m[i][i] 22 | l = i 23 | for j in range(i + 1, h): 24 | if abs(m[j][i]) > abs(a): 25 | a = m[j][i] 26 | l = j 27 | if l != i: 28 | tmp = m[i] 29 | m[i] = m[l] 30 | m[l] = tmp 31 | for j in range(w): 32 | m[i][j] = m[i][j] / a 33 | m[i][i] = 1.0 34 | for j in range(i + 1, h): 35 | a = m[j][i] 36 | for k in range(w): 37 | m[j][k] = m[j][k] - (m[i][k] * a) 38 | m[j][i] = 0.0 39 | for i in range(h - 1, -1, -1): 40 | for j in range(i - 1, -1, -1): 41 | a = m[j][i] 42 | for k in range(w): 43 | m[j][k] = m[j][k] - (m[i][k] * a) 44 | m[j][i] = 0.0 45 | return m 46 | 47 | a = [] 48 | k = -1 49 | 50 | if len(sys.argv) >= 9 and (len(sys.argv) & 1) == 1: 51 | k = (len(sys.argv) - 3) >> 1 52 | m = [] 53 | for i in range(k + 1): 54 | m += [[]] 55 | for i in range(k + 1): 56 | m[i] += [1.0, float(sys.argv[(i << 1) + 1])] 57 | for j in range(2, k + 1): 58 | m[i] += [m[i][j - 1] * m[i][1]] 59 | m[i] += [float(sys.argv[(i << 1) + 2])] 60 | m = solveEquationSystem(m) 61 | for i in range(k + 1): 62 | a += [m[i][k + 1]] 63 | print(a) 64 | else: 65 | k = len(sys.argv) - 2 66 | for i in range(k + 1, 0, -1): 67 | a += [float(sys.argv[i])] 68 | 69 | xdata = [] 70 | ydata = [] 71 | 72 | for i in range(1025): 73 | x = (i / 1024.0) * (x1 - x0) + x0 74 | xdata += [x] 75 | y = 0.0 76 | for j in range(k, -1, -1): 77 | y = y * x + a[j] 78 | ydata += [y] 79 | 80 | # plot the data 81 | fig = plt.figure() 82 | ax = fig.add_subplot(1, 1, 1) 83 | ax.plot(xdata, ydata, color='tab:blue') 84 | 85 | # set the limits 86 | ax.set_xlim([x0, x1]) 87 | ax.set_ylim([y0, y1]) 88 | ax.grid(True) 89 | 90 | # display the plot 91 | plt.show() 92 | 93 | -------------------------------------------------------------------------------- /src/ui/checkablemessagebox.h: -------------------------------------------------------------------------------- 1 | #ifndef CHECKABLEMESSAGEBOX_H 2 | #define CHECKABLEMESSAGEBOX_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | struct CheckableMessageBoxPrivate; 11 | 12 | class CheckableMessageBox : public QDialog 13 | { 14 | Q_OBJECT 15 | Q_PROPERTY(QString text READ text WRITE setText) 16 | Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap) 17 | Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked) 18 | Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText) 19 | Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons) 20 | Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton) 21 | public: 22 | explicit CheckableMessageBox( QWidget * parent ); 23 | virtual ~CheckableMessageBox(); 24 | 25 | static QDialogButtonBox::StandardButton 26 | question( QWidget * parent, 27 | const QString & title, 28 | const QString & question, 29 | const QString & checkBoxText, 30 | bool * checkBoxSetting, 31 | QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, 32 | QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No ); 33 | 34 | QString text() const; 35 | void setText( const QString & ); 36 | 37 | bool isChecked() const; 38 | void setChecked( bool s ); 39 | 40 | QString checkBoxText() const; 41 | void setCheckBoxText( const QString & ); 42 | 43 | QDialogButtonBox::StandardButtons standardButtons() const; 44 | void setStandardButtons( QDialogButtonBox::StandardButtons s ); 45 | 46 | QDialogButtonBox::StandardButton defaultButton() const; 47 | void setDefaultButton( QDialogButtonBox::StandardButton s ); 48 | 49 | QPixmap iconPixmap() const; 50 | void setIconPixmap( const QPixmap & p ); 51 | 52 | // Query the result 53 | QAbstractButton * clickedButton() const; 54 | QDialogButtonBox::StandardButton clickedStandardButton() const; 55 | 56 | // Conversion convenience 57 | static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton( QDialogButtonBox::StandardButton ); 58 | 59 | private slots: 60 | void slotClicked( QAbstractButton * b ); 61 | 62 | private: 63 | CheckableMessageBoxPrivate * m_d; 64 | }; 65 | 66 | 67 | #endif // CHECKABLEMESSAGEBOX_H 68 | -------------------------------------------------------------------------------- /src/ui/widgets/groupbox.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef GROUPBOX_H 34 | #define GROUPBOX_H 35 | 36 | #include // Inherited 37 | #include 38 | #include 39 | 40 | 41 | class GroupBox final : public QGroupBox 42 | { 43 | QStack lay; 44 | 45 | public: 46 | GroupBox( Qt::Orientation o ); 47 | GroupBox( const QString & title, Qt::Orientation o ); 48 | ~GroupBox(); 49 | 50 | void addWidget( QWidget * widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment() ); 51 | 52 | QWidget * pushLayout( const QString & name, Qt::Orientation o, int stretch = 0, Qt::Alignment alignment = Qt::Alignment() ); 53 | void pushLayout( Qt::Orientation o, int stretch = 0 ); 54 | 55 | void popLayout(); 56 | 57 | static QBoxLayout::Direction o2d( Qt::Orientation o ); 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/spells/bounds.cpp: -------------------------------------------------------------------------------- 1 | #include "spellbook.h" 2 | 3 | #include "ui/widgets/nifeditors.h" 4 | 5 | 6 | // Brief description is deliberately not autolinked to class Spell 7 | /*! \file bounds.cpp 8 | * \brief Bounding box editing spells (spEditBounds) 9 | * 10 | * All classes here inherit from the Spell class. 11 | */ 12 | 13 | //! Edit a bounding box 14 | class spEditBounds final : public Spell 15 | { 16 | public: 17 | QString name() const override final { return Spell::tr( "Edit" ); } 18 | QString page() const override final { return Spell::tr( "Bounds" ); } 19 | 20 | bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final 21 | { 22 | return (nif->itemName( index ) == "BSBound") 23 | || (nif->itemName( index.parent() ) == "BSBound" ) 24 | || (nif->get( index, "Has Bounding Box" ) == true) 25 | || (nif->itemName( index ) == "Bounding Box") 26 | || (nif->itemName( index.parent() ) == "Bounding Box"); 27 | } 28 | 29 | QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final 30 | { 31 | NifBlockEditor * edit = new NifBlockEditor( nif, nif->getBlockIndex( index ) ); 32 | 33 | if ( nif->get( index, "Has Bounding Box" ) == true || nif->itemName( index ) == "Bounding Box" || nif->itemName( index.parent() ) == "Bounding Box" ) { 34 | QModelIndex iBound; 35 | 36 | if ( nif->itemName( index ) == "Bounding Box" ) { 37 | iBound = index; 38 | } else if ( nif->itemName( index.parent() ) == "Bounding Box" ) { 39 | iBound = index.parent(); 40 | } else { 41 | iBound = nif->getIndex( index, "Bounding Box" ); 42 | } 43 | 44 | edit->add( new NifVectorEdit( nif, nif->getIndex( iBound, "Translation" ) ) ); 45 | edit->add( new NifRotationEdit( nif, nif->getIndex( iBound, "Rotation" ) ) ); 46 | edit->add( new NifVectorEdit( nif, nif->getIndex( iBound, "Radius" ) ) ); 47 | } else if ( nif->itemName( index ) == "BSBound" || nif->itemName( index.parent() ) == "BSBound" ) { 48 | QModelIndex iBound; 49 | 50 | if ( nif->itemName( index ) == "BSBound" ) { 51 | iBound = index; 52 | } else if ( nif->itemName( index.parent() ) == "BSBound" ) { 53 | iBound = index.parent(); 54 | } 55 | 56 | edit->add( new NifVectorEdit( nif, nif->getIndex( iBound, "Center" ) ) ); 57 | edit->add( new NifVectorEdit( nif, nif->getIndex( iBound, "Dimensions" ) ) ); 58 | } 59 | 60 | edit->show(); 61 | return index; 62 | } 63 | }; 64 | 65 | REGISTER_SPELL( spEditBounds ) 66 | -------------------------------------------------------------------------------- /src/lib/nvtristripwrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "nvtristripwrapper.h" 2 | #include "data/niftypes.h" 3 | 4 | #include "meshoptimizer/src/meshoptimizer.h" 5 | 6 | 7 | QVector > stripify( const QVector & triangles, bool stitch ) 8 | { 9 | QVector> strips; 10 | 11 | if ( triangles.isEmpty() ) 12 | return strips; 13 | 14 | size_t numTriangles = size_t( triangles.size() ); 15 | std::vector< unsigned int > triangleBuf( numTriangles * 3 ); 16 | std::vector< unsigned int > tristripBuf( meshopt_stripifyBound( triangleBuf.size() ) ); 17 | 18 | quint16 maxVertex = 0; 19 | for ( size_t i = 0; i < numTriangles; i++ ) { 20 | const Triangle & t = triangles.at( qsizetype(i) ); 21 | quint16 v0 = t[0]; 22 | quint16 v1 = t[1]; 23 | quint16 v2 = t[2]; 24 | maxVertex = std::max( maxVertex, std::max( v0, std::max( v1, v2 ) ) ); 25 | tristripBuf[i * 3] = v0; 26 | tristripBuf[i * 3 + 1] = v1; 27 | tristripBuf[i * 3 + 2] = v2; 28 | } 29 | meshopt_optimizeVertexCacheStrip( triangleBuf.data(), tristripBuf.data(), triangleBuf.size(), 30 | size_t( maxVertex ) + 1 ); 31 | 32 | size_t indicesCnt = meshopt_stripify( tristripBuf.data(), triangleBuf.data(), triangleBuf.size(), 33 | size_t( maxVertex ) + 1, (unsigned int) stitch - 1U ); 34 | 35 | for ( size_t i = 0; i < indicesCnt; i++ ) { 36 | size_t j = 0; 37 | for ( ; ( i + j ) < indicesCnt; j++ ) { 38 | if ( tristripBuf[i + j] == (unsigned int) -1 ) 39 | break; 40 | } 41 | if ( j > 0 ) { 42 | strips.append( QVector() ); 43 | strips.last().resize( qsizetype( j ) ); 44 | quint16 * stripData = strips.last().data(); 45 | do { 46 | *stripData = quint16( tristripBuf[i] ); 47 | i++; 48 | stripData++; 49 | } while ( --j ); 50 | } 51 | } 52 | 53 | return strips; 54 | } 55 | 56 | QVector triangulate( const QVector & strip ) 57 | { 58 | QVector tris; 59 | quint16 a, b = strip.value( 0 ), c = strip.value( 1 ); 60 | bool flip = false; 61 | 62 | for ( int s = 2; s < strip.count(); s++ ) { 63 | a = b; 64 | b = c; 65 | c = strip.value( s ); 66 | 67 | if ( a != b && b != c && c != a ) { 68 | if ( !flip ) 69 | tris.append( Triangle( a, b, c ) ); 70 | else 71 | tris.append( Triangle( a, c, b ) ); 72 | } 73 | 74 | flip = !flip; 75 | } 76 | 77 | return tris; 78 | } 79 | 80 | QVector triangulate( const QVector< QVector > & strips ) 81 | { 82 | QVector tris; 83 | for ( const QVector& strip : strips ) { 84 | tris += triangulate( strip ); 85 | } 86 | return tris; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /install/win-install/nifskope-mingw-dynamic.nsi: -------------------------------------------------------------------------------- 1 | ; *** REQUIRES MOREINFO PLUGIN *** 2 | ; Download the MoreInfo zip file from http://nsis.sourceforge.net/MoreInfo_plug-in 3 | ; and copy the Plugins\MoreInfo.dll file to your NSIS Plugins folder. 4 | 5 | ; NifSkope Self-Installer for Windows (MinGW non-static build) 6 | ; (NifTools - http://niftools.sourceforge.net) 7 | ; (NSIS - http://nsis.sourceforge.net) 8 | ; 9 | ; Copyright (c) 2005-2012, NIF File Format Library and Tools 10 | ; All rights reserved. 11 | ; 12 | ; Redistribution and use in source and binary forms, with or without 13 | ; modification, are permitted provided that the following conditions are 14 | ; met: 15 | ; 16 | ; * Redistributions of source code must retain the above copyright 17 | ; notice, this list of conditions and the following disclaimer. 18 | ; * Redistributions in binary form must reproduce the above copyright 19 | ; notice, this list of conditions and the following disclaimer in the 20 | ; documentation ; and/or other materials provided with the 21 | ; distribution. 22 | ; * Neither the name of the NIF File Format Library and Tools project 23 | ; nor the names of its contributors may be used to endorse or promote 24 | ; products derived from this software without specific prior written 25 | ; permission. 26 | ; 27 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 28 | ; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 29 | ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 | ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 31 | ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 | ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 | ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | SetCompressor /SOLID lzma 40 | 41 | !define INSTALLERPOSTFIX "windows" 42 | 43 | !macro InstallHook 44 | ; pack dll files 45 | SetOutPath $INSTDIR 46 | File ${DLL_RELEASE_FOLDER}\libgcc_s_dw2-1.dll 47 | File ${DLL_RELEASE_FOLDER}\mingwm10.dll 48 | File ${DLL_RELEASE_FOLDER}\QtCore4.dll 49 | File ${DLL_RELEASE_FOLDER}\QtGui4.dll 50 | File ${DLL_RELEASE_FOLDER}\QtNetwork4.dll 51 | File ${DLL_RELEASE_FOLDER}\QtOpenGL4.dll 52 | File ${DLL_RELEASE_FOLDER}\QtXml4.dll 53 | !macroend 54 | 55 | !include "nifskope.nsh" 56 | 57 | -------------------------------------------------------------------------------- /src/gl/glparticles.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef GLPARTICLES_H 34 | #define GLPARTICLES_H 35 | 36 | #include "glnode.h" // Inherited 37 | 38 | #include 39 | #include 40 | 41 | 42 | //! @file glparticles.h Particles 43 | 44 | class Particles : public Node 45 | { 46 | friend class ParticleController; 47 | 48 | public: 49 | Particles( Scene * s, const QModelIndex & b ) : Node( s, b ) {} 50 | 51 | void clear() override; 52 | void transform() override; 53 | 54 | void transformShapes() override; 55 | 56 | void drawShapes( NodeList * secondPass = nullptr ) override; 57 | 58 | BoundSphere bounds() const override; 59 | 60 | protected: 61 | void setController( const NifModel * nif, const QModelIndex & controller ) override; 62 | void updateImpl( const NifModel * nif, const QModelIndex & index ) override; 63 | 64 | QPersistentModelIndex iData; 65 | bool updateData = false; 66 | 67 | QVector verts; 68 | QVector colors; 69 | QVector sizes; 70 | 71 | int active = 0; 72 | float size = 0; 73 | }; 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/gl/glmesh.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef GLMESH_H 34 | #define GLMESH_H 35 | 36 | #include "gl/glshape.h" // Inherited 37 | 38 | //! @file glmesh.h Mesh 39 | 40 | //! A mesh 41 | class Mesh : public Shape 42 | { 43 | 44 | public: 45 | Mesh( Scene * s, const QModelIndex & b ) : Shape( s, b ) { } 46 | 47 | // Node 48 | 49 | void transformShapes() override; 50 | 51 | void drawShapes( NodeList * secondPass = nullptr ) override; 52 | void drawSelection() const override; 53 | 54 | BoundSphere bounds() const override; 55 | 56 | QString textStats() const override; // TODO (Gavrant): move to Shape 57 | 58 | // end Node 59 | 60 | // Shape 61 | 62 | void drawVerts() const; 63 | QModelIndex vertexAt( int ) const override; 64 | QModelIndex triangleAt( int ) const override; 65 | void updateLodLevel() override; 66 | 67 | protected: 68 | void updateImpl( const NifModel * nif, const QModelIndex & index ) override; 69 | void addBoneWeight( int vertexNum, int boneNum, float weight ); 70 | void updateData( const NifModel * nif ) override; 71 | 72 | void updateData_NiMesh( const NifModel * nif ); 73 | void updateData_NiTriShape( const NifModel * nif ); 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /.github/workflows/qt5release.yml: -------------------------------------------------------------------------------- 1 | name: Build NifSkope Qt 5 release packages 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v2*' 7 | 8 | jobs: 9 | build_windows: 10 | runs-on: windows-latest 11 | name: Build MSYS2 12 | 13 | steps: 14 | - name: 'Checkout' 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | submodules: recursive 19 | 20 | - name: 'Setup MSYS2' 21 | uses: msys2/setup-msys2@v2 22 | with: 23 | msystem: UCRT64 24 | update: true 25 | cache: true 26 | install: 'base-devel mingw-w64-ucrt-x86_64-gcc msys/p7zip mingw-w64-ucrt-x86_64-qt5-base mingw-w64-ucrt-x86_64-qt5-imageformats mingw-w64-ucrt-x86_64-qt5-tools' 27 | 28 | - name: 'Build with qmake' 29 | shell: msys2 {0} 30 | run: | 31 | qmake noavx=1 NifSkope.pro 32 | make -j 8 33 | mv -f release/NifSkope.exe release/NifSkope_noavx.exe 34 | make clean 35 | qmake noavx2=1 NifSkope.pro 36 | make -j 8 37 | mv -f release/NifSkope.exe release/NifSkope_noavx2.exe 38 | make clean 39 | qmake NifSkope.pro 40 | make -j 8 41 | mv -f release NifSkope 42 | 7za a -m0=lzma -mx=9 NifSkope_2_0_$(date +"%Y-%m-%d")-win64qt5_gcc.7z NifSkope 43 | 44 | - name: 'Upload Artifacts' 45 | uses: actions/upload-artifact@v4 46 | with: 47 | name: build-win 48 | path: | 49 | NifSkope*.7z 50 | 51 | 52 | build_clang64: 53 | runs-on: windows-latest 54 | name: Build MSYS2-CLANG64 55 | 56 | steps: 57 | - name: 'Checkout' 58 | uses: actions/checkout@v4 59 | with: 60 | fetch-depth: 0 61 | submodules: recursive 62 | 63 | - name: 'Setup MSYS2' 64 | uses: msys2/setup-msys2@v2 65 | with: 66 | msystem: CLANG64 67 | update: true 68 | cache: true 69 | install: 'base-devel mingw-w64-clang-x86_64-gcc msys/p7zip mingw-w64-clang-x86_64-qt5-base mingw-w64-clang-x86_64-qt5-imageformats mingw-w64-clang-x86_64-qt5-tools' 70 | 71 | - name: 'Build with qmake' 72 | shell: msys2 {0} 73 | run: | 74 | qmake noavx=1 NifSkope.pro 75 | make -j 8 76 | mv -f release/NifSkope.exe release/NifSkope_noavx.exe 77 | make clean 78 | qmake noavx2=1 NifSkope.pro 79 | make -j 8 80 | mv -f release/NifSkope.exe release/NifSkope_noavx2.exe 81 | make clean 82 | qmake NifSkope.pro 83 | make -j 8 84 | mv -f release NifSkope 85 | 7za a -m0=lzma -mx=9 NifSkope_2_0_$(date +"%Y-%m-%d")-win64qt5_clang.7z NifSkope 86 | 87 | - name: 'Upload Artifacts' 88 | uses: actions/upload-artifact@v4 89 | with: 90 | name: build-clang64 91 | path: | 92 | NifSkope*.7z 93 | -------------------------------------------------------------------------------- /src/ui/widgets/inspect.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef INSPECT_H 34 | #define INSPECT_H 35 | 36 | #include // Inherited 37 | #include 38 | 39 | 40 | //! \file inspect.h InspectView class 41 | 42 | class NifModel; 43 | class QModelIndex; 44 | class InspectViewInternal; 45 | class Scene; 46 | 47 | //! The transform inspection window 48 | class InspectView final : public QDialog 49 | { 50 | Q_OBJECT 51 | 52 | public: 53 | explicit InspectView( QWidget * parent = 0, Qt::WindowFlags f = Qt::Widget ); 54 | ~InspectView(); 55 | 56 | QSize minimumSizeHint() const override final { return { 50, 50 }; } 57 | QSize sizeHint() const override final { return { 400, 400 }; } 58 | 59 | void setNifModel( NifModel * ); 60 | void setScene( Scene * ); 61 | 62 | void clear(); 63 | 64 | void setVisible( bool visible ) override final; 65 | 66 | public slots: 67 | void updateSelection( const QModelIndex & ); 68 | void refresh(); 69 | void updateTime( float t, float mn, float mx ); 70 | void update(); 71 | void copyTransformToMimedata(); 72 | 73 | private: 74 | InspectViewInternal * impl; 75 | NifModel * nif; 76 | Scene * scene; 77 | QPersistentModelIndex selection; 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | ### Invisible Starfield meshes, or missing textures on models from other games 2 | 3 | This issue is most often caused by incorrect resource settings. Make sure that the game is enabled (Options/Settings.../Resources/Games), and that data paths are set up for it on the Paths tab. Any number of archives and/or folders can be added as paths, and folders are loaded recursively, so the simplest configuration consists of just the data path of the game (e.g. K:/SteamLibrary/steamapps/common/Starfield/Data). If the same resource can be found under multiple paths, then the one listed first has the highest precedence. 4 | 5 | ### Starfield shapes have no mesh paths 6 | 7 | By default, Starfield models are automatically converted to use internal geometry data, which is currently required by most of the mesh editing functionality and spells in NifSkope. This conversion can be disabled in the general settings under NIF, and meshes can be converted to either format (internal or external) with spells. 8 | 9 | ### Empty or black viewport 10 | 11 | This problem is usually related to the OpenGL driver or settings. On systems with more than one GPU, make sure that NifSkope is using the correct one, setting it for the application on the control panel of the driver if necessary. In some cases, an empty viewport can also be caused by using a higher MSAA setting than the maximum supported by the hardware or driver. 12 | 13 | ### Errors launching NifSkope on Windows 7 or 8 14 | 15 | Only the builds using Qt 5 run on Windows versions older than 10, and the [Universal C Runtime](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) should be installed. 16 | 17 | ### Very long load times 18 | 19 | Initializing the asset database can potentially take a long time if the number of loose resource files is unusually large. On Windows, performance is impacted much more by the number of resource folders than the number of files, so the problem is most often caused by having all Starfield geometry data (over 350,000 folders, each containing one .mesh file) added as loose resources. In this case, if the geometries are under the main game data path, it is recommended to add archives manually under Options/Settings.../Resources/Paths, and additional data folders only when they are really needed, instead of the simple configuration that recursively loads all data. Note that the 'Add Archive or File' button allows selecting multiple files at once, and that it is allowed to add sub-folders like K:/SteamLibrary/steamapps/common/Starfield/Data/geometries/MyMod as data paths. 20 | 21 | Using too high quality settings for image based lighting can also result in long processing times when the environment map is first loaded. 22 | 23 | ### Rendering issues on Linux 24 | 25 | Running NifSkope under Wayland on Linux may require setting the QT\_QPA\_PLATFORM environment variable to "xcb": 26 | 27 | QT_QPA_PLATFORM=xcb ./NifSkope 28 | 29 | -------------------------------------------------------------------------------- /lib/miniball/example.C: -------------------------------------------------------------------------------- 1 | // Synopsis: Example program illustrating how to use the Seb library 2 | // 3 | // Authors: Martin Kutz , 4 | // Kaspar Fischer 5 | 6 | #include 7 | #include 8 | 9 | #include "Seb.h" 10 | #include "Seb_debug.h" 11 | #include "Seb_debug.C" // ... only needed because we use Seb::Timer below 12 | 13 | int main(int argn,char **argv) { 14 | typedef double FT; 15 | typedef Seb::Point Point; 16 | typedef std::vector PointVector; 17 | typedef Seb::Smallest_enclosing_ball Miniball; 18 | 19 | using std::cout; 20 | using std::endl; 21 | using std::vector; 22 | 23 | cout << "====================================================" << endl 24 | << "Seb example" << endl; 25 | 26 | // Check for right number of arguments ... 27 | if (argn < 3) { 28 | cout << "Usage: " << argv[0] << " number-of-points dimension [boundary]" << endl 29 | << "If 'boundary' is given, all points will be on the boundary of a sphere." << endl 30 | << "====================================================" << endl; 31 | return 1; 32 | } 33 | cout << "====================================================" << endl; 34 | // ... and parse command line arguments 35 | const int n = std::atoi(argv[1]), d = std::atoi(argv[2]); 36 | const bool on_boundary = argn > 3 && std::string(argv[3]) == "boundary"; 37 | 38 | // Construct n random points in dimension d 39 | PointVector S; 40 | vector coords(d); 41 | srand(clock()); 42 | for (int i=0; i(2.0*rand()/RAND_MAX - 1.0); 48 | len += coords[j]*coords[j]; 49 | } 50 | 51 | // Normalize length to "almost" 1 (makes it harder for the algorithm) 52 | if (on_boundary) { 53 | const double Wiggle = 1e-2; 54 | len = 1/(std::sqrt(len)+Wiggle*rand()/RAND_MAX); 55 | for (int j=0; j 0 ) { 103 | // 0: always, 1: <, 2: ==, 3: <=, 4: >, 5: !=, 6: >=, 7: never 104 | int m = ( color.a < alphaThreshold ? 0x2B2B : ( color.a > alphaThreshold ? 0x7171 : 0x4D4D ) ); 105 | if ( ( m & ( 1 << alphaFlags ) ) == 0 ) 106 | discard; 107 | } 108 | if ( alphaFlags < 8 ) 109 | color.a = 1.0; 110 | 111 | fragColor = vec4( color.rgb * ( glowMult * sqrt(brightnessScale) ), color.a ); 112 | } 113 | -------------------------------------------------------------------------------- /src/ui/widgets/groupbox.cpp: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #include "groupbox.h" 34 | 35 | 36 | GroupBox::GroupBox( Qt::Orientation o ) : QGroupBox() 37 | { 38 | lay.push( new QBoxLayout( o2d( o ), this ) ); 39 | } 40 | 41 | GroupBox::GroupBox( const QString & title, Qt::Orientation o ) : QGroupBox( title ) 42 | { 43 | lay.push( new QBoxLayout( o2d( o ), this ) ); 44 | } 45 | 46 | GroupBox::~GroupBox() 47 | { 48 | } 49 | 50 | void GroupBox::addWidget( QWidget * widget, int stretch, Qt::Alignment alignment ) 51 | { 52 | lay.top()->addWidget( widget, stretch, alignment ); 53 | } 54 | 55 | QWidget * GroupBox::pushLayout( const QString & name, Qt::Orientation o, int stretch, Qt::Alignment alignment ) 56 | { 57 | QGroupBox * grp = new QGroupBox( name ); 58 | lay.top()->addWidget( grp, stretch, alignment ); 59 | QBoxLayout * l = new QBoxLayout( o2d( o ) ); 60 | grp->setLayout( l ); 61 | lay.push( l ); 62 | return grp; 63 | } 64 | 65 | void GroupBox::pushLayout( Qt::Orientation o, int stretch ) 66 | { 67 | QBoxLayout * l = new QBoxLayout( o2d( o ) ); 68 | lay.top()->addLayout( l, stretch ); 69 | lay.push( l ); 70 | } 71 | 72 | void GroupBox::popLayout() 73 | { 74 | if ( lay.count() > 1 ) 75 | lay.pop(); 76 | } 77 | 78 | QBoxLayout::Direction GroupBox::o2d( Qt::Orientation o ) 79 | { 80 | switch ( o ) { 81 | case Qt::Vertical: 82 | return QBoxLayout::TopToBottom; 83 | case Qt::Horizontal: 84 | default: 85 | return QBoxLayout::LeftToRight; 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /res/shaders/uvedit.frag: -------------------------------------------------------------------------------- 1 | #version 410 core 2 | 3 | uniform sampler2D BaseMap; 4 | 5 | // 0 = no color conversion 6 | // 1 = sRGB texture 7 | // 2 = unsigned BC5 normal map 8 | // 3 = signed BC5 normal map 9 | // +4 = disable alpha channel 10 | uniform int textureColorMode; 11 | 12 | uniform vec2 uvCenter; 13 | uniform vec4 uvScaleAndOffset; 14 | uniform float uvRotation; 15 | 16 | uniform vec2 pixelScale; 17 | 18 | uniform vec4 gridColors[3]; 19 | uniform vec3 gridLineWidths; 20 | uniform bool gridEnabled[3]; 21 | 22 | uniform vec4 backgroundColor; 23 | uniform vec2 textureColorScale; 24 | 25 | in vec2 texCoord; 26 | 27 | out vec4 fragColor; 28 | 29 | 30 | vec4 srgbCompress( vec4 c ) 31 | { 32 | vec3 tmp = max( c.rgb, vec3( 0.0 ) ) + 0.000858025; 33 | vec3 tmp1 = tmp; 34 | vec3 tmp2 = tmp * tmp; 35 | tmp = inversesqrt( tmp ) * tmp1; 36 | tmp1 = tmp1 * 0.59302883 + 1.42598062; 37 | tmp2 = tmp2 * -0.18732371 - 0.04110602; 38 | tmp = ( tmp * -0.79095451 + tmp1 ) * tmp + tmp2; 39 | return vec4( tmp, c.a ); 40 | } 41 | 42 | vec3 drawGridLines( vec3 color, float x, float s ) 43 | { 44 | vec3 f = vec3( x ) * vec3( 4.0, 16.0, 64.0 ); 45 | f = abs( f - round( f ) ) * vec3( 0.25, 0.0625, 0.015625 ) * s; 46 | f = max( f - ( gridLineWidths * 0.5 - 0.5 ), vec3( 0.0 ) ); 47 | if ( gridEnabled[0] && f.x < 1.0 ) 48 | return mix( color, gridColors[0].rgb, ( cos( f.x * 3.14159265 ) * 0.5 + 0.5 ) * gridColors[0].a ); 49 | if ( gridEnabled[1] && f.y < 1.0 ) 50 | return mix( color, gridColors[1].rgb, ( cos( f.y * 3.14159265 ) * 0.5 + 0.5 ) * gridColors[1].a ); 51 | if ( gridEnabled[2] && f.z < 1.0 ) 52 | return mix( color, gridColors[2].rgb, ( cos( f.z * 3.14159265 ) * 0.5 + 0.5 ) * gridColors[2].a ); 53 | return color; 54 | } 55 | 56 | void main() 57 | { 58 | vec4 color = vec4( 0.0 ); 59 | 60 | if ( texCoord.s >= -1.0 && texCoord.s <= 2.0 && texCoord.t >= -1.0 && texCoord.t <= 2.0 ) { 61 | vec2 offs = texCoord.st - uvCenter; 62 | float r_c = cos( uvRotation ); 63 | float r_s = sin( uvRotation ) * -1.0; 64 | offs = vec2( offs.x * r_c - offs.y * r_s, offs.x * r_s + offs.y * r_c ) * uvScaleAndOffset.xy; 65 | offs = offs + uvCenter + uvScaleAndOffset.zw; 66 | 67 | color = texture( BaseMap, offs ); 68 | 69 | if ( ( textureColorMode & 2 ) != 0 ) { 70 | // BC5 normal map 71 | if ( ( textureColorMode & 1 ) == 0 ) { 72 | // UNORM 73 | color = color * 2.0 - 1.0; 74 | } 75 | color.b = sqrt( max( 1.0 - dot( color.rg, color.rg ), 0.0 ) ); 76 | color = color * 0.5 + 0.5; 77 | } else if ( ( textureColorMode & 1 ) != 0 ) { 78 | // convert to sRGB 79 | color = srgbCompress( color ); 80 | } 81 | 82 | if ( ( textureColorMode & 4 ) != 0 ) 83 | color.a = 1.0; 84 | 85 | if ( texCoord.s >= 0.0 && texCoord.s <= 1.0 && texCoord.t >= 0.0 && texCoord.t <= 1.0 ) 86 | color.rgb *= textureColorScale.x; 87 | else 88 | color.rgb *= textureColorScale.y; 89 | } 90 | 91 | color = vec4( mix( backgroundColor.rgb, color.rgb, color.a ), 1.0 ); 92 | 93 | color.rgb = drawGridLines( drawGridLines( color.rgb, texCoord.s, pixelScale.x ), texCoord.t, pixelScale.y ); 94 | 95 | fragColor = color; 96 | } 97 | -------------------------------------------------------------------------------- /src/bsamodel.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef BSAMODEL_H 34 | #define BSAMODEL_H 35 | 36 | #include "libfo76utils/src/ba2file.hpp" 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | class BSAModel : public QStandardItemModel 43 | { 44 | Q_OBJECT 45 | 46 | public: 47 | BSAModel( QObject * parent = nullptr ); 48 | 49 | void init(); 50 | 51 | Qt::ItemFlags flags( const QModelIndex & index ) const override; 52 | bool fillModel( const BA2File * bsa, const QString & folder ); 53 | protected: 54 | struct FileScanFuncData { 55 | BSAModel * p; 56 | const BA2File * bsa; 57 | std::string path; 58 | QHash< QString, QStandardItem * > folderMap; 59 | }; 60 | static bool fileListScanFunction( void * p, const BA2File::FileInfo & fd ); 61 | QStandardItem * insertFolder( const QString & path, qsizetype pos1, qsizetype pos2, QHash< QString, QStandardItem * > & folderMap ); 62 | }; 63 | 64 | 65 | class BSAProxyModel : public QSortFilterProxyModel 66 | { 67 | Q_OBJECT 68 | 69 | public: 70 | BSAProxyModel( QObject * parent = nullptr ); 71 | 72 | void setFiletypes( QStringList types ); 73 | 74 | void resetFilter(); 75 | 76 | public slots: 77 | void setFilterByNameOnly( bool nameOnly ); 78 | 79 | protected: 80 | bool filterAcceptsRow( int sourceRow, const QModelIndex & sourceParent ) const; 81 | bool lessThan( const QModelIndex & left, const QModelIndex & right ) const; 82 | 83 | private: 84 | QStringList filetypes; 85 | bool filterByNameOnly = false; 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /lib/miniball/Seb_debug.h: -------------------------------------------------------------------------------- 1 | // Synopsis: A simple class to save debugging comments to files 2 | // 3 | // Authors: Martin Kutz , 4 | // Kaspar Fischer 5 | 6 | #ifndef SEB_DEBUG_H 7 | #define SEB_DEBUG_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SEB_NAMESPACE { 16 | 17 | class Logger 18 | // A singleton class which sends debugging comments to log files. 19 | // (A class is called a "singleton" if at most one instance of it 20 | // may ever exist.) By calling void log(channel,msg) you can send 21 | // the string msg to the file with name channel. 22 | { 23 | private: // (Construction and destruction are private to prevent 24 | // more than one instantiation.) 25 | 26 | Logger(); 27 | Logger(const Logger&); 28 | Logger& operator=(const Logger&); 29 | ~Logger(); 30 | 31 | public: // access and routines: 32 | 33 | static Logger& instance(); 34 | // Returns a reference to the only existing instance of this class: 35 | 36 | void log(const char *channel,const std::string& msg); 37 | // If this is the first call to log with string channel as the 38 | // first parameter, then the file with name channel.log is 39 | // opened (at the beginning) for writing and msg is written to 40 | // it. Otherwise, the string msg is opened to the already open 41 | // file channel.log. 42 | 43 | private: // private members: 44 | typedef std::map Streams; 45 | Streams channels; // a collection of pairs (k,v) where 46 | // k is the file-name and v is the 47 | // (open) stream associated with k 48 | }; 49 | 50 | class Timer 51 | // A singleton class which maintains a collection of named timers. 52 | // (A class is called a "singleton" if at most one instance of it 53 | // may ever exist.) The following routines are provided: 54 | // 55 | // - start(name): If this is the first time start() has been 56 | // called with name as the first parameter, then a new timer is 57 | // created and started. Otherwise, the timer with name name is 58 | // restarted. 59 | // 60 | // - lapse(name): Retuns the number of seconds which have elapsed 61 | // since start(name) was called last. 62 | // Precondition: start(name) has been called once. 63 | { 64 | private: // (Construction and destruction are private to prevent 65 | // more than one instantiation.) 66 | 67 | Timer(); 68 | Timer(const Timer&); 69 | Timer& operator=(const Timer&); 70 | 71 | public: // access and routines: 72 | 73 | static Timer& instance(); 74 | // Returns a reference to the only existing instance of this class: 75 | 76 | void start(const char *name); 77 | float lapse(const char *name); 78 | 79 | private: // private members: 80 | typedef std::map Timers; 81 | Timers timers; // a collection of pairs (k,v) where 82 | // k is the timer name and v is the 83 | // (started) timer associated with k 84 | }; 85 | 86 | } // namespace SEB_NAMESPACE 87 | 88 | #endif // SEB_DEBUG_H 89 | -------------------------------------------------------------------------------- /src/gl/renderer.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef GLSHADER_H 34 | #define GLSHADER_H 35 | 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | 46 | #include "glcontext.hpp" 47 | #include "material.hpp" 48 | 49 | //! @file renderer.h Renderer, Renderer::ConditionSingle, Renderer::ConditionGroup, Renderer::Shader, Renderer::Program 50 | 51 | class NifModel; 52 | class Scene; 53 | class Shape; 54 | 55 | typedef unsigned int GLenum; 56 | typedef unsigned int GLuint; 57 | 58 | //! Manages rendering and shaders 59 | class Renderer : public QObject, public NifSkopeOpenGLContext 60 | { 61 | Q_OBJECT 62 | 63 | public: 64 | Renderer( QOpenGLContext * c ); 65 | ~Renderer(); 66 | 67 | //! Set up shader program 68 | Program * setupProgram( Shape *, Program * hint = nullptr ); 69 | 70 | public slots: 71 | void updateSettings(); 72 | 73 | protected: 74 | // Starfield 75 | bool setupProgramCE2( const NifModel *, Program *, Shape * ); 76 | // Skyrim, Fallout 4, Fallout 76 77 | bool setupProgramCE1( const NifModel *, Program *, Shape * ); 78 | // Oblivion, Fallout 3/New Vegas 79 | bool setupProgramFO3( const NifModel *, Program *, Shape * ); 80 | // other games 81 | void setupFixedFunction( Shape * ); 82 | 83 | struct Settings 84 | { 85 | std::uint8_t meshCacheSize = 16; // in units of 8 MiB 86 | QString cubeMapPathFO76; 87 | QString cubeMapPathSTF; 88 | } cfg; 89 | 90 | public: 91 | bool drawSkyBox( Scene * scene ); 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/ui/widgets/floatedit.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef FLOATEDIT_H 34 | #define FLOATEDIT_H 35 | 36 | #include // Inherited 37 | #include // Inherited 38 | 39 | 40 | class FloatValidator final : public QDoubleValidator 41 | { 42 | Q_OBJECT 43 | 44 | public: 45 | FloatValidator( QObject * parent = nullptr ) 46 | : QDoubleValidator( parent ) 47 | {} 48 | FloatValidator( double bottom, double top, int decimals, QObject * parent = nullptr ) 49 | : QDoubleValidator( bottom, top, decimals, parent ) 50 | {} 51 | 52 | QValidator::State validate( QString & input, int & pos ) const override final; 53 | 54 | bool canMin() const; 55 | bool canMax() const; 56 | }; 57 | 58 | class FloatEdit final : public QLineEdit 59 | { 60 | Q_OBJECT 61 | 62 | public: 63 | FloatEdit( QWidget * = nullptr ); 64 | 65 | float value() const; 66 | 67 | void setRange( float minimum, float maximum ); 68 | 69 | bool isMin() const; 70 | bool isMax() const; 71 | 72 | protected: 73 | void contextMenuEvent( class QContextMenuEvent * event ) override final; 74 | 75 | signals: 76 | void sigEdited( float ); 77 | void sigEdited( const QString & ); 78 | void valueChanged( float ); 79 | void valueChanged( const QString & ); 80 | 81 | public slots: 82 | void setValue( float val ); 83 | void set( float val, float n, float x ); 84 | void setMin(); 85 | void setMax(); 86 | 87 | protected slots: 88 | void edited(); 89 | 90 | protected: 91 | float val; 92 | FloatValidator * validator; 93 | class QAction * actMin; 94 | class QAction * actMax; 95 | }; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/ui/settingspane.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSPANE_H 2 | #define SETTINGSPANE_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "gamemanager.h" 10 | 11 | //! @file settingspane.h SettingsPane, SettingsGeneral, SettingsRender, SettingsResources 12 | 13 | class SettingsDialog; 14 | class QStringListModel; 15 | class QListWidget; 16 | 17 | namespace Ui { 18 | class SettingsGeneral; 19 | class SettingsRender; 20 | class SettingsResources; 21 | } 22 | 23 | class SettingsPane : public QWidget 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | explicit SettingsPane( QWidget * parent = nullptr ); 29 | virtual ~SettingsPane(); 30 | 31 | virtual void read() = 0; 32 | virtual void write() = 0; 33 | virtual void setDefault() = 0; 34 | 35 | public slots: 36 | virtual void modifyPane(); 37 | 38 | signals: 39 | void paneModified(); 40 | 41 | protected: 42 | void readPane( QWidget * w, QSettings & settings ); 43 | void writePane( QWidget * w, QSettings & settings ); 44 | bool isModified(); 45 | void setModified( bool ); 46 | 47 | SettingsDialog * dlg; 48 | 49 | bool modified = false; 50 | }; 51 | 52 | class SettingsGeneral : public SettingsPane 53 | { 54 | Q_OBJECT 55 | 56 | public: 57 | explicit SettingsGeneral( QWidget * parent = nullptr ); 58 | ~SettingsGeneral(); 59 | 60 | void read() override final; 61 | void write() override final; 62 | void setDefault() override final; 63 | 64 | private: 65 | std::unique_ptr ui; 66 | }; 67 | 68 | class SettingsRender : public SettingsPane 69 | { 70 | Q_OBJECT 71 | 72 | public: 73 | explicit SettingsRender( QWidget * parent = nullptr ); 74 | ~SettingsRender(); 75 | 76 | void read() override final; 77 | void write() override final; 78 | void setDefault() override final; 79 | 80 | public slots: 81 | void clearCubeCache(); 82 | void selectF76CubeMap(); 83 | void selectSTFCubeMap(); 84 | void detectMSAAMaxSamples(); 85 | 86 | private: 87 | std::unique_ptr ui; 88 | }; 89 | 90 | class SettingsResources : public SettingsPane 91 | { 92 | Q_OBJECT 93 | 94 | public: 95 | explicit SettingsResources( QWidget * parent = nullptr ); 96 | ~SettingsResources(); 97 | 98 | void read() override final; 99 | void write() override final; 100 | void setDefault() override final; 101 | 102 | void select_first(QListWidget* list); 103 | void manager_sync(bool make_connections = false); 104 | 105 | public slots: 106 | void modifyPane() override; 107 | void on_btnFolderAdd_clicked(); 108 | void on_btnArchiveAdd_clicked(); 109 | void on_btnFolderRemove_clicked(); 110 | void on_btnFolderDown_clicked(); 111 | void on_btnFolderUp_clicked(); 112 | void on_btnFolderAutoDetect_clicked(); 113 | void on_btnSubfoldersAdd_clicked(); 114 | void on_btnRemoveInvalidPaths_clicked(); 115 | 116 | void setFolderList(); 117 | 118 | void onBrowseClicked(); 119 | 120 | private: 121 | std::unique_ptr ui; 122 | 123 | // returns Game::OTHER if nothing is selected 124 | Game::GameMode currentFolderItem(); 125 | 126 | QStringListModel * folders; 127 | 128 | QStringList applicableFolders{ "materials", "textures", "geometries" }; 129 | }; 130 | 131 | 132 | #endif // SETTINGSPANE_H 133 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | NIFSKOPE LICENSE 2 | 3 | Copyright (c) 2005-2014, NIF File Format Library and Tools. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 3. The name of the NIF File Format Library and Tools project may not be 15 | used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 30 | CREDITS 31 | 32 | The Windows build of NifSkope uses Havok(R) for the generation of MOPP code. 33 | Copyright (c) 1999-2014 Havok.com Inc. (and its Licensors). 34 | All Rights Reserved. See www.havok.com for details. 35 | 36 | NifSkope uses Qhull for the generation of convex hulls, from http://www.qhull.org. 37 | Copyright (c) 1993-2012 C.B. Barber and The Geometry Center. 38 | See Qhull_COPYING.txt for details and http://gitorious.org/qhull/ for the source. 39 | 40 | NifSkope uses [OpenGL Image (GLI)](http://gli.g-truc.net/): 41 | MIT License, Copyright (c) 2010 - 2016 G-Truc Creation. 42 | 43 | For bounding sphere calculation, NifSkope uses [Miniball](https://github.com/hbf/miniball) 44 | by Kaspar Fischer, Bernd Gärtner and Martin Kutz, the code is available under the 45 | [Apache 2 License](http://www.apache.org/licenses/LICENSE-2.0.html). 46 | 47 | Starfield meshlet and LOD generation are based on code from [meshoptimizer](https://github.com/zeux/meshoptimizer) 48 | (MIT License, Copyright (c) 2016-2025 Arseny Kapoulkine) and [DirectXMesh](https://github.com/microsoft/DirectXMesh) 49 | (MIT License, Copyright (c) by Microsoft Corporation). 50 | 51 | [Tiny glTF](https://github.com/syoyo/tinygltf) is copyright (c) 2015-present by 52 | Syoyo Fujita, Aurélien Chatelain and many contributors under the MIT License. 53 | 54 | [JSON for Modern C++](https://github.com/nlohmann/json) library is copyright (c) 55 | 2013-2025 by Niels Lohmann, MIT License. 56 | 57 | [xxHash](https://github.com/Cyan4973/xxHash) is copyright (c) 2012-2023 by 58 | Yann Collet, BSD 2-Clause License. 59 | 60 | NOTICE 61 | 62 | Parts of NifSkope (i.e. included libraries) might be subject to 63 | other licenses. This license only applies to original NifSkope 64 | sources. 65 | -------------------------------------------------------------------------------- /src/ui/widgets/filebrowser.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef FILEBROWSER_H_INCLUDED 34 | #define FILEBROWSER_H_INCLUDED 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include "gamemanager.h" 48 | 49 | class DDSTextureInfo; 50 | 51 | class FileBrowserWidget : public QDialog 52 | { 53 | Q_OBJECT 54 | 55 | protected: 56 | QGridLayout * layout; 57 | QTreeWidget * treeWidget; 58 | QLineEdit * filter; 59 | const std::set< std::string_view > & fileSet; 60 | const std::string_view * currentFile; 61 | qsizetype selectedFileIndex = -1; 62 | std::vector< const std::string_view * > filesShown; 63 | DDSTextureInfo * textureInfo = nullptr; 64 | Game::GameManager::GameResources * gameResources; 65 | QTreeWidgetItem * findDirectory( std::map< std::string_view, QTreeWidgetItem * > & dirMap, const std::string_view & d ); 66 | void updateTreeWidget(); 67 | void findItemsSelected( std::set< std::string_view > & filesSelected, const QTreeWidgetItem * i ); 68 | 69 | public: 70 | // texture preview is enabled if 'archives' is not nullptr 71 | FileBrowserWidget( int w, int h, const char * titleString, 72 | const std::set< std::string_view > & files, const std::string_view & fileSelected, 73 | Game::GameManager::GameResources * archives = nullptr, bool archiveExtractorMode = false ); 74 | virtual ~FileBrowserWidget(); 75 | const std::string_view * getItemSelected() const; 76 | 77 | public slots: 78 | virtual void checkItemActivated( QTreeWidgetItem *, int ); 79 | virtual void showTextureInfo(); 80 | virtual void extractItemSelected(); 81 | }; 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/gl/icontrollable.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef ICONTROLLABLE_H 34 | #define ICONTROLLABLE_H 35 | 36 | #include // Inherited 37 | #include 38 | #include 39 | #include 40 | 41 | 42 | //! @file icontrollable.h IControllable interface 43 | 44 | class Controller; 45 | class Scene; 46 | class NifModel; 47 | 48 | //! Anything capable of having a Controller 49 | class IControllable : public QObject 50 | { 51 | Q_OBJECT 52 | 53 | friend class ControllerManager; 54 | 55 | public: 56 | IControllable( Scene * Scene, const QModelIndex & index ); 57 | virtual ~IControllable(); 58 | 59 | QModelIndex index() const { return iBlock; } 60 | virtual bool isValid() const { return iBlock.isValid(); } 61 | 62 | virtual void clear(); 63 | 64 | void update( const NifModel * nif, const QModelIndex & index ); 65 | 66 | virtual void transform(); 67 | 68 | virtual void timeBounds( float & start, float & stop ); 69 | 70 | void setSequence( const QString & seqname ); 71 | Controller * findController( const QString & ctrltype, const QString & var1, const QString & var2 ); 72 | 73 | Controller * findController( const QModelIndex & index ); 74 | 75 | inline const QString & getName() const { return name; } 76 | 77 | protected: 78 | //! Sets the Controller 79 | virtual void setController( const NifModel * nif, const QModelIndex & iController ); 80 | 81 | //! Actual implementation of update, with the validation check taken care of by update(...) 82 | virtual void updateImpl( const NifModel * nif, const QModelIndex & index ); 83 | 84 | Scene * scene; 85 | 86 | QPersistentModelIndex iBlock; 87 | 88 | QList controllers; 89 | 90 | void registerController( const NifModel* nif, Controller *ctrl ); 91 | 92 | QString name; 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /install/win-install/nifskope-fedora-mingw-dynamic.nsi: -------------------------------------------------------------------------------- 1 | ; *** REQUIRES MOREINFO PLUGIN *** 2 | ; Download the MoreInfo zip file from http://nsis.sourceforge.net/MoreInfo_plug-in 3 | ; and copy the Plugins\MoreInfo.dll file to your NSIS Plugins folder. 4 | 5 | ; NifSkope Self-Installer for Windows (MinGW non-static build) 6 | ; (NifTools - http://niftools.sourceforge.net) 7 | ; (NSIS - http://nsis.sourceforge.net) 8 | ; 9 | ; Copyright (c) 2005-2012, NIF File Format Library and Tools 10 | ; All rights reserved. 11 | ; 12 | ; Redistribution and use in source and binary forms, with or without 13 | ; modification, are permitted provided that the following conditions are 14 | ; met: 15 | ; 16 | ; * Redistributions of source code must retain the above copyright 17 | ; notice, this list of conditions and the following disclaimer. 18 | ; * Redistributions in binary form must reproduce the above copyright 19 | ; notice, this list of conditions and the following disclaimer in the 20 | ; documentation ; and/or other materials provided with the 21 | ; distribution. 22 | ; * Neither the name of the NIF File Format Library and Tools project 23 | ; nor the names of its contributors may be used to endorse or promote 24 | ; products derived from this software without specific prior written 25 | ; permission. 26 | ; 27 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 28 | ; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 29 | ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 | ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 31 | ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 | ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 | ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | SetCompressor /SOLID lzma 40 | 41 | !define INSTALLERPOSTFIX "windows" 42 | 43 | !macro InstallHook 44 | ; pack dll files 45 | SetOutPath $INSTDIR 46 | File ${DLL_RELEASE_FOLDER}\libgcc_s_sjlj-1.dll 47 | File ${DLL_RELEASE_FOLDER}\libjpeg-62.dll 48 | File ${DLL_RELEASE_FOLDER}\libpng15-15.dll 49 | File ${DLL_RELEASE_FOLDER}\libstdc++-6.dll 50 | File ${DLL_RELEASE_FOLDER}\libtiff-3.dll 51 | File ${DLL_RELEASE_FOLDER}\zlib1.dll 52 | File ${DLL_RELEASE_FOLDER}\QtCore4.dll 53 | File ${DLL_RELEASE_FOLDER}\QtGui4.dll 54 | File ${DLL_RELEASE_FOLDER}\QtNetwork4.dll 55 | File ${DLL_RELEASE_FOLDER}\QtOpenGL4.dll 56 | File ${DLL_RELEASE_FOLDER}\QtSvg4.dll 57 | File ${DLL_RELEASE_FOLDER}\QtXml4.dll 58 | SetOutPath $INSTDIR\imageformats 59 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qgif4.dll 60 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qico4.dll 61 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qjpeg4.dll 62 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qmng4.dll 63 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qsvg4.dll 64 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qtga4.dll 65 | File ${DLL_RELEASE_FOLDER}\..\lib\qt4\plugins\imageformats\qtiff4.dll 66 | 67 | !macroend 68 | 69 | !include "nifskope.nsh" 70 | 71 | -------------------------------------------------------------------------------- /lib/libfo76utils/src/zlib.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ZLIB_HPP_INCLUDED 3 | #define ZLIB_HPP_INCLUDED 4 | 5 | #include "common.hpp" 6 | 7 | class ZLibDecompressor 8 | { 9 | protected: 10 | const unsigned char *inPtr; 11 | const unsigned char *inBufEnd; 12 | unsigned int tableBuf[1312]; // 320 * 3 + 32 + 32 + 288 13 | // huffTable[N] (0 <= N <= 255): 14 | // fast decode table for code lengths <= 8, contains length | (C << 8), 15 | // where C is the decoded symbol, or N bit reversed if length > 8 16 | // huffTable[len + 255] (1 <= len <= 16): 17 | // limit table, len bits of input is valid if less than the table element 18 | // huffTable[len + 287] (1 <= len <= 16): 19 | // table of signed offset to be added to the input for symbol table offset 20 | // huffTable[C + 320] (0 <= C <= 31, or 287 for literals): 21 | // table of decoded symbols 22 | inline unsigned int *getHuffTable(size_t n) 23 | { 24 | // n = 0: code lengths 25 | // n = 1: distances 26 | // n = 2: literals / lengths 27 | return (tableBuf + (n * (256 + 64 + 32))); 28 | } 29 | inline unsigned char readU8() 30 | { 31 | if (inPtr >= inBufEnd) 32 | errorMessage("end of ZLib compressed data"); 33 | unsigned char c = *(inPtr++); 34 | return c; 35 | } 36 | inline unsigned short readU16LE() 37 | { 38 | if ((inPtr + 1) >= inBufEnd) 39 | errorMessage("end of ZLib compressed data"); 40 | unsigned short w = *(inPtr++); 41 | w = w | ((unsigned short) *(inPtr++) << 8); 42 | return w; 43 | } 44 | std::uint32_t readU32LE(); 45 | std::uint64_t readU64LE(); 46 | std::uint16_t readU16BE(); 47 | std::uint32_t readU32BE(); 48 | inline void srLoad(unsigned long long& sr); 49 | inline void srReset(unsigned long long& sr); 50 | // read bits packed in Deflate order (LSB first - LSB first) 51 | // nBits must be in the range 1 to 16 52 | inline unsigned int readBitsRR(unsigned long long& sr, unsigned char nBits, 53 | unsigned int prefix = 0U); 54 | size_t decompressLZ4(unsigned char *buf, size_t uncompressedSize); 55 | unsigned long long huffmanInit(unsigned long long sr, bool useFixedEncoding); 56 | // lenTbl[c] = length of symbol 'c' (0: not used) 57 | static void huffmanBuildDecodeTable( 58 | unsigned int *huffTable, const unsigned char *lenTbl, size_t lenTblSize); 59 | inline unsigned int huffmanDecode(unsigned long long& sr, 60 | const unsigned int *huffTable); 61 | unsigned char *decompressZLibBlock(unsigned long long& srRef, 62 | unsigned char *wp, 63 | unsigned char *buf, unsigned char *bufEnd); 64 | size_t decompressZLib(unsigned char *buf, size_t uncompressedSize); 65 | static unsigned int calculateAdler32(const unsigned char *buf, size_t bufSize, 66 | unsigned int a); 67 | ZLibDecompressor(const unsigned char *inBuf, size_t compressedSize) 68 | : inPtr(inBuf), 69 | inBufEnd(inBuf + compressedSize) 70 | { 71 | } 72 | public: 73 | static size_t decompressData(unsigned char *buf, size_t uncompressedSize, 74 | const unsigned char *inBuf, 75 | size_t compressedSize); 76 | // decompress headerless LZ4 block data 77 | static size_t decompressLZ4Raw(unsigned char *buf, size_t uncompressedSize, 78 | const unsigned char *inBuf, 79 | size_t compressedSize); 80 | }; 81 | 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /README_GLTF.md: -------------------------------------------------------------------------------- 1 | # NifSkope glTF 2.0 Import and Export v1.2 2 | 3 | glTF 2.0 export and import are currently supported on static and skinned Skyrim (import is limited to Special Edition), Fallout 4, Fallout 76 and Starfield meshes. Collision data, controllers and particle systems cannot be exported or imported, and there are a number of other limitations described below. 4 | 5 | # glTF Import 6 | 7 | ## Skinned meshes 8 | 9 | Skin partitions (used by Skyrim) are currently not supported, the mesh is always imported as BSTriShape for games before Starfield. Weights and bone transforms are imported for all games. 10 | 11 | For Starfield only, setting the "Flat" custom boolean property on a skeleton node disables importing that node and all of its children. This is useful when the model needs to use an external skeleton file, with the bone nodes referenced by name in a SkinAttach block instead of being imported to the NIF. 12 | 13 | ## Materials 14 | 15 | Material import is limited to setting material paths, using the name of the material, or the "Material Path" extra data if available. Shader property data and texture sets need to be created manually, or copied from an existing model. 16 | 17 | # glTF Export 18 | 19 | To view and export Starfield meshes, you must first: 20 | 21 | 1. Enable and add the path to your Starfield installation in Settings > Resources. 22 | 2. Add the Meshes archives or extracted folders containing `geometries` to Paths in Settings > Resources, under Starfield. 23 | 24 | If no item is selected, then the entire scene is exported. Otherwise, either a node or a shape must be selected, and only that item and its children are exported. 25 | 26 | ## Skinned meshes 27 | 28 | ### Pre-Export 29 | 30 | If you do not desire the full posable skeleton, you may skip these steps. 31 | 32 | If you do not paste in the COM skeleton, a flat skeleton will be reconstructed for you. 33 | **Please note:** You will receive a warning after export that the skeleton has been reconstructed for you. This is fine. 34 | 35 | If you desire the full posable skeleton, and the mesh does not have a skeleton with a `COM` or `COM_Twin` NiNode in its NIF: 36 | 37 | 1. Open the skeleton.nif for that skinned mesh (e.g. `meshes\actors\human\characterassets\skeleton.nif`) 38 | 2. Copy (Ctrl-C) the `COM` NiNode in skeleton.nif 39 | 3. Paste (Ctrl-V) the entire `COM` branch onto the mesh NIF's root NiNode (0) 40 | 4. Export to glTF 41 | 42 | ### Pre-Blender Import 43 | 44 | As of Exporter v1.1 you should **no longer need to uncheck "Guess Original Bind Pose"**. 45 | 46 | ## Materials 47 | 48 | glTF export includes a limited set of material settings, and textures from the first layer of the material, which are saved in the output .bin file in PNG format. Replacement colors are stored as 1x1 textures. Texture quality can be configured in the general settings with the 'Export texture mip level' option. A mip level of -1 disables texture export. 49 | 50 | For Skyrim, only the diffuse and normal maps are exported. PBR support is limited for Fallout 4, while in the case of Fallout 76 materials, albedo, roughness, metalness and occlusion maps are generated from the texture set. 51 | 52 | ## LOD 53 | 54 | Exporting and importing LOD meshes is implemented only for Starfield. It is disabled by default, and can be enabled in the general settings. When enabled, LOD meshes use the MSFT\_lod glTF extension. 55 | 56 | ## Blender scripts 57 | 58 | Blender scripts are provided for use with glTF exports. They may be opened and run from the Scripting tab inside Blender. 59 | 60 | 1. `gltf_lod_blender_script.py` is included in the `scripts` folder for managing LOD visibility in exported glTF. 61 | -------------------------------------------------------------------------------- /src/ui/widgets/refrbrowser.cpp: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #include "refrbrowser.h" 34 | 35 | #include "model/nifmodel.h" 36 | 37 | #include 38 | #include 39 | 40 | 41 | ReferenceBrowser::ReferenceBrowser( QWidget * parent ) 42 | : QTextBrowser( parent ) 43 | { 44 | nif = nullptr; 45 | docFolder.setPath( qApp->applicationDirPath() ); 46 | docFolderPresent = docFolder.exists( "doc" ); 47 | 48 | #ifdef Q_OS_LINUX 49 | 50 | if ( !docFolderPresent ) { 51 | docFolder.cd( "/usr/share/nifskope" ); 52 | docFolderPresent = docFolder.exists( "doc" ); 53 | } 54 | 55 | #endif 56 | 57 | if ( docFolderPresent ) { 58 | docFolder.cd( "doc" ); 59 | } 60 | 61 | if ( !docFolderPresent || !QFileInfo( docFolder.filePath( "index.html" ) ).exists() ) { 62 | setText( tr( "Please install the reference documentation into the 'doc' folder." ) ); 63 | return; 64 | } 65 | 66 | setSearchPaths( { docFolder.absolutePath() } ); 67 | setStyleSheet( "docsys.css" ); 68 | setSourceFile( "index.html" ); 69 | } 70 | 71 | void ReferenceBrowser::setNifModel( NifModel * nifModel ) 72 | { 73 | nif = nifModel; 74 | } 75 | 76 | // TODO: Read documentation from ZIP files 77 | 78 | void ReferenceBrowser::setSourceFile( const QString & source ) 79 | { 80 | if ( QFileInfo( docFolder.filePath( source ) ).exists() ) { 81 | setSource( QUrl( source ) ); 82 | } 83 | } 84 | 85 | void ReferenceBrowser::browse( const QModelIndex & index ) 86 | { 87 | if ( !nif || !docFolderPresent ) { 88 | return; 89 | } 90 | 91 | QString blockType = nif->itemStrType( index ); 92 | 93 | if ( blockType == "NiBlock" ) { 94 | blockType = nif->itemName( index ); 95 | } 96 | 97 | if ( !QFileInfo( docFolder.filePath( "%1.html" ).arg( blockType ) ).exists() ) { 98 | setText( tr( "The reference file for '%1' could not be found." ).arg( blockType ) ); 99 | return; 100 | } 101 | 102 | setSourceFile( QString( "%1.html" ).arg( blockType ) ); 103 | } 104 | -------------------------------------------------------------------------------- /src/gl/glmarker.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef GLMARKER_H_INCLUDED 34 | #define GLMARKER_H_INCLUDED 35 | 36 | class Scene; 37 | 38 | struct GLMarker 39 | { 40 | int nv; 41 | int nf; 42 | const float * verts; 43 | const unsigned short * faces; 44 | 45 | void drawMarker( Scene * scene, bool solid = false ) const; 46 | 47 | static const float FurnitureMarker01Verts[288]; 48 | static const unsigned short FurnitureMarker01Faces[198]; 49 | static const GLMarker FurnitureMarker01; 50 | 51 | static const float FurnitureMarker03Verts[228]; 52 | static const unsigned short FurnitureMarker03Faces[168]; 53 | static const GLMarker FurnitureMarker03; 54 | 55 | static const float FurnitureMarker04Verts[228]; 56 | static const unsigned short FurnitureMarker04Faces[168]; 57 | static const GLMarker FurnitureMarker04; 58 | 59 | static const float FurnitureMarker11Verts[324]; 60 | static const unsigned short FurnitureMarker11Faces[228]; 61 | static const GLMarker FurnitureMarker11; 62 | 63 | static const float FurnitureMarker13Verts[324]; 64 | static const unsigned short FurnitureMarker13Faces[228]; 65 | static const GLMarker FurnitureMarker13; 66 | 67 | static const float FurnitureMarker14Verts[324]; 68 | static const unsigned short FurnitureMarker14Faces[228]; 69 | static const GLMarker FurnitureMarker14; 70 | 71 | static const float BedLeftVerts[288]; 72 | static const unsigned short BedLeftFaces[198]; 73 | static const GLMarker BedLeft; 74 | 75 | static const float ChairLeftVerts[324]; 76 | static const unsigned short ChairLeftFaces[228]; 77 | static const GLMarker ChairLeft; 78 | 79 | static const float ChairFrontVerts[324]; 80 | static const unsigned short ChairFrontFaces[228]; 81 | static const GLMarker ChairFront; 82 | 83 | static const float ChairBehindVerts[324]; 84 | static const unsigned short ChairBehindFaces[228]; 85 | static const GLMarker ChairBehind; 86 | 87 | static const float BumperMarker01Verts[288]; 88 | static const unsigned short BumperMarker01Faces[432]; 89 | static const GLMarker BumperMarker01; 90 | }; 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /src/model/nifproxymodel.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2015, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef NIFPROXYMODEL_H 34 | #define NIFPROXYMODEL_H 35 | 36 | #include // Inherited 37 | #include 38 | #include 39 | #include 40 | 41 | 42 | //! @file nifproxymodel.h NifProxyModel 43 | 44 | class NifModel; 45 | class NifProxyItem; 46 | 47 | class NifProxyModel final : public QAbstractItemModel 48 | { 49 | Q_OBJECT 50 | 51 | public: 52 | NifProxyModel( QObject * parent = 0 ); 53 | ~NifProxyModel(); 54 | 55 | void setModel( QAbstractItemModel * model ); 56 | QAbstractItemModel * model() const; 57 | 58 | QModelIndex index( int row, int col, const QModelIndex & parent ) const override final; 59 | QModelIndex parent( const QModelIndex & index ) const override final; 60 | 61 | Qt::ItemFlags flags( const QModelIndex & index ) const override final; 62 | 63 | int columnCount( const QModelIndex & index ) const override final { Q_UNUSED( index ); return 2; } 64 | int rowCount( const QModelIndex & index ) const override final; 65 | 66 | bool hasChildren( const QModelIndex & index ) const override final 67 | { return rowCount( index ) > 0; } 68 | 69 | QVariant data( const QModelIndex & index, int role ) const override final; 70 | bool setData( const QModelIndex & index, const QVariant & v, int role ) override final; 71 | 72 | QVariant headerData( int section, Qt::Orientation o, int role ) const override final; 73 | 74 | QModelIndex mapTo( const QModelIndex & index ) const; 75 | QModelIndex mapFrom( const QModelIndex & index, const QModelIndex & ref ) const; 76 | 77 | public slots: 78 | void reset(); 79 | 80 | protected slots: 81 | void xDataChanged( const QModelIndex &, const QModelIndex & ); 82 | void xHeaderDataChanged( Qt::Orientation, int, int ); 83 | void xRowsAboutToBeRemoved( const QModelIndex &, int, int ); 84 | 85 | void xLinksChanged(); 86 | 87 | protected: 88 | QList mapFrom( const QModelIndex & index ) const; 89 | 90 | void updateRoot( bool fast ); 91 | void updateItem( NifProxyItem * item, bool fast ); 92 | 93 | NifModel * nif; 94 | 95 | NifProxyItem * root; 96 | }; 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /src/model/undocommands.h: -------------------------------------------------------------------------------- 1 | /***** BEGIN LICENSE BLOCK ***** 2 | 3 | BSD License 4 | 5 | Copyright (c) 2005-2017, NIF File Format Library and Tools 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. The name of the NIF File Format Library and Tools project may not be 17 | used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ***** END LICENCE BLOCK *****/ 32 | 33 | #ifndef UNDOCOMMANDS_H 34 | #define UNDOCOMMANDS_H 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | //! @file undocommands.h ChangeValueCommand, ToggleCheckBoxListCommand 42 | 43 | class NifModel; 44 | class NifValue; 45 | 46 | class ChangeValueCommand : public QUndoCommand 47 | { 48 | public: 49 | ChangeValueCommand( const QModelIndex & index, const QVariant & value, 50 | const QString & valueString, const QString & valueType, NifModel * model ); 51 | ChangeValueCommand( const QModelIndex & index, const NifValue & oldValue, 52 | const NifValue & newValue, const QString & valueType, NifModel * model ); 53 | void redo() override; 54 | void undo() override; 55 | 56 | //! The command ID 57 | int id() const override; 58 | 59 | //! Handle merging of commands in the same transaction 60 | bool mergeWith( const QUndoCommand * command ) override; 61 | 62 | //! Increments the lastID 63 | static void createTransaction(); 64 | 65 | private: 66 | NifModel * nif; 67 | QVector newValues, oldValues; 68 | QVector idxs; 69 | 70 | //! The command ID for this undo command 71 | size_t localID; 72 | 73 | //! The current command ID for any new undo commands 74 | static size_t lastID; 75 | }; 76 | 77 | 78 | class ToggleCheckBoxListCommand : public QUndoCommand 79 | { 80 | public: 81 | ToggleCheckBoxListCommand( const QModelIndex & index, const QVariant & value, const QString & valueType, NifModel * model ); 82 | void redo() override; 83 | void undo() override; 84 | private: 85 | NifModel * nif; 86 | QVariant newValue, oldValue; 87 | QPersistentModelIndex idx; 88 | }; 89 | 90 | 91 | class ArrayUpdateCommand : public QUndoCommand 92 | { 93 | public: 94 | ArrayUpdateCommand( const QModelIndex & index, NifModel * model ); 95 | void redo() override; 96 | void undo() override; 97 | private: 98 | NifModel * nif; 99 | uint newSize, oldSize; 100 | QPersistentModelIndex idx; 101 | }; 102 | 103 | #endif // UNDOCOMMANDS_H 104 | --------------------------------------------------------------------------------