Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
57aa9e6
Add Qt6 3D model viewport with custom OpenGL renderer
james-gre Apr 13, 2026
3f6fa3e
feat: add compile mode and tilefade undo to align with CLI
james-gre Apr 14, 2026
c081741
refactor: migrate from legacy flags to subcommand interface
james-gre Apr 14, 2026
7952b78
fix: handle string severity values from cleanmodels v4
james-gre Apr 16, 2026
f8c50e6
chore: gitignore build/ directory and remove tracked build artifacts
james-gre Apr 16, 2026
1fbb358
chore: remove agentic session artifacts from repo
james-gre Apr 16, 2026
e425af1
chore: remove legacy Prolog state file and resource
james-gre Apr 16, 2026
893c36e
chore: remove legacy qmake .pro file (project uses CMake)
james-gre Apr 16, 2026
36f291b
fix: address 18 review findings across security, architecture, and co…
james-gre Apr 16, 2026
614b035
Update for cleanmodels Go v4 rewrite
james-gre Apr 21, 2026
abfd5c2
ci: remove qtopengl module (included in qtbase for Qt6)
james-gre Apr 21, 2026
7486c00
fix: use QImage::mirrored() instead of non-existent flipped()
james-gre Apr 21, 2026
030474d
ci: bundle Qt libs for self-contained distribution
james-gre Apr 22, 2026
cd8baf8
ci: bundle libxcb-cursor in Linux deploy
james-gre Apr 22, 2026
449e2eb
Switch Linux deploy from zip bundle to AppImage
james-gre Apr 22, 2026
a51c9a4
Fix AppImage rename glob to match actual output filename
james-gre Apr 22, 2026
2a4613e
feat: add Report Issue integration and cleanup
james-gre Apr 22, 2026
0fcfa5a
feat: add standardize-texture0 and strip-ee-extras to GUI
james-gre Apr 25, 2026
f4e5de1
chore: migrate to PRODUCT.md/DESIGN.md and address /impeccable audit
james-gre Apr 26, 2026
c57137c
feat: add Bioware DDS texture loader
plenarius Apr 30, 2026
146bf36
feat(viewer): MDL animation playback + skinmesh rendering fixes
plenarius Apr 30, 2026
d100acb
fix(viewer): post-feature review hardening
plenarius Apr 30, 2026
33b63b7
fix(viewer): close pre-existing parser OOB / OOM gaps
plenarius Apr 30, 2026
a9cadba
build(ci): add linux-arm64 and macos-amd64 to Qt build matrix
plenarius May 2, 2026
23a5f84
build(ci): bundle cleanmodels CLI alongside the GUI in every Qt artifact
plenarius May 2, 2026
eca939d
build(ci): produce a single universal2 macOS bundle instead of two ar…
plenarius May 2, 2026
f715fac
build(ci): fix verification ls inside the CLI download step
plenarius May 2, 2026
4777e23
build(ci): scope artifact globs so linuxdeploy helpers stay out of th…
plenarius May 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
393 changes: 213 additions & 180 deletions .github/workflows/build.yml

Large diffs are not rendered by default.

93 changes: 32 additions & 61 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,72 +1,43 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
name: CodeQL

on:
push:
branches: [ main ]
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
branches: [main]
schedule:
- cron: '20 19 * * 3'
- cron: "20 19 * * 3"

permissions:
security-events: write

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

steps:
- name: Checkout repository
uses: actions/checkout@v2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

- name: Qt Dependencies
run: |
sudo apt-get update
sudo apt-get install qtbase5-dev

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- uses: actions/checkout@v6

- name: Install Qt6
uses: jurplel/install-qt-action@v4
with:
version: "6.7.*"
cache: true

- name: Install OpenGL
run: |
sudo apt-get update
sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: cpp

- name: Configure and build
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --parallel

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ ui_*.h
*.jsc
Makefile*
*build-*
build/
*.qm
*.prl
release
Expand Down
33 changes: 33 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# cleanmodels-qt

