Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into meshageddon
Browse files Browse the repository at this point in the history
  • Loading branch information
JMPZ11 committed Jul 22, 2024
2 parents 08bdce2 + ac14e2f commit 6fbd891
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 66 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
== CHANGELOG ==

* Added a new spell (Material/Clone and Copy to Clipboard) that is available in the right click menu on the name of a Starfield BSLightingShaderProperty, and copies the material to the clipboard in JSON (.mat) format, but with randomly generated new resource IDs. This is useful when creating a new material using an existing one as the base. **Note:** if a modified material is saved to a different path, the first BSComponentDB::CTName needs to be updated to reflect the new base name of the .mat file. Additionally, the asset database needs to be cleared in NifSkope (Alt+Q) to ensure that any new materials are loaded and used.
* Starfield NIF files are now automatically converted to internal geometry on load. This is often useful because most geometry editing functionality is not implemented for external .mesh files, but it can be disabled in the general settings under 'NIF'.
* New 'Material' spell menu for BSGeometry, BSTriShape (Fallout 4 and 76), BSLightingShaderProperty and BSEffectShaderProperty blocks, with shortcuts to material spells.
* Bug fixes in drawing the normals or tangents of a selected Starfield shape, the Starfield grid scale, and simplifying skinned meshes.

#### NifSkope-2.0.dev9-20240716

* Implemented Starfield glTF import, fixes and improvements to glTF export.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

NifSkope is a tool for opening and editing the NetImmerse file format (NIF). NIF is used by video games such as Morrowind, Oblivion, Skyrim, Fallout 3/NV/4/76, Starfield, Civilization IV, and more.

