Added modelviewer.

Added neural network code(turned off by default).
Lots of editor and rendering fixes.
This commit is contained in:
Justin Marshall
2026-05-17 22:09:25 -07:00
parent 079442e7ba
commit 76f642286e
74 changed files with 101444 additions and 2227 deletions
File diff suppressed because it is too large Load Diff
+222
View File
@@ -0,0 +1,222 @@
/*
===========================================================================
IceTech GPL Source Code
Copyright (C) 2026 Justin Marshall
This file is part of the IceTech GPL Source Code.
===========================================================================
*/
#ifndef __MODELVIEWDOCK_H__
#define __MODELVIEWDOCK_H__
class idDeclModelDef;
class idDeclModelDefInterface;
class idRenderModel;
class idAnim;
class idMD5Anim;
class idJointMat;
// These IDs live in the same private range used by the XY/Game dock controls.
#define ID_MODELVIEW_DECLCOMBO 0x7A60
#define ID_MODELVIEW_REFRESH 0x7A61
#define ID_MODELVIEW_SHOWSKELETON 0x7A62
#define ID_MODELVIEW_MESHTREE 0x7A63
#define ID_MODELVIEW_ANIMLIST 0x7A64
#define ID_MODELVIEW_RENDER 0x7A65
#define ID_MODELVIEW_MENUBAR 0x7A66
#define ID_MODELVIEW_FILE_NEWMD5DECL 0x7A67
#define ID_MODELVIEW_FILE_ADDANIM 0x7A68
#define ID_MODELVIEW_PLAY 0x7A69
#define ID_MODELVIEW_PAUSE 0x7A6A
#define ID_MODELVIEW_STOP 0x7A6B
#define ID_MODELVIEW_TIMELINE 0x7A6C
#define ID_MODELVIEW_TIMETEXT 0x7A6D
#define ID_MODELVIEW_TRANSPORT 0x7A6E
#define ID_MODELVIEW_REIMPORT 0x7A6F
#define WM_MODELVIEW_ANIMTIME_CHANGED (WM_APP + 0x260)
//=============================================================================
// CModelRenderWnd
//
// Model preview renderer for the Radiant Model View tab.
// This intentionally does not own or drive the game-side animator object.
// It uses the public gameEdit animation helpers that Radiant/tool code
// already consumes for non-game skeletal rendering.
//=============================================================================
class CModelRenderWnd : public CWnd {
DECLARE_DYNAMIC(CModelRenderWnd)
public:
CModelRenderWnd();
virtual ~CModelRenderWnd();
BOOL Create(CWnd* pParent, UINT nID);
void SetModelDecl(const idDeclModelDef* modelDecl);
void SetAnimation(const idMD5Anim* anim, int animLengthMS, int numFrames, const char* displayName);
void SetAnimationTimeMS(int timeMS);
void PlayAnimation();
void PauseAnimation();
void StopAnimation();
void SetShowSkeleton(BOOL showSkeleton);
void SetActive(BOOL active);
void FocusRenderWindow();
int GetAnimationTimeMS() const;
int GetAnimationLengthMS() const;
int GetAnimationFrames() const;
BOOL HasAnimation() const;
BOOL IsPlaying() const;
private:
HDC m_hDC;
HGLRC m_hGLRC;
const idDeclModelDefInterface* m_modelDecl;
idRenderModel* m_model;
idRenderModel* m_cachedDynamicModel;
idJointMat* m_joints;
int m_numJoints;
BOOL m_haveAnimFrame;
const idMD5Anim* m_anim;
int m_animLengthMS;
int m_animFrames;
int m_animTimeMS;
CString m_animDisplayName;
DWORD m_lastTick;
BOOL m_showSkeleton;
BOOL m_active;
BOOL m_playing;
BOOL m_dragging;
CPoint m_lastMouse;
float m_yaw;
float m_pitch;
float m_distance;
float m_center[3];
float m_radius;
private:
void InitGL();
void ShutdownGL();
void FreeJointBuffer();
void AllocateJointBuffer();
void ResetCachedDynamicModel();
void ResolveModelFromGameEdit();
void UpdateAnimationFrame(BOOL forceResetCachedModel);
void NotifyAnimationTimeChanged();
void FitCameraToModel();
void StepAnimation();
void DrawScene();
void SetupCamera(const CRect& client);
void DrawGrid();
void DrawModel();
void DrawRenderModel(idRenderModel* model, bool wireOnly);
void DrawSkeleton();
void DrawOverlayText();
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
DECLARE_MESSAGE_MAP()
};
//=============================================================================
// CModelViewDockWnd
//=============================================================================
class CModelViewDockWnd : public CWnd {
DECLARE_DYNAMIC(CModelViewDockWnd)
public:
CModelViewDockWnd();
virtual ~CModelViewDockWnd();
BOOL Create(CWnd* pParent, UINT nID);
void LayoutChildren();
void SetActive(BOOL active);
void FocusModelView();
private:
CStatic m_lblModel;
CComboBox m_comboDecls;
CButton m_btnRefresh;
CButton m_btnReimport;
CButton m_chkSkeleton;
CStatic m_lblMesh;
CStatic m_lblAnim;
CTreeCtrl m_treeMesh;
CListBox m_listAnims;
CModelRenderWnd m_wndRender;
CStatic m_transportPanel;
CButton m_btnPlay;
CButton m_btnPause;
CButton m_btnStop;
CSliderCtrl m_sliderTimeline;
CStatic m_lblTime;
HWND m_hMenuBar;
const idDeclModelDefInterface* m_modelDecl;
BOOL m_active;
bool m_inLayout;
bool m_updatingTimeline;
int m_timelineLengthMS;
CPtrArray m_animItems;
private:
void ApplyDarkTheme();
void ClearAnimationItems();
void PopulateModelDecls();
void LoadSelectedModelDecl();
CString GetSelectedModelDeclFileName();
void SetModelDecl(const idDeclModelDef* modelDecl);
void PopulateMeshTree();
void PopulateAnimationList();
void SelectAnimationItem(int itemIndex);
void SelectModelDeclByName(const char* declName);
void SelectAnimationByName(const char* animName);
void SetTimelineRange(int animLengthMS);
void UpdateTimelinePosition(int animTimeMS, int animLengthMS);
void UpdateTimeLabel(int animTimeMS, int animLengthMS);
void UpdateTransportControls();
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnDeclChanged();
afx_msg void OnAnimChanged();
afx_msg void OnRefresh();
afx_msg void OnReimportModel();
afx_msg void OnNewMD5Decl();
afx_msg void OnAddAnimationFile();
afx_msg void OnShowSkeleton();
afx_msg void OnPlay();
afx_msg void OnPause();
afx_msg void OnStop();
afx_msg LRESULT OnAnimTimeChanged(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
#endif // __MODELVIEWDOCK_H__
+61 -1
View File
@@ -32,6 +32,7 @@ If you have questions concerning this license or the applicable additional terms
#include "qe3.h"
#include "Radiant.h"
#include "XYWnd.h"
#include "ModelViewDock.h"
#include "ZWnd.h"
#include "DialogInfo.h"
#include "splines.h"
@@ -45,6 +46,7 @@ If you have questions concerning this license or the applicable additional terms
#define ID_XYDOCK_TABS 0x7A00
#define ID_XYDOCK_XYPAGE 0x7A03
#define ID_XYDOCK_GAMEPAGE 0x7A04
#define ID_XYDOCK_MODELVIEWPAGE 0x7A05
#define ID_GAME_HOST 0x7A30
#define ID_GAME_FILL_FIT 0x7A40
@@ -1604,6 +1606,9 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
item.pszText = "Game";
m_wndTabs.InsertItem(XYDOCK_TAB_GAME, &item);
item.pszText = "Model View";
m_wndTabs.InsertItem(XYDOCK_TAB_MODELVIEW, &item);
CString pageClass = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW),
@@ -1628,6 +1633,11 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
}
m_wndGamePage.ShowWindow(SW_HIDE);
if (!m_wndModelPage.Create(&m_wndTabs, ID_XYDOCK_MODELVIEWPAGE)) {
return -1;
}
m_wndModelPage.ShowWindow(SW_HIDE);
if (!m_wndMenuBar.Create(&m_wndXYPage, 0x7A01)) {
return -1;
}
@@ -1766,6 +1776,7 @@ int CXYDockWnd::GetZPercent() const {
void CXYDockWnd::ShowActiveTab() {
const BOOL xyActive = (m_nActiveTab == XYDOCK_TAB_XY);
const BOOL gameActive = (m_nActiveTab == XYDOCK_TAB_GAME);
const BOOL modelActive = (m_nActiveTab == XYDOCK_TAB_MODELVIEW);
if (m_wndXYPage.GetSafeHwnd()) {
m_wndXYPage.ShowWindow(xyActive ? SW_SHOW : SW_HIDE);
@@ -1783,10 +1794,19 @@ void CXYDockWnd::ShowActiveTab() {
}
m_wndGamePage.SetActive(gameActive);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.ShowWindow(modelActive ? SW_SHOW : SW_HIDE);
if (modelActive) {
m_wndModelPage.SetWindowPos(&wndTop, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
m_wndModelPage.SetActive(modelActive);
}
}
void CXYDockWnd::SetActiveTab(int nTab) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME && nTab != XYDOCK_TAB_MODELVIEW) {
nTab = XYDOCK_TAB_XY;
}
@@ -1812,9 +1832,29 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndGamePage.GetSafeHwnd()) {
m_wndGamePage.SetActive(TRUE);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
FocusGameWindow();
}
else if (m_nActiveTab == XYDOCK_TAB_MODELVIEW) {
//
// Model View tab selected:
// - game HWND is deactivated
// - editor/tool input stays active
// - focus moves to the model preview window
//
if (m_wndGamePage.GetSafeHwnd()) {
m_wndGamePage.SetActive(FALSE);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(TRUE);
}
common->ActivateTool(true);
FocusModelView();
}
else {
//
// XY tab selected:
@@ -1825,6 +1865,9 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndGamePage.GetSafeHwnd()) {
m_wndGamePage.SetActive(FALSE);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
common->ActivateTool(true);
FocusXYWindow();
@@ -1849,10 +1892,18 @@ void CXYDockWnd::SelectGameTab() {
SetActiveTab(XYDOCK_TAB_GAME);
}
void CXYDockWnd::SelectModelViewTab() {
SetActiveTab(XYDOCK_TAB_MODELVIEW);
}
BOOL CXYDockWnd::IsGameTabActive() const {
return (m_nActiveTab == XYDOCK_TAB_GAME) ? TRUE : FALSE;
}
BOOL CXYDockWnd::IsModelViewTabActive() const {
return (m_nActiveTab == XYDOCK_TAB_MODELVIEW) ? TRUE : FALSE;
}
void CXYDockWnd::AttachGameWindow(HWND hGameWnd) {
m_wndGamePage.AttachGameWindow(hGameWnd);
m_wndGamePage.SetActive(IsGameTabActive());
@@ -1874,6 +1925,10 @@ void CXYDockWnd::FocusGameWindow() {
m_wndGamePage.FocusGameWindow();
}
void CXYDockWnd::FocusModelView() {
m_wndModelPage.FocusModelView();
}
void CXYDockWnd::FocusXYWindow() {
m_wndMDIContainer.FocusXYWindow();
}
@@ -1916,6 +1971,11 @@ void CXYDockWnd::LayoutChildren() {
m_wndGamePage.LayoutChildren();
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.MoveWindow(pageRect, TRUE);
m_wndModelPage.LayoutChildren();
}
ShowActiveTab();
if (m_pToolBar && m_pToolBar->GetSafeHwnd() && m_wndXYPage.GetSafeHwnd()) {
+7 -3
View File
@@ -41,6 +41,7 @@ If you have questions concerning this license or the applicable additional terms
#include "CamWnd.h"
#include <afxcmn.h>
#include "ModelViewDock.h"
class CXYWnd;
class CZWnd;
@@ -262,21 +263,24 @@ public:
BOOL IsGameWindowDocked() const;
HWND GetDockedGameWindow() const;
BOOL IsGameTabActive() const;
BOOL IsModelViewTabActive() const;
void SelectXYTab();
void SelectGameTab();
void SelectModelViewTab();
void FocusGameWindow();
void FocusXYWindow();
void FocusModelView();
protected:
enum {
XYDOCK_TAB_XY = 0,
XYDOCK_TAB_GAME = 1
XYDOCK_TAB_GAME = 1,
XYDOCK_TAB_MODELVIEW = 2
};
CTabCtrl m_wndTabs;
CWnd m_wndXYPage;
CGameDockWnd m_wndGamePage;
CModelViewDockWnd m_wndModelPage;
CXYMenuBar m_wndMenuBar;
CXYMDIContainerWnd m_wndMDIContainer;
CToolBar *m_pToolBar;