Qt6/C++17 desktop GUI for [cleanmodels](https://github.com/plenarius/cleanmodels), a tool to fix and clean NWN:EE MDL model files. Launches the Go CLI as a subprocess and consumes its `--json-lines` output.

## Architecture
- **mainwindow.cpp** — UI construction (programmatic, not Designer-driven), settings, directory management
- **mainwindow_clean.cpp** — QProcess lifecycle, JSON-lines parsing, file table + debug log updates
- **modelviewport.cpp** — QOpenGLWidget subclass for 3D model preview (OpenGL 3.3 Core)
- **renderer.cpp** — Scene graph traversal, shader compilation, mesh/texture upload
- **mdlscene.cpp** — Lightweight ASCII MDL parser (preview-only, not the authoritative parser)
- **gpumesh.cpp / gputexture.cpp** — GPU resource wrappers
- **camera.cpp** — Orbit camera with mouse interaction
- **fsmodel.cpp** — QFileSystemModel wrapper for directory completion

## Design Context

### Users
NWN community modders who build, fix, and maintain 3D model files (.mdl) for Neverwinter Nights: Enhanced Edition. These users range from experienced 3D artists to module builders with limited technical background. They work in a pipeline that includes 3D editors (NWMax/Blender), the game's toolset, and cleanmodels as the quality gate before assets ship.

### Brand Personality
**Fast, precise, flexible.** The tool should feel like a sharp instrument — quick to produce correct results, trustworthy in its output, and accommodating of the wide variety of models found in the NWN community (old, malformed, hand-edited, tool-exported). It never corrupts data and always explains what it changed.

### Aesthetic Direction
- **Qt GUI**: Native OS look — blend in with the platform rather than imposing a custom theme. The interface should feel like a well-made professional utility, not a game launcher or a toy. Polished and intentional, but never flashy.
- **3D Viewport**: Critical to the workflow. Users rely on it to visually verify fixes. It should be clear, responsive, and show geometry accurately. Grid, wireframe, and reference model overlay are first-class features.
- **Anti-references**: Not Blender-dark, not game-fantasy-themed, not web-app-styled. Think: native file manager meets engineering tool.

### Design Principles
1. **Speed is a feature** — The legacy Prolog tool was too slow. Every operation should feel instant on single models, and batch processing should saturate I/O, not CPU. Never block the UI.
2. **Correctness over convenience** — Binary output must match the game's own compiler. Checks should catch real issues, not generate noise. When in doubt, preserve the original data.
3. **Approachable complexity** — The tool has deep options (pivot repair, tilefade slicing, walkmesh material remapping) but non-technical modders should be able to hit "All Fixes" and get a good result. Progressive disclosure: simple defaults, advanced options collapsed.
4. **Explain what changed** — Every fix, warning, and repair should produce a human-readable message. The debug log and per-file fix counts are the user's audit trail.
5. **Stay focused** — NWN MDL files only. No scope creep into other formats, game engines, or unrelated tooling.
54 changes: 31 additions & 23 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
cmake_minimum_required(VERSION 3.10)
project(cleanmodels-qt)
cmake_minimum_required(VERSION 3.16)
project(cleanmodels-qt LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(QT_COMPONENTS Core Widgets Gui)

if(DEFINED ENV{STATIC_BUILD} AND NOT $ENV{STATIC_BUILD} STREQUAL "")
if(DEFINED ENV{QT_STATIC_PATH} AND NOT $ENV{QT_STATIC_PATH} STREQUAL "")
set(CMAKE_PREFIX_PATH "$ENV{QT_STATIC_PATH}/lib/cmake/Qt5")
set(QT_ROOT "$ENV{QT_STATIC_PATH}/lib/cmake/")
include("./CMakeModules/Qt.cmake")
endif()
endif()

find_package(Qt5 COMPONENTS ${QT_COMPONENTS} REQUIRED)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

add_executable(${PROJECT_NAME} main.cpp mainwindow.cpp mainwindow_clean.cpp fsmodel.cpp icons.qrc prolog_files.qrc mainwindow.ui)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui OpenGL OpenGLWidgets)

add_executable(${PROJECT_NAME}
main.cpp
mainwindow.cpp
mainwindow_clean.cpp
fsmodel.cpp
camera.cpp
mdlscene.cpp
mdlanimationplayer.cpp
gpumesh.cpp
gputexture.cpp
renderer.cpp
modelviewport.cpp
constants.h
icons.qrc
mainwindow.ui
)

include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Widgets Qt5::Gui)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt6::Core Qt6::Widgets Qt6::Gui Qt6::OpenGL Qt6::OpenGLWidgets)

if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
endif()
if(WIN32)
set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE)
endif()

if(DEFINED ENV{STATIC_BUILD} AND NOT $ENV{STATIC_BUILD} STREQUAL "")
if(DEFINED ENV{QT_STATIC_PATH} AND NOT $ENV{QT_STATIC_PATH} STREQUAL "")
qt5_import_plugins(${PROJECT_NAME}
EXCLUDE_BY_TYPE imageformats
)
endif()
endif()
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
Loading