This is an experimental fork of 2.0.dev9 with partial support for Starfield materials, and improvements and fixes to Fallout 76 rendering.
This is an experimental fork of 2.0.dev9 with many improvements to Starfield support, and a number of fixes to issues related to older games. See [CHANGELOG.md](https://github.com/fo76utils/nifskope/blob/develop/CHANGELOG.md) for details.

### Meshageddon Edition

Expand Down Expand Up @@ -51,7 +51,7 @@ Anyone can report issues specific to this fork at [GitHub](https://github.com/fo

### Contribute

You can fork the latest source from [GitHub](https://github.com/niftools/nifskope). See [Fork A Repo](https://help.github.com/articles/fork-a-repo) on how to send your contributions upstream. To grab all submodules, make sure to use `--recursive` like so:
You can fork the latest source from [GitHub](https://github.com/fo76utils/nifskope). See [Fork A Repo](https://help.github.com/articles/fork-a-repo) on how to send your contributions upstream. To grab all submodules, make sure to use `--recursive` like so:

```
git clone --recursive git://github.com/<YOUR_USERNAME>/nifskope.git
Expand Down
4 changes: 2 additions & 2 deletions build/README.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

NifSkope is a tool for opening and editing the NetImmerse file format (NIF). NIF is used by video games such as Morrowind, Oblivion, Skyrim, Fallout 3/NV/4/76, Starfield, Civilization IV, and more.

This is an experimental fork of 2.0.dev9 with partial support for Starfield materials, and improvements and fixes to Fallout 76 rendering.
This is an experimental fork of 2.0.dev9 with many improvements to Starfield support, and a number of fixes to issues related to older games. See [CHANGELOG.md](https://github.com/fo76utils/nifskope/blob/develop/CHANGELOG.md) for details.

### Download

Expand Down Expand Up @@ -42,7 +42,7 @@ Anyone can report issues specific to this fork at [GitHub](https://github.com/fo

### Contribute

You can fork the latest source from [GitHub](https://github.com/niftools/nifskope). See [Fork A Repo](https://help.github.com/articles/fork-a-repo) on how to send your contributions upstream. To grab all submodules, make sure to use `--recursive` like so:
You can fork the latest source from [GitHub](https://github.com/fo76utils/nifskope). See [Fork A Repo](https://help.github.com/articles/fork-a-repo) on how to send your contributions upstream. To grab all submodules, make sure to use `--recursive` like so:

```
git clone --recursive git://github.com/<YOUR_USERNAME>/nifskope.git
Expand Down
24 changes: 7 additions & 17 deletions src/glview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,31 +415,21 @@ void GLView::glProjection( int x, int y )
bs |= BoundSphere( scene->view * Vector3(), axis );
}

float bounds = (bs.radius > 1024.0 * scale()) ? bs.radius : 1024.0 * scale();
float bounds = std::max< float >( bs.radius, 1024.0f * scale() );


GLdouble nr = fabs( bs.center[2] ) - bounds * 1.5;
GLdouble fr = fabs( bs.center[2] ) + bounds * 1.5;

if ( perspectiveMode || (view == ViewWalk) ) {
// Perspective View
if ( nr < 1.0 * scale() )
nr = 1.0 * scale();
if ( fr < 2.0 * scale() )
fr = 2.0 * scale();

if ( nr > fr ) {
// add: swap them when needed
GLfloat tmp = nr;
nr = fr;
fr = tmp;
}

if ( (fr - nr) < 0.00001f ) {
// add: ensure distance
nr = 1.0 * scale();
fr = 2.0 * scale();
std::swap( nr, fr );
}
nr = std::max< GLdouble >( nr, scale() );
// ensure distance
fr = std::max< GLdouble >( fr, nr + scale() );

GLdouble h2 = tan( ( cfg.fov / Zoom ) / 360 * M_PI ) * nr;
GLdouble w2 = h2 * aspect;
Expand Down Expand Up @@ -1078,7 +1068,7 @@ void GLView::setCenter()
// Center on entire mesh
BoundSphere bs = scene->bounds();

if ( bs.radius < 1 * scale() )
if ( bs.radius < scale() )
bs.radius = 1024.0 * scale();

setDistance( bs.radius * 1.2 );
Expand Down Expand Up @@ -1924,7 +1914,7 @@ void GLView::mouseReleaseEvent( QMouseEvent * event )
void GLView::wheelEvent( QWheelEvent * event )
{
if ( view == ViewWalk )
mouseMov += Vector3( 0, 0, double( event->angleDelta().y() ) / 8.0 ) * scale();
mouseMov += Vector3( 0, 0, double( event->angleDelta().y() ) / 4.0 ) * scale();
else
{
if (event->angleDelta().y() < 0)
Expand Down
16 changes: 14 additions & 2 deletions src/model/nifmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1813,10 +1813,18 @@ static QString getNIFDataPath( const char * pathName )
return QString();
}

class spMeshFileImport
{
public:
static bool processAllItems( NifModel * nif );
};

bool NifModel::load( QIODevice & device, const char* fileName )
{
QSettings settings;
bool ignoreSize = settings.value( "Ignore Block Size", true ).toBool();
bool convertSFMeshes =
settings.value( "Settings/Nif/Convert Starfield meshes to internal geometry on load", true ).toBool();

clear();

Expand Down Expand Up @@ -2045,6 +2053,10 @@ bool NifModel::load( QIODevice & device, const char* fileName )

//qDebug() << t.msecsTo( QTime::currentTime() );
reset(); // notify model views that a significant change to the data structure has occurded

if ( getBSVersion() >= 170 && convertSFMeshes )
spMeshFileImport::processAllItems( this );

return true;
}

Expand Down Expand Up @@ -2569,8 +2581,8 @@ void NifModel::updateLinks( int block )
for ( int c = 0; c < n; c++ ) {
if ( !hasrefs[c] ) {
const NifItem * b;
if ( bsVersion >= 151 && ( b = getBlockItem( quint32(c) ) ) != nullptr && b->name() == "BSShaderTextureSet" ) {
if ( c > 0 && ( b = getBlockItem( quint32(c - 1) ) ) != nullptr && b->name() == "BSLightingShaderProperty" )
if ( bsVersion >= 151 && ( b = getBlockItem( qint32(c) ) ) != nullptr && b->name() == "BSShaderTextureSet" ) {
if ( c > 0 && ( b = getBlockItem( qint32(c - 1) ) ) != nullptr && b->name() == "BSLightingShaderProperty" )
childLinks[c - 1] += c;
} else {
rootLinks.append( c );
Expand Down
23 changes: 15 additions & 8 deletions src/spells/fileextract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ QModelIndex spExtractAllResources::cast( NifModel * nif, const QModelIndex & ind

std::set< std::string > fileSet;
for ( int b = 0; b < nif->getBlockCount(); b++ ) {
const NifItem * item = nif->getBlockItem( quint32(b) );
const NifItem * item = nif->getBlockItem( qint32(b) );
if ( item )
findPaths( fileSet, nif, item );
}
Expand Down Expand Up @@ -400,7 +400,7 @@ QModelIndex spMeshFileExport::cast( NifModel * nif, const QModelIndex & index )
meshesConverted = processItem( nif, item, outputDirectory );
} else {
for ( int b = 0; b < nif->getBlockCount(); b++ )
meshesConverted |= processItem( nif, nif->getBlockItem( quint32(b) ), outputDirectory );
meshesConverted |= processItem( nif, nif->getBlockItem( qint32(b) ), outputDirectory );
}
if ( meshesConverted )
Game::GameManager::close_resources();
Expand Down Expand Up @@ -432,7 +432,8 @@ class spMeshFileImport final : public Spell
return ( item->name() == "BSGeometry" && ( nif->get<quint32>(item, "Flags") & 0x0200 ) == 0 );
}

bool processItem( NifModel * nif, NifItem * item );
static bool processItem( NifModel * nif, NifItem * item );
static bool processAllItems( NifModel * nif );
QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final;
};

Expand Down Expand Up @@ -486,6 +487,14 @@ bool spMeshFileImport::processItem( NifModel * nif, NifItem * item )
return true;
}

bool spMeshFileImport::processAllItems( NifModel * nif )
{
bool r = false;
for ( int b = 0; b < nif->getBlockCount(); b++ )
r = r | processItem( nif, nif->getBlockItem( qint32(b) ) );
return r;
}

QModelIndex spMeshFileImport::cast( NifModel * nif, const QModelIndex & index )
{
if ( !( nif && nif->getBSVersion() >= 170 ) )
Expand All @@ -495,12 +504,10 @@ QModelIndex spMeshFileImport::cast( NifModel * nif, const QModelIndex & index )
if ( item && !( item->name() == "BSGeometry" && (nif->get<quint32>(item, "Flags") & 0x0200) == 0 ) )
return index;

if ( item ) {
if ( item )
processItem( nif, item );
} else {
for ( int b = 0; b < nif->getBlockCount(); b++ )
processItem( nif, nif->getBlockItem( quint32(b) ) );
}
else
processAllItems( nif );

return index;
}
Expand Down
2 changes: 1 addition & 1 deletion src/spells/filerename.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ QModelIndex spResourceRename::cast ( NifModel * nif, const QModelIndex & index )
QRegularExpression filterPattern( le3->text().trimmed(), QRegularExpression::CaseInsensitiveOption );

for ( int b = 0; b < nif->getBlockCount(); b++ ) {
NifItem * item = nif->getBlockItem( quint32(b) );
NifItem * item = nif->getBlockItem( qint32(b) );
if ( item )
renamePaths( nif, item, searchPattern, replacementString, filterPattern );
}
Expand Down
46 changes: 45 additions & 1 deletion src/spells/headerstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,48 @@ void spEditStringIndex::browseMaterial( QLineEdit * le, const NifModel * nif )

REGISTER_SPELL( spEditStringIndex )

//! Choose a material path
class spBrowseMaterialPath final : public Spell
{
public:
QString name() const override final { return Spell::tr( "Choose" ); }
QString page() const override final { return Spell::tr( "Material" ); }
QIcon icon() const override final
{
return QIcon();
}
bool constant() const override final { return true; }
bool instant() const override final { return true; }

bool isApplicable( const NifModel * nif, const QModelIndex & index ) override final
{
if ( !( nif && nif->getBSVersion() >= 130 && index.isValid() ) )
return false;
if ( nif->getBSVersion() >= 170 )
return nif->blockInherits( index, "BSGeometry" ) || nif->blockInherits( index, "BSLightingShaderProperty" );
return ( nif->blockInherits( index, "BSTriShape" ) || nif->blockInherits( index, "BSLightingShaderProperty" )
|| nif->blockInherits( index, "BSEffectShaderProperty" ) );
}

QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final
{
QModelIndex idx = index;
if ( nif->blockInherits( idx, ( nif->getBSVersion() < 170 ? "BSTriShape" : "BSGeometry" ) ) )
idx = nif->getBlockIndex( nif->getLink( idx, "Shader Property" ) );
if ( nif->blockInherits( idx, "BSShaderProperty" ) )
idx = nif->getIndex( idx, "Name" );
else
return index;
if ( idx.isValid() ) {
spEditStringIndex sp;
(void) sp.cast( nif, idx );
}
return index;
}
};

REGISTER_SPELL( spBrowseMaterialPath )

//! Browse a material path stored as header string
class spBrowseHeaderMaterialPath final : public Spell
{
Expand Down Expand Up @@ -233,7 +275,9 @@ class spBrowseHeaderMaterialPath final : public Spell
if ( !( item && item->valueType() == NifValue::tSizedString ) )
return false;
QString s( item->getValueAsString() );
return ( s.endsWith( ".bgsm", Qt::CaseInsensitive ) || s.endsWith( ".bgem", Qt::CaseInsensitive ) || s.endsWith( ".mat", Qt::CaseInsensitive ) );
if ( nif->getBSVersion() < 170 )
return ( s.endsWith( ".bgsm", Qt::CaseInsensitive ) || s.endsWith( ".bgem", Qt::CaseInsensitive ) );
return ( s.endsWith( ".mat", Qt::CaseInsensitive ) || s == "MATERIAL_PATH" );
}

QModelIndex cast( NifModel * nif, const QModelIndex & index ) override final
Expand Down
2 changes: 1 addition & 1 deletion src/spells/meshfilecopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ QModelIndex spResourceCopy::cast(NifModel* nif, const QModelIndex& index)
QString projectName = sanitizeFileName(le2->text().trimmed().remove(QRegularExpression("^[\\\\/]+|[\\\\/]+$")));

for (int b = 0; b < nif->getBlockCount(); b++) {
NifItem* item = nif->getBlockItem(quint32(b));
NifItem* item = nif->getBlockItem(qint32(b));
if (item)
copyPaths(nif, item, authorPrefix, projectName, nif->getFolder());
}
Expand Down
Loading

0 comments on commit 6fbd891

Please sign in to comment.