From 6de82ca18cbc756e912abd3187c961a5f7caae5c Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Fri, 27 Aug 2021 21:15:57 +0200 Subject: [PATCH] Menu-FN: if a menu.dat is compiled with MODEL_PREVIEW defined, we'll use a 3D player-model previews instead of the image based one --- src/menu-fn/includes.src | 1 + src/menu-fn/m_customize.qc | 121 ++++++++++++++++++++++++++++- src/menu-fn/w_3dview.qc | 151 +++++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 src/menu-fn/w_3dview.qc diff --git a/src/menu-fn/includes.src b/src/menu-fn/includes.src index f9fbeee1..22c930c0 100644 --- a/src/menu-fn/includes.src +++ b/src/menu-fn/includes.src @@ -15,6 +15,7 @@ modserver.qc tcp.qc widgets.qc +w_3dview.qc w_checkbox.qc w_colorlist.qc w_dialog.qc diff --git a/src/menu-fn/m_customize.qc b/src/menu-fn/m_customize.qc index 77842f97..66c51498 100644 --- a/src/menu-fn/m_customize.qc +++ b/src/menu-fn/m_customize.qc @@ -19,10 +19,16 @@ CMainButton cz_btnDone; CMainButton cz_btnAdvanced; CTextBox cz_tbNetname; CPictureSwitch cz_psSpray; -CPictureSwitch cz_psModel; CSlider cz_sldTopcolor; CSlider cz_sldBottomcolor; +#ifdef MODEL_PREVIEW +CUI3DView cz_3dModel; +var int g_iModel; +#else +CPictureSwitch cz_psModel; +#endif + vector g_vecTopcolor; vector g_vecBottomcolor; @@ -65,7 +71,11 @@ cz_btnadvanced_start(void) void cz_cbModelChanged(void) { +#ifdef MODEL_PREVIEW + string mdl = g_models[g_iModel]; +#else string mdl = cz_psModel.GetPic(); +#endif tokenizebyseparator(mdl, "/"); localcmd(sprintf("seta _cl_playermodel %s\n", argv(2))); localcmd(sprintf("setinfo model %s\n", argv(2))); @@ -243,6 +253,98 @@ menu_customize_init(void) } if (games[gameinfo_current].nomodels == 0) { +#ifdef MODEL_PREVIEW + static entity eModel; + static vector vecDistance = [ 45, 0, 0 ]; + static void ModelPreview_SetModel( string strModel ) { + setmodel( eModel, strModel ); + eModel.colormap = 0; + AngleVectors( cz_3dModel.Get3DAngles() ); + cz_3dModel.Set3DPos( v_forward * -vecDistance[0] + v_right * vecDistance[1] + v_up * vecDistance[2] ); + } + static void ModelPreview_Draw ( void ) { + static int initialized = FALSE; + if ( !initialized ) { + initialized = TRUE; + eModel = spawn(); + eModel.angles[1] -= 180; + ModelPreview_SetModel(sprintf("models/player/%s/%s.mdl", cvar_string("_cl_playermodel"), cvar_string("_cl_playermodel"))); + } + addentity( eModel ); + eModel.frame1time += frametime; + } + static void ModelPreview_Input ( float type, float x, float y, float flDevID ) { + if (type == IE_KEYUP && x == K_MOUSE1 && Util_CheckMouse(414, 340, 64, 24) == TRUE) { + g_iModel--; + if (g_iModel < 0) + g_iModel = g_modelcount - 1; + + cz_cbModelChanged(); + ModelPreview_SetModel(sprintf("%s.mdl", g_models[g_iModel])); + } + if (type == IE_KEYUP && x == K_MOUSE1 && Util_CheckMouse(510, 340, 64, 24) == TRUE) { + g_iModel++; + if (g_iModel >= g_modelcount) + g_iModel = 0; + + cz_cbModelChanged(); + ModelPreview_SetModel(sprintf("%s.mdl", g_models[g_iModel])); + } + /*static int iMouseDrag = FALSE; + static int iShiftDrag = FALSE; + static vector vecDragOfs; + vector vecDifference; + + int iMouseOver = Util_MouseAbove( getmousepos(), cz_3dModel.m_parent.GetPos() + cz_3dModel.GetPos(), cz_3dModel.GetSize() ); + if ( flEVType == IE_KEYDOWN ) { + if ( flKey == K_MOUSE1 && iMouseOver == TRUE ) { + iMouseDrag = TRUE; + vecDragOfs = getmousepos(); + } else if ( flKey == K_MWHEELUP && iMouseOver == TRUE ) { + vecDistance[0] = bound( 0, --vecDistance[0], 512 ); + AngleVectors( cz_3dModel.Get3DAngles() ); + cz_3dModel.Set3DPos( v_forward * -vecDistance[0] + v_right * vecDistance[1] + v_up * vecDistance[2] ); + } else if ( flKey == K_MWHEELDOWN && iMouseOver == TRUE ) { + vecDistance[0] = bound( 0, ++vecDistance[0], 512 ); + AngleVectors( cz_3dModel.Get3DAngles() ); + cz_3dModel.Set3DPos( v_forward * -vecDistance[0] + v_right * vecDistance[1] + v_up * vecDistance[2] ); + } else if ( flKey == K_LSHIFT && iMouseOver == TRUE ) { + iShiftDrag = TRUE; + } + } else if ( flEVType == IE_KEYUP ) { + if ( flKey == K_MOUSE1 ) { + iMouseDrag = FALSE; + } else if ( flKey == K_LSHIFT ) { + iShiftDrag = FALSE; + } + } + + if ( iMouseDrag == TRUE && iShiftDrag == FALSE ) { + if ( flEVType == IE_MOUSEABS ) { + vecDifference = [ flChar, flKey ] - [ vecDragOfs[1], vecDragOfs[0] ]; + cz_3dModel.Set3DAngles( cz_3dModel.Get3DAngles() + vecDifference ); + AngleVectors( cz_3dModel.Get3DAngles() ); + cz_3dModel.Set3DPos( v_forward * -vecDistance[0] + v_right * vecDistance[1] + v_up * vecDistance[2] ); + vecDragOfs = getmousepos(); + } + } else if ( iMouseDrag == TRUE && iShiftDrag == TRUE ) { + if ( flEVType == IE_MOUSEABS ) { + vecDifference = [ flChar, flKey ] - [ vecDragOfs[1], vecDragOfs[0] ]; + vecDistance[1] -= vecDifference[1]; + vecDistance[2] += vecDifference[0]; + cz_3dModel.Set3DPos( v_forward * -vecDistance[0] + v_right * vecDistance[1] + v_up * vecDistance[2] ); + vecDragOfs = getmousepos(); + } + }*/ + } + + cz_3dModel = spawn(CUI3DView); + cz_3dModel.SetPos(410,160); + cz_3dModel.SetSize(170,221); + cz_3dModel.SetDrawFunc(ModelPreview_Draw); + cz_3dModel.SetInputFunc(ModelPreview_Input); + Widget_Add(fn_customize, cz_3dModel); +#else cz_psModel = spawn(CPictureSwitch); cz_psModel.SetPos(410,160); cz_psModel.SetSize(170,221); @@ -252,7 +354,8 @@ menu_customize_init(void) cz_psModel.SetCallback(cz_cbModelChanged); cz_psModel.SetValueS(sprintf("models/player/%s/%s", cvar_string("_cl_playermodel"), cvar_string("_cl_playermodel"))); Widget_Add(fn_customize, cz_psModel); - +#endif + cz_sldTopcolor = spawn(CSlider); cz_sldTopcolor.SetPos(420,400); cz_sldTopcolor.SetValue(cvar("_cl_topcolor")); @@ -281,14 +384,26 @@ menu_customize_draw(void) if (games[gameinfo_current].nomodels == 0) { WLabel_Static(410, 140, sprintf(m_reslbl[IDS_MODEL_NAME], cvar_string("_cl_playermodel")), 14, 14, [1,1,1], 1.0f, 0, font_arial); - +#ifdef MODEL_PREVIEW + drawfill([g_menuofs[0] + 414,g_menuofs[1] + 370], [64,12], g_vecTopcolor, 0.75f); + drawfill([g_menuofs[0] + 510,g_menuofs[1] + 370], [64,12], g_vecBottomcolor, 0.75f); +#else drawfill([g_menuofs[0] + 414,g_menuofs[1] + 346], [64,12], g_vecTopcolor, 0.75f); drawfill([g_menuofs[0] + 510,g_menuofs[1] + 346], [64,12], g_vecBottomcolor, 0.75f); +#endif } if (games[gameinfo_current].nosprays == 0) WLabel_Static(212, 203, m_reslbl[IDS_PROFILE_LOGO], 14, 14, [1,1,1], 1.0f, 0, font_arial); + +#ifdef MODEL_PREVIEW + /* fake buttons */ + WLabel_Static(414, 340, "Previous", 14, 14, [1,1,1], + 1.0f, 0, font_arial); + WLabel_StaticR(575, 340, "Next", 14, 14, [1,1,1], + 1.0f, 0, font_arial); +#endif } void diff --git a/src/menu-fn/w_3dview.qc b/src/menu-fn/w_3dview.qc new file mode 100644 index 00000000..79b30231 --- /dev/null +++ b/src/menu-fn/w_3dview.qc @@ -0,0 +1,151 @@ + +noref .vector angles; +noref .float colormap; +noref .float frame, frame2, lerpfrac, renderflags, frame1time; + +enumflags +{ + VIEW_VISIBLE +}; + +class CUI3DView:CWidget +{ + vector m_vecSize; + vector m_vec3DPos; + vector m_vec3DAngles; + float m_flFOV; + + void(void) CUI3DView; + virtual void(void) m_vDrawFunc = 0; + virtual void(float, float, float, float) m_vInputFunc = 0; + virtual void(void) Draw; + virtual vector() GetSize; + virtual vector() Get3DPos; + virtual vector() Get3DAngles; + virtual void(vector) SetSize; + virtual void(vector) Set3DPos; + virtual void(vector) Set3DAngles; + virtual void(void(void)) SetDrawFunc; + virtual void(void(float, float, float, float)) SetInputFunc; + virtual void(float, float, float, float) Input; +}; + +void +CUI3DView::CUI3DView(void) +{ + m_flFOV = 90; + m_vecSize = [64,64]; + m_vec3DPos = m_vec3DAngles = [0,0,0]; +} + +void +CUI3DView::SetSize(vector vecSize) +{ + m_vecSize = vecSize; +} + +vector +CUI3DView::GetSize(void) +{ + return m_vecSize; +} + +void +CUI3DView::Set3DAngles(vector vecAngles) +{ + m_vec3DAngles = vecAngles; +} + +vector +CUI3DView::Get3DAngles(void) +{ + return m_vec3DAngles; +} + +void +CUI3DView::Set3DPos(vector vecPos) +{ + m_vec3DPos = vecPos; +} + +vector +CUI3DView::Get3DPos(void) +{ + return m_vec3DPos; +} + +void +CUI3DView::SetDrawFunc(void(void) vFunc) +{ + m_vDrawFunc = vFunc; +} + +void +CUI3DView::SetInputFunc(void(float, float, float, float) vFunc) +{ + m_vInputFunc = vFunc; +} + +void +CUI3DView::Draw(void) +{ + if (!m_vDrawFunc) { + return; + } + + clearscene(); + setproperty(VF_VIEWPORT, [m_x + g_menuofs[0],m_y + g_menuofs[1]], m_vecSize); + setproperty(VF_AFOV, 90); + setproperty(VF_ORIGIN, m_vec3DPos); + setproperty(VF_ANGLES, m_vec3DAngles); + + if (m_vDrawFunc) { + m_vDrawFunc(); + renderscene(); + } +} + +void +CUI3DView::Input(float flEVType, float flKey, float flChar, float flDevID) +{ + if (!m_vInputFunc) { + return; + } + + m_vInputFunc(flEVType, flKey, flChar, flDevID); +} + +/* 3D helper functions */ + + +// menuqc doesn't have access to makevectors... screw you, guys +noref vector v_forward; +noref vector v_up; +noref vector v_right; +void AngleVectors ( vector angles ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[1] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[0] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[2] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + v_forward[0] = cp*cy; + v_forward[1] = cp*sy; + v_forward[2] = -sp; + + v_right[0] = (-1*sr*sp*cy+-1*cr*-sy); + v_right[1] = (-1*sr*sp*sy+-1*cr*cy); + v_right[2] = -1*sr*cp; + + v_up[0] = (cr*sp*cy+-sr*-sy); + v_up[1] = (cr*sp*sy+-sr*cy); + v_up[2] = cr*cp; +}