mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-25 19:55:54 +01:00
2469 lines
72 KiB
C++
2469 lines
72 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
|
|
|
// SeriousSkaStudioView.cpp : implementation of the CSeriousSkaStudioView class
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "SeriousSkaStudio.h"
|
|
|
|
#include "SeriousSkaStudioDoc.h"
|
|
#include "SeriousSkaStudioView.h"
|
|
|
|
#include <Engine/Templates/Stock_CMesh.h>
|
|
#include <Engine/Templates/Stock_CSkeleton.h>
|
|
#include <Engine/Templates/Stock_CAnimSet.h>
|
|
#include <Engine/Templates/Stock_CTextureData.h>
|
|
#include <Engine/Graphics/GfxLibrary.h>
|
|
|
|
#include "MainFrm.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#undef new
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
BOOL _bSelectedItemChanged = FALSE;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSeriousSkaStudioView
|
|
|
|
IMPLEMENT_DYNCREATE(CSeriousSkaStudioView, CView)
|
|
|
|
BEGIN_MESSAGE_MAP(CSeriousSkaStudioView, CView)
|
|
//{{AFX_MSG_MAP(CSeriousSkaStudioView)
|
|
ON_WM_SIZE()
|
|
ON_WM_DESTROY()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_RBUTTONUP()
|
|
ON_COMMAND(ID_RESET_VIEW, OnResetView)
|
|
ON_COMMAND(ID_SHOW_WIREFRAME, OnShowWireframe)
|
|
ON_COMMAND(ID_SHOW_SKELETON, OnShowSkeleton)
|
|
ON_COMMAND(ID_SHOW_TEXTURE, OnShowTexture)
|
|
ON_COMMAND(ID_ADD_MESHLOD, OnAddMeshlod)
|
|
ON_COMMAND(ID_ADD_ANIMATION, OnAddAnimation)
|
|
ON_COMMAND(ID_ADD_SKELETONLOD, OnAddSkeletonlod)
|
|
ON_COMMAND(ID_DELETESELECTED, OnDeleteselected)
|
|
ON_COMMAND(ID_ADD_ANIMSET, OnAddAnimset)
|
|
ON_COMMAND(ID_ADD_MESHLIST, (AFX_PMSG)OnAddMeshlist)
|
|
ON_COMMAND(ID_ADD_SKELETONLIST, OnAddSkeletonlist)
|
|
ON_COMMAND(ID_ADD_TEXTURE, OnAddTexture)
|
|
ON_COMMAND(ID_ADD_CHILD_MODEL_INSTANCE, OnAddChildModelInstance)
|
|
ON_COMMAND(ID_ADD_COLISIONBOX, OnAddColisionbox)
|
|
ON_COMMAND(ID_ANIM_STOP, OnAnimStop)
|
|
ON_COMMAND(ID_ANIM_SYNC, OnAnimSync)
|
|
ON_COMMAND(ID_AUTO_MIPING, OnAutoMiping)
|
|
ON_UPDATE_COMMAND_UI(ID_AUTO_MIPING, OnUpdateAutoMiping)
|
|
ON_COMMAND(ID_SHOW_GROUND, OnShowGround)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_GROUND, OnUpdateShowGround)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_SKELETON, OnUpdateShowSkeleton)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_TEXTURE, OnUpdateShowTexture)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_WIREFRAME, OnUpdateShowWireframe)
|
|
ON_COMMAND(ID_SHOW_ANIM_QUEUE, OnShowAnimQueue)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_ANIM_QUEUE, OnUpdateShowAnimQueue)
|
|
ON_COMMAND(ID_FILE_SAVEMI, OnFileSaveModel)
|
|
ON_COMMAND(ID_SHOW_NORMALS, OnShowNormals)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_NORMALS, OnUpdateShowNormals)
|
|
ON_COMMAND(ID_SHOW_LIGHTS, OnShowLights)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_LIGHTS, OnUpdateShowLights)
|
|
ON_COMMAND(ID_CHANGE_AMBIENTCOLOR, OnChangeAmbientcolor)
|
|
ON_COMMAND(ID_CHANGE_LIGHTCOLOR, OnChangeLightcolor)
|
|
ON_COMMAND(ID_ANIM_LOOP, OnAnimLoop)
|
|
ON_UPDATE_COMMAND_UI(ID_ANIM_LOOP, OnUpdateAnimLoop)
|
|
ON_COMMAND(ID_ANIM_PAUSE, OnAnimPause)
|
|
ON_UPDATE_COMMAND_UI(ID_ANIM_PAUSE, OnUpdateAnimPause)
|
|
ON_COMMAND(ID_SHOW_COLISION, OnShowColision)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_COLISION, OnUpdateShowColision)
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_RBUTTONDBLCLK()
|
|
ON_COMMAND(ID_FILE_SAVEMI_AS, OnFileSavemiAs)
|
|
ON_COMMAND(ID_FILE_RECREATETEXTURE, OnFileRecreatetexture)
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_RECREATETEXTURE, OnUpdateFileRecreatetexture)
|
|
ON_COMMAND(ID_VK_DOWN, OnVkDown)
|
|
ON_COMMAND(ID_VK_UP, OnVkUp)
|
|
ON_COMMAND(ID_VK_ESCAPE, OnVkEscape)
|
|
ON_COMMAND(ID_CREATE_ADD_TEXTURE, OnCreateAddTexture)
|
|
ON_COMMAND(ID_ADD_TEXTURE_BUMP, OnAddTextureBump)
|
|
ON_COMMAND(ID_ADD_TEXTURE_REFLECTION, OnAddTextureReflection)
|
|
ON_COMMAND(ID_ADD_TEXTURE_SPECULAR, OnAddTextureSpecular)
|
|
ON_COMMAND(ID_SHOW_ACTIVE_SKELETON, OnShowActiveSkeleton)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_ACTIVE_SKELETON, OnUpdateShowActiveSkeleton)
|
|
ON_COMMAND(ID_SHOW_ALL_FRAMES_BBOX, OnShowAllFramesBbox)
|
|
ON_UPDATE_COMMAND_UI(ID_SHOW_ALL_FRAMES_BBOX, OnUpdateShowAllFramesBbox)
|
|
ON_COMMAND(ID_MODELINSTANCE_SAVEWITHOFFSET, OnModelinstanceSavewithoffset)
|
|
ON_COMMAND(ID_VK_LEFT, OnVkLeft)
|
|
ON_COMMAND(ID_VK_RIGHT, OnVkRight)
|
|
ON_COMMAND(ID_VK_LEFT_WITH_CTRL, OnVkLeftWithCtrl)
|
|
ON_COMMAND(ID_VK_RIGHT_WITH_CTRL, OnVkRightWithCtrl)
|
|
ON_COMMAND(ID_CONVERT_SELECTED, OnConvertSelected)
|
|
ON_COMMAND(ID_RESET_COLISIONBOX, OnResetColisionbox)
|
|
ON_COMMAND(ID_ALL_FRAMES_RECALC, OnAllFramesRecalc)
|
|
ON_COMMAND(ID_RELOAD_TEXTURE, OnReloadTexture)
|
|
ON_COMMAND(ID_RECREATE_TEXTURE, OnRecreateTexture)
|
|
ON_COMMAND(ID_BROWSE_TEXTURE, OnBrowseTexture)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSeriousSkaStudioView construction/destruction
|
|
|
|
CSeriousSkaStudioView::CSeriousSkaStudioView()
|
|
{
|
|
m_fFOV = 60.0f;
|
|
m_pdpDrawPort = NULL;
|
|
m_pvpViewPort = NULL;
|
|
m_angModelAngle = ANGLE3D(0.0f, 0.0f, 0.0f);
|
|
m_plLightPlacement.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f); // center
|
|
m_plLightPlacement.pl_OrientationAngle(1) = AngleDeg( 45.0f); // heading
|
|
m_plLightPlacement.pl_OrientationAngle(2) = AngleDeg( -45.0f); // pitch
|
|
m_plLightPlacement.pl_OrientationAngle(3) = AngleDeg( 0.0f); // banking
|
|
m_fLightDistance = 3.5f;
|
|
OnResetView();
|
|
}
|
|
|
|
CSeriousSkaStudioView::~CSeriousSkaStudioView()
|
|
{
|
|
}
|
|
|
|
void CSeriousSkaStudioView::SetProjectionData( CPerspectiveProjection3D &prProjection, CDrawPort *pDP)
|
|
{
|
|
prProjection.FOVL() = AngleDeg(m_fFOV);
|
|
prProjection.ScreenBBoxL() = FLOATaabbox2D( FLOAT2D(0.0f,0.0f),
|
|
FLOAT2D((float)pDP->GetWidth(), (float)pDP->GetHeight()));
|
|
prProjection.AspectRatioL() = 1.0f;
|
|
prProjection.FrontClipDistanceL() = 0.05f;
|
|
|
|
prProjection.ViewerPlacementL().pl_PositionVector = m_vTarget;
|
|
prProjection.ViewerPlacementL().pl_OrientationAngle = m_angViewerOrientation;
|
|
prProjection.Prepare();
|
|
prProjection.ViewerPlacementL().Translate_OwnSystem(FLOAT3D( 0.0f, 0.0f, m_fTargetDistance));
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnIdle(void)
|
|
{
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
BOOL CSeriousSkaStudioView::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
// TODO: Modify the Window class or styles here by modifying
|
|
// the CREATESTRUCT cs
|
|
|
|
return CView::PreCreateWindow(cs);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSeriousSkaStudioView drawing
|
|
static INDEX ctChildLevel=0;
|
|
#define MAKESPACE(x) (x>0?"%*c":""),x,' '
|
|
void CreateCurrentAnimationList(CModelInstance *pmi,CTString &strAnimations)
|
|
{
|
|
CTString strText;
|
|
CTString strTemp;
|
|
|
|
// return if no animsets
|
|
INDEX ctas = pmi->mi_aAnimSet.Count();
|
|
if(ctas == 0) {
|
|
strText.PrintF(MAKESPACE(ctChildLevel));
|
|
strText += CTString(0,"[%s]\n",(const char*)pmi->GetName());
|
|
strAnimations += strText;
|
|
return;
|
|
}
|
|
|
|
// count animlists
|
|
INDEX ctal = pmi->mi_aqAnims.aq_Lists.Count();
|
|
// find newes animlist that has fully faded in
|
|
INDEX iFirstAnimList = 0;
|
|
// loop from newer to older
|
|
INDEX ial=ctal-1;
|
|
for(;ial>=0;ial--) {
|
|
AnimList &alList = pmi->mi_aqAnims.aq_Lists[ial];
|
|
// calculate fade factor
|
|
FLOAT fFadeFactor = CalculateFadeFactor(alList);
|
|
if(fFadeFactor >= 1.0f) {
|
|
iFirstAnimList = ial;
|
|
break;
|
|
}
|
|
}
|
|
|
|
strText.PrintF(MAKESPACE(ctChildLevel));
|
|
strText += CTString(0,"[%s]\n",(const char*)pmi->GetName());
|
|
strAnimations += strText;
|
|
|
|
// for each anim list after iFirstAnimList
|
|
for(ial=iFirstAnimList;ial<ctal;ial++) {
|
|
AnimList &alList = pmi->mi_aqAnims.aq_Lists[ial];
|
|
AnimList *palListNext=NULL;
|
|
if(ial+1<ctal) palListNext = &pmi->mi_aqAnims.aq_Lists[ial+1];
|
|
|
|
INDEX ctpa = alList.al_PlayedAnims.Count();
|
|
// for each played anim in played anim list
|
|
for(int ipa=0;ipa<ctpa;ipa++) {
|
|
FLOAT fTime = _pTimer->GetLerpedCurrentTick();
|
|
PlayedAnim &pa = alList.al_PlayedAnims[ipa];
|
|
|
|
strText.PrintF(MAKESPACE(ctChildLevel+1));
|
|
strAnimations += strText;
|
|
|
|
BOOL bAnimLooping = pa.pa_ulFlags & AN_LOOPING;
|
|
|
|
INDEX iAnimSetIndex;
|
|
INDEX iAnimIndex;
|
|
// find anim by ID in all anim sets within this model
|
|
if(pmi->FindAnimationByID(pa.pa_iAnimID,&iAnimSetIndex,&iAnimIndex)) {
|
|
// if found, animate bones
|
|
Animation &an = pmi->mi_aAnimSet[iAnimSetIndex].as_Anims[iAnimIndex];
|
|
|
|
// calculate end time for this animation list
|
|
FLOAT fEndTime = alList.al_fStartTime + alList.al_fFadeTime;
|
|
// calculate curent and next frame in animation
|
|
if(palListNext!=NULL) {
|
|
if(fTime > palListNext->al_fStartTime) fTime = palListNext->al_fStartTime;
|
|
}
|
|
|
|
if(fTime < fEndTime) fTime = fEndTime;
|
|
FLOAT f = (fTime - fEndTime) / (TIME)an.an_fSecPerFrame;
|
|
|
|
INDEX iCurentFrame;
|
|
INDEX iAnimFrame,iNextAnimFrame;
|
|
|
|
if(bAnimLooping) {
|
|
f = fmod(f,an.an_iFrames);
|
|
iCurentFrame = INDEX(f);
|
|
iAnimFrame = iCurentFrame % an.an_iFrames;
|
|
iNextAnimFrame = (iCurentFrame+1) % an.an_iFrames;
|
|
} else {
|
|
if(f>an.an_iFrames) f = an.an_iFrames-1;
|
|
iCurentFrame = INDEX(f);
|
|
iAnimFrame = ClampUp(iCurentFrame,an.an_iFrames-1L);
|
|
iNextAnimFrame = ClampUp(iCurentFrame+1L,an.an_iFrames-1L);
|
|
}
|
|
|
|
FLOAT fAnimLength = an.an_iFrames * an.an_fSecPerFrame;
|
|
FLOAT fFadeFactor = CalculateFadeFactor(alList);
|
|
strText.PrintF("%s %g - %g",ska_GetStringFromTable(pa.pa_iAnimID),f,fFadeFactor);
|
|
INDEX iLength = strText.Length();
|
|
if(iLength<30) {
|
|
strTemp.PrintF(MAKESPACE(30-iLength));
|
|
strText+=strTemp;
|
|
}
|
|
strTemp.PrintF("[%g / %g]\n",f*an.an_fSecPerFrame,fAnimLength);
|
|
strAnimations += strText+strTemp;
|
|
}
|
|
}
|
|
strText.PrintF(MAKESPACE(ctChildLevel+1));
|
|
strAnimations += strText+"-----------------------\n";
|
|
}
|
|
|
|
INDEX ctcmi = pmi->mi_cmiChildren.Count();
|
|
ctChildLevel+=2;
|
|
// for each child model instance
|
|
for(INDEX icmi=0;icmi<ctcmi;icmi++) {
|
|
CModelInstance *pcmi = &pmi->mi_cmiChildren[icmi];
|
|
// create list of animations for child
|
|
CreateCurrentAnimationList(pcmi,strAnimations);
|
|
}
|
|
ctChildLevel-=2;
|
|
}
|
|
|
|
INDEX CSeriousSkaStudioView::TestRayCastHit(CPoint &pt)
|
|
{
|
|
INDEX iHitBone = -1;
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
ASSERT(pDoc!=NULL);
|
|
if(pDoc!=NULL) {
|
|
CModelInstance *pmi = pDoc->m_ModelInstance;
|
|
ASSERT(pmi!=NULL);
|
|
if(pmi!=NULL) {
|
|
|
|
INDEX iBoneID = -1;
|
|
FLOATmatrix3D mat;
|
|
mat.Diagonal(1);
|
|
// get viewer's direction vector
|
|
|
|
// set projection data
|
|
CPerspectiveProjection3D prPerspectiveProjection;
|
|
SetProjectionData( prPerspectiveProjection, m_pdpDrawPort);
|
|
|
|
// prepare render model structure
|
|
CAnyProjection3D apr;
|
|
apr = prPerspectiveProjection;
|
|
apr->Prepare();
|
|
|
|
|
|
CPlacement3D plRay;
|
|
apr->RayThroughPoint(FLOAT3D((float)pt.x,
|
|
m_pdpDrawPort->GetHeight()-(float)pt.y, 0.0f), plRay);
|
|
|
|
FLOAT3D vDirection;
|
|
AnglesToDirectionVector( plRay.pl_OrientationAngle, vDirection);
|
|
FLOAT3D vResult;
|
|
vResult = plRay.pl_PositionVector + vDirection;
|
|
|
|
RM_TestRayCastHit(*pmi,mat,FLOAT3D(0,0,0),plRay.pl_PositionVector,vResult,300000,&iBoneID);
|
|
if(iBoneID>=0) {
|
|
iHitBone = iBoneID;
|
|
}
|
|
}
|
|
}
|
|
return iHitBone;
|
|
}
|
|
|
|
void CSeriousSkaStudioView::RenderLightModels(CDrawPort *pdp,CPlacement3D &pl)
|
|
{
|
|
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
// show light objects
|
|
if(pDoc!=NULL && pDoc->bShowLights && theApp.pmiLight!=NULL)
|
|
{
|
|
CPlacement3D plLightPlacement;
|
|
plLightPlacement.pl_OrientationAngle = m_plLightPlacement.pl_OrientationAngle;
|
|
plLightPlacement.pl_PositionVector = FLOAT3D(0,0,0);
|
|
plLightPlacement.Translate_OwnSystem( FLOAT3D( 0.0f, 0.0f, m_fLightDistance));
|
|
if(pDoc->m_ModelInstance != NULL) {
|
|
plLightPlacement.Translate_AbsoluteSystem( pDoc->m_ModelInstance->GetOffsetPos());
|
|
}
|
|
|
|
|
|
// back up current model flags
|
|
ULONG ulModelFlags = RM_GetFlags();
|
|
// change render flags
|
|
RM_SetFlags(RMF_SHOWTEXTURE);
|
|
|
|
RM_SetObjectPlacement(plLightPlacement);
|
|
// render light model
|
|
RM_RenderSKA(*theApp.pmiLight);
|
|
|
|
// restore model flags
|
|
RM_SetFlags(ulModelFlags);
|
|
}
|
|
}
|
|
|
|
void AdjustBonesCallback(void *pData)
|
|
{
|
|
// aditionaly adjust bones
|
|
}
|
|
|
|
void CSeriousSkaStudioView::RenderView(CDrawPort *pdp)
|
|
{
|
|
if(theApp.GetDisableRenderRequests()>0) return;
|
|
|
|
CSeriousSkaStudioDoc* pDoc = GetDocument();
|
|
|
|
pDoc->SetTimerForDocument();
|
|
|
|
pdp->Fill(C_lGRAY | CT_OPAQUE);
|
|
pdp->FillZBuffer(ZBUF_BACK);
|
|
pdp->SetTextLineSpacing( 64);
|
|
pdp->SetFont( _pfdDisplayFont);
|
|
pdp->SetTextAspect( 1.0f);
|
|
|
|
CTString strTest;
|
|
strTest.PrintF("Serious SKA Studio");
|
|
|
|
FLOAT fX = pdp->dp_Width - 10 - pdp->GetTextWidth(strTest);
|
|
FLOAT fY = pdp->dp_Height - 8 - pdp->dp_FontData->fd_pixCharHeight;
|
|
|
|
// pdp->PutText( strTest, fX, fY, 0x0055ff00|CT_OPAQUE);
|
|
|
|
CPerspectiveProjection3D prPerspectiveProjection;
|
|
|
|
CPlacement3D pl;
|
|
pl.pl_OrientationAngle = m_angModelAngle;
|
|
pl.pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f);
|
|
|
|
if(pmiSelected!=NULL) {
|
|
// Adjust custom model instance stretch
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CString strStretch;
|
|
pMainFrame->m_ctrlMIStretch.GetWindowText(strStretch);
|
|
FLOAT fStretch = atof(CStringA(strStretch));
|
|
pmiSelected->mi_vStretch = FLOAT3D(fStretch,fStretch,fStretch);
|
|
}
|
|
|
|
|
|
if(pDoc->m_ModelInstance != NULL)
|
|
{
|
|
// set projection data
|
|
SetProjectionData( prPerspectiveProjection, pdp);
|
|
|
|
// prepare render model structure
|
|
CAnyProjection3D apr;
|
|
apr = prPerspectiveProjection;
|
|
|
|
RM_BeginRenderingView(apr, m_pdpDrawPort);
|
|
// set placement of model
|
|
CPlacement3D pl;
|
|
pl.pl_OrientationAngle = m_angModelAngle;
|
|
FLOAT fZPos = pDoc->m_fSpeedZ*fmod(_pTimer->GetLerpedCurrentTick(),pDoc->m_fLoopSecends);
|
|
pl.pl_PositionVector = FLOAT3D(0.0f, 0.0f, -fZPos);
|
|
RM_SetObjectPlacement(pl);
|
|
|
|
// Set color of shading light
|
|
RM_SetLightColor(pDoc->m_colAmbient, pDoc->m_colLight);
|
|
// Set light direction
|
|
FLOAT3D vLightDir;
|
|
AnglesToDirectionVector(pDoc->m_vLightDir,vLightDir);
|
|
|
|
CPlacement3D plLightPlacement;
|
|
plLightPlacement.pl_OrientationAngle = m_plLightPlacement.pl_OrientationAngle;
|
|
plLightPlacement.pl_PositionVector = FLOAT3D(0,0,0);
|
|
plLightPlacement.Translate_OwnSystem( FLOAT3D( 0.0f, 0.0f, m_fLightDistance));
|
|
if(pDoc->m_ModelInstance != NULL) {
|
|
plLightPlacement.Translate_AbsoluteSystem( pDoc->m_ModelInstance->GetOffsetPos());
|
|
}
|
|
|
|
RM_SetLightDirection(-plLightPlacement.pl_PositionVector);
|
|
//
|
|
|
|
// if ground is visible
|
|
if(pDoc->bShowGround) {
|
|
RM_RenderGround(theApp.toGroundTexture);
|
|
}
|
|
|
|
// Fix this
|
|
if(pDoc->bAutoMiping) {
|
|
// auto mipping
|
|
RM_SetCustomMeshLodDistance(-1);
|
|
RM_SetCustomSkeletonLodDistance(-1);
|
|
} else {
|
|
// custom mipping
|
|
RM_SetCustomMeshLodDistance(pDoc->fCustomMeshLodDist);
|
|
RM_SetCustomSkeletonLodDistance(pDoc->fCustomSkeletonLodDist);
|
|
}
|
|
|
|
/*
|
|
// Render shadow
|
|
FLOATplane3D plShadowPlane = FLOATplane3D(FLOAT3D(0,1,0),0);
|
|
pDoc->m_ModelInstance->AddSimpleShadow(1.0f,plShadowPlane);
|
|
*/
|
|
|
|
RM_SetBoneAdjustCallback(&AdjustBonesCallback,this);
|
|
|
|
// render model
|
|
RM_RenderSKA(*pDoc->m_ModelInstance);
|
|
// render selected bone
|
|
if(theApp.iSelectedBoneID >= 0) {
|
|
RM_RenderBone(*pDoc->m_ModelInstance,theApp.iSelectedBoneID);
|
|
}
|
|
|
|
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelectedItem = m_TreeCtrl.GetSelectedItem();
|
|
NodeInfo *pni = NULL;
|
|
if(hSelectedItem!=NULL) {
|
|
pni = &theApp.m_dlgBarTreeView.GetNodeInfo(hSelectedItem);
|
|
}
|
|
|
|
BOOL bShowColisionBoxes = pDoc->bShowColisionBox;
|
|
if(pni!=NULL && pni->ni_iType == NT_COLISIONBOX) {
|
|
bShowColisionBoxes = TRUE;
|
|
}
|
|
BOOL bShowAllFramesBBox = pDoc->bShowAllFramesBBox;
|
|
if(pni!=NULL && pni->ni_iType == NT_ALLFRAMESBBOX) {
|
|
bShowAllFramesBBox = TRUE;
|
|
}
|
|
|
|
// show colision box
|
|
if(pmiSelected->mi_cbAABox.Count()>0 &&pmiSelected->mi_iCurentBBox>=0) {
|
|
if(bShowColisionBoxes) {
|
|
ColisionBox &cb = pmiSelected->GetColisionBox(pmiSelected->mi_iCurentBBox);
|
|
RM_RenderColisionBox(*pmiSelected,cb,C_mlGREEN);
|
|
}
|
|
}
|
|
if(bShowAllFramesBBox) {
|
|
ColisionBox &cbAllFrames = pmiSelected->mi_cbAllFramesBBox;
|
|
RM_RenderColisionBox(*pmiSelected,cbAllFrames,C_ORANGE);
|
|
}
|
|
|
|
RenderLightModels(pdp,pl);
|
|
|
|
RM_EndRenderingView();
|
|
// show paused indicator
|
|
if(pDoc->m_bViewPaused) {
|
|
TIME tmNow = _pTimer->GetHighPrecisionTimer().GetSeconds();
|
|
ULONG ulAlpha = sin(tmNow*16)*96 +128;
|
|
pdp->SetFont( _pfdConsoleFont);
|
|
pdp->PutText( "Paused", m_pdpDrawPort->dp_Width-50, ClampDn<PIX>(m_pdpDrawPort->dp_Height-15,0), 0xffff0000|ulAlpha);
|
|
}
|
|
|
|
// Show anim queue
|
|
if(theApp.bShowAnimQueue) {
|
|
pdp->Fill(0,0,200,m_pdpDrawPort->dp_Height,0x0000007f,0x00000000,0x0000007f,0x00000000);
|
|
// show curent played animations
|
|
pdp->SetFont( _pfdConsoleFont);
|
|
|
|
CTString strAnimations;
|
|
CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
|
|
// strAnimations.PrintF("Test %g\n",tvNow.GetMilliseconds());
|
|
CreateCurrentAnimationList(pDoc->m_ModelInstance,strAnimations);
|
|
pdp->PutText( strAnimations, 0, 0, 0xffffff00|CT_OPAQUE);
|
|
}
|
|
|
|
/*
|
|
if(theApp.iSelectedBoneID>=0) {
|
|
FLOAT3D vStartPoint;
|
|
FLOAT3D vEndPoint;
|
|
if(RM_GetBoneAbsPosition(*pDoc->m_ModelInstance,theApp.iSelectedBoneID,vStartPoint,vEndPoint)) {
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgBone) {
|
|
FLOAT3D vDirection = vEndPoint - vStartPoint;
|
|
ANGLE3D angAngle;
|
|
DirectionVectorToAngles(vDirection,angAngle);
|
|
|
|
pDlgCurrent->GetDlgItem(IDC_LB_POSX)->SetWindowText((const char*)CTString(0,"%g",vStartPoint(1)));
|
|
pDlgCurrent->GetDlgItem(IDC_LB_POSY)->SetWindowText((const char*)CTString(0,"%g",vStartPoint(2)));
|
|
pDlgCurrent->GetDlgItem(IDC_LB_POSZ)->SetWindowText((const char*)CTString(0,"%g",vStartPoint(3)));
|
|
pDlgCurrent->GetDlgItem(IDC_LB_HEADING)->SetWindowText((const char*)CTString(0,"%g",angAngle(1)));
|
|
pDlgCurrent->GetDlgItem(IDC_LB_PITCH)->SetWindowText((const char*)CTString(0,"%g",angAngle(2)));
|
|
pDlgCurrent->GetDlgItem(IDC_LB_BANKING)->SetWindowText((const char*)CTString(0,"%g",angAngle(3)));
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be texture dialog
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
|
|
|
|
void CSeriousSkaStudioView::OnDraw(CDC* pDC)
|
|
{
|
|
CSeriousSkaStudioDoc* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
|
|
// if there is a valid drawport, and the drawport can be locked
|
|
if( m_pdpDrawPort!=NULL && m_pdpDrawPort->Lock())
|
|
{
|
|
// render view
|
|
RenderView( m_pdpDrawPort);
|
|
|
|
// unlock the drawport
|
|
m_pdpDrawPort->Unlock();
|
|
|
|
// swap if there is a valid viewport
|
|
if( m_pvpViewPort!=NULL)
|
|
{
|
|
m_pvpViewPort->SwapBuffers();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CView::OnSize(nType, cx, cy);
|
|
// get mainfrm
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
// get mdi client
|
|
CMDIClientWnd *pMDIClient = &pMainFrame->m_wndMDIClient;
|
|
// get mdi client rect
|
|
CRect rc;
|
|
pMDIClient->GetWindowRect(&rc);
|
|
INDEX iWidth = rc.right - rc.left - 4;
|
|
INDEX iHeight = rc.bottom - rc.top - 4;
|
|
// check if view is maximized
|
|
if((iWidth == cx) && (iHeight == cy))
|
|
{
|
|
m_iViewSize = SIZE_MAXIMIZED;
|
|
theApp.bChildrenMaximized = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_iViewSize = 0;
|
|
theApp.bChildrenMaximized = FALSE;
|
|
}
|
|
|
|
|
|
// if we are not in game mode and changing of display mode is not on
|
|
if( m_pvpViewPort!=NULL)
|
|
{ // resize it
|
|
m_pvpViewPort->Resize();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnDestroy()
|
|
{
|
|
CView::OnDestroy();
|
|
|
|
// destroy canvas that is currently used
|
|
_pGfx->DestroyWindowCanvas( m_pvpViewPort);
|
|
m_pvpViewPort = NULL;
|
|
|
|
CView::OnDestroy();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSeriousSkaStudioView diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CSeriousSkaStudioView::AssertValid() const
|
|
{
|
|
CView::AssertValid();
|
|
}
|
|
|
|
void CSeriousSkaStudioView::Dump(CDumpContext& dc) const
|
|
{
|
|
CView::Dump(dc);
|
|
}
|
|
|
|
CSeriousSkaStudioDoc* CSeriousSkaStudioView::GetDocument() // non-debug version is inline
|
|
{
|
|
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSeriousSkaStudioDoc)));
|
|
return (CSeriousSkaStudioDoc*)m_pDocument;
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSeriousSkaStudioView message handlers
|
|
|
|
void CSeriousSkaStudioView::OnInitialUpdate()
|
|
{
|
|
CView::OnInitialUpdate();
|
|
|
|
CSeriousSkaStudioDoc* pDoc = GetDocument();
|
|
// at this time, m_hWnd is valid, so we do canvas initialization here
|
|
_pGfx->CreateWindowCanvas(m_hWnd, &m_pvpViewPort, &m_pdpDrawPort);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
BOOL bSpace = (GetKeyState(' ') & 128) != 0;
|
|
BOOL bLMB = nFlags & MK_LBUTTON;
|
|
BOOL bRMB = nFlags & MK_RBUTTON;
|
|
BOOL bCtrl = nFlags & MK_CONTROL;
|
|
BOOL bShift = nFlags & MK_SHIFT;
|
|
|
|
|
|
CPoint pntDelta = point - m_pntLastMouse;
|
|
m_pntLastMouse = point;
|
|
FLOAT fDistance = -m_fTargetDistance;
|
|
|
|
CPlacement3D plViewer;
|
|
plViewer.pl_PositionVector = m_vTarget;
|
|
plViewer.pl_OrientationAngle = m_angViewerOrientation;
|
|
// moving offsets need small amounts
|
|
FLOAT dx = 0.001f * pntDelta.x * fDistance;
|
|
FLOAT dy = 0.001f * pntDelta.y * fDistance;
|
|
FLOAT dz = 0.01f * pntDelta.y * fDistance;
|
|
// angles need lot for rotation
|
|
ANGLE dAngleX = AngleDeg( -0.5f * pntDelta.x);
|
|
ANGLE dAngleY = AngleDeg( -0.5f * pntDelta.y);
|
|
|
|
if (bSpace && bCtrl) {
|
|
// if only space
|
|
} else if (bSpace)
|
|
{
|
|
if (bRMB && bLMB)
|
|
{
|
|
m_angViewerOrientation(1)+=dAngleX;
|
|
m_angViewerOrientation(2)+=dAngleY;
|
|
// if only left button
|
|
} else if (bLMB) {
|
|
CPlacement3D plTarget;
|
|
plTarget.pl_PositionVector = m_vTarget;
|
|
plTarget.pl_OrientationAngle = m_angViewerOrientation;
|
|
|
|
// project the placement to the viewer's system
|
|
plTarget.AbsoluteToRelative( plViewer);
|
|
// translate it
|
|
plTarget.Translate_AbsoluteSystem( FLOAT3D( dx, -dy, 0.0f));
|
|
// project the placement back from viewer's system
|
|
plTarget.RelativeToAbsolute( plViewer);
|
|
m_vTarget = plTarget.pl_PositionVector;
|
|
// if only right button
|
|
} else if (bRMB) {
|
|
// move target away
|
|
m_fTargetDistance += dz;
|
|
|
|
// now apply left/right movement
|
|
CPlacement3D plTarget;
|
|
plTarget.pl_PositionVector = m_vTarget;
|
|
plTarget.pl_OrientationAngle = m_angViewerOrientation;
|
|
|
|
// project the placement to the viewer's system
|
|
plTarget.AbsoluteToRelative( plViewer);
|
|
// translate it
|
|
plTarget.Translate_AbsoluteSystem( FLOAT3D( dx, 0.0f, 0.0f));
|
|
// project the placement back from viewer's system
|
|
plTarget.RelativeToAbsolute( plViewer);
|
|
m_vTarget = plTarget.pl_PositionVector;
|
|
// if no buttons are held
|
|
} else {
|
|
|
|
}
|
|
}
|
|
// if only ctrl
|
|
else if (bCtrl && (bRMB || bLMB))
|
|
{
|
|
CSeriousSkaStudioDoc* pDoc = GetDocument();
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelectedItem = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelectedItem==NULL) {
|
|
return;
|
|
}
|
|
NodeInfo &niSelected = theApp.m_dlgBarTreeView.GetNodeInfo(hSelectedItem);
|
|
CModelInstance *pmi = NULL;
|
|
// is selected item model instance
|
|
if(niSelected.ni_iType == NT_MODELINSTANCE){
|
|
// get pointer to model instance
|
|
pmi = (CModelInstance*)niSelected.ni_pPtr;
|
|
|
|
// set default bone placement
|
|
QVect qvBonePlacement;
|
|
memset(&qvBonePlacement,0,sizeof(QVect));
|
|
qvBonePlacement.qRot.q_w = 1;
|
|
// find parent bone of selected model instance
|
|
RenBone rb;
|
|
if(RM_GetRenBoneAbs(*pDoc->m_ModelInstance,pmi->mi_iParentBoneID,rb)) {
|
|
// get bone qvect
|
|
Matrix12ToQVect(qvBonePlacement,rb.rb_mBonePlacement);
|
|
}
|
|
CPlacement3D plBone,plOffset;
|
|
FLOATmatrix3D matBone,matOffset;
|
|
|
|
// set bone placement
|
|
qvBonePlacement.qRot.ToMatrix(matBone);
|
|
plBone.pl_PositionVector = qvBonePlacement.vPos;
|
|
DecomposeRotationMatrix(plBone.pl_OrientationAngle,matBone);
|
|
|
|
// set offset
|
|
pmi->mi_qvOffset.qRot.ToMatrix(matOffset);
|
|
plOffset.pl_PositionVector = pmi->mi_qvOffset.vPos;
|
|
DecomposeRotationMatrix(plOffset.pl_OrientationAngle,matOffset);
|
|
|
|
plOffset.RelativeToRelative(plBone,plViewer);
|
|
|
|
if(bLMB && bRMB) {
|
|
plOffset.Rotate_TrackBall( ANGLE3D( -dAngleX/2, -dAngleY/2, 0));
|
|
} else if(bLMB) {
|
|
plOffset.pl_PositionVector += FLOAT3D( -dx, dy, 0.0f);
|
|
} else if(bRMB) {
|
|
plOffset.pl_PositionVector += FLOAT3D( 0.0f, 0.0f, -dy);
|
|
}
|
|
plOffset.RelativeToRelative(plViewer,plBone);
|
|
|
|
pmi->mi_qvOffset.vPos=plOffset.pl_PositionVector;
|
|
pmi->mi_qvOffset.qRot.FromEuler(plOffset.pl_OrientationAngle);
|
|
|
|
_bSelectedItemChanged = TRUE;
|
|
pDoc->MarkAsChanged();
|
|
// is selected item colision box
|
|
} else if (niSelected.ni_iType == NT_COLISIONBOX) {
|
|
// get pointer to parent model instance
|
|
pmi = (CModelInstance*)niSelected.pmi;
|
|
|
|
ColisionBox &cb = pmi->GetColisionBox(pmi->mi_iCurentBBox);
|
|
|
|
CPlacement3D plCBMin;
|
|
CPlacement3D plCBMax;
|
|
FLOATmatrix3D matOffset;
|
|
|
|
// set min and max of colision box
|
|
plCBMin.pl_PositionVector = cb.Min();
|
|
plCBMin.pl_OrientationAngle = ANGLE3D(0,0,0);
|
|
plCBMin.AbsoluteToRelative(plViewer);
|
|
|
|
plCBMax.pl_PositionVector = cb.Max();
|
|
plCBMax.pl_OrientationAngle = ANGLE3D(0,0,0);
|
|
plCBMax.AbsoluteToRelative(plViewer);
|
|
// if shift is pressed
|
|
if(bShift) {
|
|
if(bLMB) {
|
|
plCBMin.pl_PositionVector += FLOAT3D( -dx, dy, 0.0f);
|
|
} else if(bRMB) {
|
|
plCBMax.pl_PositionVector += FLOAT3D( -dx, dy, 0.0f);
|
|
}
|
|
// if not
|
|
} else {
|
|
if(bLMB) {
|
|
plCBMin.pl_PositionVector += FLOAT3D( -dx, dy, 0.0f);
|
|
plCBMax.pl_PositionVector += FLOAT3D( -dx, dy, 0.0f);
|
|
} else if(bRMB) {
|
|
plCBMin.pl_PositionVector += FLOAT3D( 0.0f, 0.0f, -dy);
|
|
}
|
|
}
|
|
|
|
plCBMin.RelativeToAbsolute(plViewer);
|
|
plCBMax.RelativeToAbsolute(plViewer);
|
|
cb.SetMin(plCBMin.pl_PositionVector);
|
|
cb.SetMax(plCBMax.pl_PositionVector);
|
|
|
|
_bSelectedItemChanged = TRUE;
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
// if only shift is presed
|
|
} else if(bShift) {
|
|
if(bLMB) {
|
|
// project the placement to the viewer's system
|
|
m_plLightPlacement.AbsoluteToRelative( plViewer);
|
|
// rotate it
|
|
m_plLightPlacement.Rotate_TrackBall( ANGLE3D( -dAngleX/2, -dAngleY/2, 0));
|
|
// project the placement back from viewer's system
|
|
m_plLightPlacement.RelativeToAbsolute( plViewer);
|
|
} else if(bRMB) {
|
|
FLOAT fNewDistance = m_fLightDistance - dz;
|
|
if( fNewDistance > 0.2f) {
|
|
m_fLightDistance = fNewDistance;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// SetActiveWindow();
|
|
SetFocus();
|
|
/*
|
|
GetParentFrame()->SetActiveView( this);
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
pMainFrame->MDIActivate(GetParentFrame());
|
|
*/
|
|
/*
|
|
HWND hwndUnderMouse = ::WindowFromPoint( point);
|
|
HWND hwndInfo = NULL;
|
|
if( pMainFrame->m_pInfoFrame != NULL)
|
|
hwndInfo = pMainFrame->m_pInfoFrame->m_hWnd;
|
|
|
|
if( (m_hWnd != ::GetActiveWindow()) && ( hwndInfo != hwndUnderMouse) )
|
|
{
|
|
SetActiveWindow();
|
|
SetFocus();
|
|
GetParentFrame()->SetActiveView( this);
|
|
pMainFrame->MDIActivate(GetParentFrame());
|
|
}
|
|
*/
|
|
CView::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
|
|
void CSeriousSkaStudioView::FastZoomIn()
|
|
{
|
|
if( m_fTargetDistance > 1.0f) {
|
|
m_fTargetDistance /= 2.0f;
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::FastZoomOut()
|
|
{
|
|
if( m_fTargetDistance < 65535.0f) {
|
|
m_fTargetDistance *= 2.0f;
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
|
|
BOOL bCtrl = nFlags & MK_CONTROL;
|
|
BOOL bShift = nFlags & MK_SHIFT;
|
|
// ctrl+space+XMB is used for 2x zooming
|
|
if( bCtrl && bSpace) {
|
|
FastZoomIn();
|
|
return;
|
|
}
|
|
|
|
if(bCtrl||bSpace||bShift) {}
|
|
else {
|
|
INDEX iHitBone = TestRayCastHit(point);
|
|
if(iHitBone!=(-1) && iHitBone!=theApp.iSelectedBoneID) {
|
|
|
|
}
|
|
theApp.iSelectedBoneID = iHitBone;
|
|
}
|
|
|
|
m_pntLastMouse = point;
|
|
CView::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
|
|
BOOL bCtrl = nFlags & MK_CONTROL;
|
|
// ctrl+space+XMB is used for 2x zooming
|
|
if( bCtrl && bSpace) {
|
|
FastZoomIn();
|
|
}
|
|
CView::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnRButtonDown(UINT nFlags, CPoint point) {
|
|
BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
|
|
BOOL bCtrl = nFlags & MK_CONTROL;
|
|
// ctrl+space+XMB is used for 2x zooming
|
|
if( bCtrl && bSpace) {
|
|
FastZoomOut();
|
|
return;
|
|
}
|
|
CView::OnRButtonDown(nFlags, point);
|
|
}
|
|
void CSeriousSkaStudioView::OnRButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
BOOL bSpace = (GetKeyState( ' ') & 128) != 0;
|
|
BOOL bCtrl = nFlags & MK_CONTROL;
|
|
// ctrl+space+XMB is used for 2x zooming
|
|
if( bCtrl && bSpace) {
|
|
FastZoomOut();
|
|
}
|
|
CView::OnRButtonDblClk(nFlags, point);
|
|
}
|
|
|
|
|
|
void CSeriousSkaStudioView::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelectedItem = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelectedItem!=NULL && _bSelectedItemChanged) {
|
|
theApp.m_dlgBarTreeView.SelItemChanged(hSelectedItem);
|
|
_bSelectedItemChanged = FALSE;
|
|
}
|
|
CView::OnLButtonUp(nFlags, point);
|
|
}
|
|
void CSeriousSkaStudioView::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelectedItem = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelectedItem!=NULL && _bSelectedItemChanged) {
|
|
theApp.m_dlgBarTreeView.SelItemChanged(hSelectedItem);
|
|
_bSelectedItemChanged = FALSE;
|
|
}
|
|
CView::OnRButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnResetView()
|
|
{
|
|
m_angViewerOrientation = ANGLE3D(180.0f, -20.0f, 0.0f);
|
|
m_vTarget = FLOAT3D(0.0f, 1.0f, 0.0f);
|
|
m_fTargetDistance = 5.0f;
|
|
}
|
|
|
|
// add CMesh to selected model instance
|
|
BOOL CSeriousSkaStudioView::OnAddMeshlist()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CTFileName fnSim;
|
|
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return FALSE;
|
|
}
|
|
|
|
CTFileName fnSelected = pmiSelected->mi_fnSourceFile;
|
|
fnSelected = fnSelected.FileName();
|
|
// get file name
|
|
fnSim = _EngineGUI.FileRequester( "Type name for new Mesh list or select existing",
|
|
"ASCII model files (*.aml)\0*.aml\0"
|
|
"All files (*.*)\0*.*\0\0",
|
|
"Open directory", "Models\\",fnSelected);
|
|
if (fnSim=="") return FALSE;
|
|
// check if file allready exist
|
|
if(FileExists(fnSim))
|
|
{
|
|
CTString strText = CTString(0,"File '%s' exist\n\nPress OK to load it, Cancel to overwrite it",fnSim);
|
|
int iRet = AfxMessageBox(CString(strText),MB_OKCANCEL);
|
|
if(iRet == IDOK)
|
|
{
|
|
// convert and load animset
|
|
if(theApp.ConvertMesh(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".bm";
|
|
try
|
|
{
|
|
pmiSelected->AddMesh_t(fnSim);
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
return TRUE;
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
// else owerwrite it bellow
|
|
}
|
|
// if file does not exist create new one
|
|
CTFileStream ostrFile;
|
|
try
|
|
{
|
|
// create new file
|
|
ostrFile.Create_t(fnSim,CTStream::CM_TEXT);
|
|
// write empty header in file
|
|
ostrFile.FPrintF_t("MESHLODLIST\n{\n}\n");
|
|
// close file
|
|
ostrFile.Close();
|
|
// convert it to binary (just to exist)
|
|
if(theApp.ConvertMesh(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".bm";
|
|
// add it to selected model instance
|
|
try
|
|
{
|
|
pmiSelected->AddMesh_t(fnSim);
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
return FALSE;
|
|
}
|
|
pDoc->MarkAsChanged();
|
|
return TRUE;
|
|
}
|
|
|
|
// add CSkeleton to selected model instance
|
|
void CSeriousSkaStudioView::OnAddSkeletonlist()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CTFileName fnSim;
|
|
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
|
|
CSkeleton *skl = pmiSelected->mi_psklSkeleton;
|
|
if(skl != NULL)
|
|
{
|
|
theApp.ErrorMessage("Skeleton for this object exists. Only one skeleton per model is allowed!");
|
|
return;
|
|
}
|
|
|
|
CTFileName fnSelected = pmiSelected->mi_fnSourceFile;
|
|
fnSelected = fnSelected.FileName();
|
|
// get file name
|
|
fnSim = _EngineGUI.FileRequester( "Type name for new Skeleton list or select existing",
|
|
"ASCII model files (*.asl)\0*.asl\0"
|
|
"All files (*.*)\0*.*\0\0",
|
|
"Open directory", "Models\\", fnSelected);
|
|
if (fnSim=="") return;
|
|
// check if file allready exist
|
|
if(FileExists(fnSim))
|
|
{
|
|
CTString strText = CTString(0,"File '%s' exist\n\nPress OK to load it, Cancel to overwrite it",fnSim);
|
|
int iRet = AfxMessageBox(CString(strText),MB_OKCANCEL);
|
|
if(iRet == IDOK)
|
|
{
|
|
// convert and load animset
|
|
if(theApp.ConvertSkeleton(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".bs";
|
|
try
|
|
{
|
|
pmiSelected->AddSkeleton_t(fnSim);
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
// else owerwrite it bellow
|
|
}
|
|
// if file does not exist create new one
|
|
CTFileStream ostrFile;
|
|
try
|
|
{
|
|
// create new file
|
|
ostrFile.Create_t(fnSim,CTStream::CM_TEXT);
|
|
// write empty header in file
|
|
ostrFile.FPrintF_t("SKELETONLODLIST\n{\n}\n");
|
|
// close file
|
|
ostrFile.Close();
|
|
// convert it to binary (just to exist)
|
|
if(theApp.ConvertSkeleton(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".bs";
|
|
// add it to selected model instance
|
|
pmiSelected->AddSkeleton_t(fnSim);
|
|
// save smc
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
}
|
|
pDoc->MarkAsChanged();
|
|
return;
|
|
}
|
|
|
|
// add anim set to selected model instance
|
|
void CSeriousSkaStudioView::OnAddAnimset()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CTFileName fnSim;
|
|
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
|
|
CTFileName fnSelected = pmiSelected->mi_fnSourceFile;
|
|
fnSelected = fnSelected.FileName();
|
|
// get file name
|
|
fnSim = _EngineGUI.FileRequester( "Type name for new Animset or select existing",
|
|
"ASCII model files (*.aal)\0*.aal\0"
|
|
"All files (*.*)\0*.*\0\0",
|
|
"Open directory", "Models\\", fnSelected);
|
|
if (fnSim=="") return;
|
|
// check if file allready exist
|
|
if(FileExists(fnSim))
|
|
{
|
|
CTString strText = CTString(0,"File '%s' exist\n\nPress OK to load it, Cancel to overwrite it",fnSim);
|
|
int iRet = AfxMessageBox(CString(strText),MB_OKCANCEL);
|
|
if(iRet == IDOK)
|
|
{
|
|
// convert and load animset
|
|
if(theApp.ConvertAnimSet(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".ba";
|
|
try
|
|
{
|
|
pmiSelected->AddAnimSet_t(fnSim);
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
// else owerwrite it bellow
|
|
}
|
|
// if file does not exist create new one
|
|
CTFileStream ostrFile;
|
|
try
|
|
{
|
|
// create new file
|
|
ostrFile.Create_t(fnSim,CTStream::CM_TEXT);
|
|
// write empty header in file
|
|
ostrFile.FPrintF_t("ANIMSETLIST\n{\n}\n");
|
|
// close file
|
|
ostrFile.Close();
|
|
// convert it to binary (just to exist)
|
|
if(theApp.ConvertAnimSet(fnSim))
|
|
{
|
|
fnSim = fnSim.NoExt() + ".ba";
|
|
// add it to selected model instance
|
|
pmiSelected->AddAnimSet_t(fnSim);
|
|
}
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
theApp.ErrorMessage("%s",strError);
|
|
}
|
|
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
return;
|
|
}
|
|
|
|
// add new child model instance to selected model instance
|
|
void CSeriousSkaStudioView::OnAddChildModelInstance()
|
|
{
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
CModelInstance::EnableSrcRememberFN(TRUE);
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
if(pDoc->m_ModelInstance == NULL)
|
|
{
|
|
theApp.ErrorMessage("There is no root model instance");
|
|
return;
|
|
}
|
|
|
|
CSkeleton *psklParent = pmiSelected->mi_psklSkeleton;
|
|
SkeletonLOD *psklodParent = NULL;
|
|
INDEX iParentBoneID = 0;
|
|
// if parent has skeleton
|
|
if(psklParent != NULL)
|
|
{
|
|
// if parent has skeleton lods
|
|
INDEX ctslod = psklParent->skl_aSkeletonLODs.Count();
|
|
if(ctslod > 0)
|
|
{
|
|
psklodParent = &psklParent->skl_aSkeletonLODs[0];
|
|
INDEX ctsb = psklodParent->slod_aBones.Count();
|
|
// if parent has any bones
|
|
if(ctsb > 0)
|
|
{
|
|
SkeletonBone &sb = psklodParent->slod_aBones[0];
|
|
iParentBoneID = sb.sb_iID;
|
|
}
|
|
}
|
|
}
|
|
|
|
CTFileName fnSim;
|
|
fnSim = _EngineGUI.FileRequester( "Open ASCII intermediate files",
|
|
"ASCII model files (*.smc)\0*.smc\0"
|
|
"All files (*.*)\0*.*\0\0",
|
|
"Open directory", "Models\\", "");
|
|
if (fnSim=="") return;
|
|
|
|
CTFileName fnFull;
|
|
fnFull = _fnmApplicationPath + fnSim;
|
|
CModelInstance *pcmi=NULL;
|
|
try
|
|
{
|
|
pcmi = ParseSmcFile_t(fnFull);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
// error in parsing occured
|
|
theApp.ErrorMessage("%s",strError);
|
|
if(pcmi != NULL) pcmi->Clear();
|
|
return;
|
|
}
|
|
|
|
CTString strText = CTString(0,"Add this model as reference or use own copy");
|
|
int iRet = AfxMessageBox(CString(strText),MB_YESNO);
|
|
if(iRet == IDNO)
|
|
{
|
|
// assign same source file name as parent model instance so it will be saved in same file
|
|
pcmi->mi_fnSourceFile = pmiSelected->mi_fnSourceFile;
|
|
}
|
|
pcmi->mi_iParentBoneID = iParentBoneID;
|
|
|
|
// reset offset
|
|
memset(&pcmi->mi_qvOffset,0,sizeof(QVect));
|
|
pcmi->mi_qvOffset.qRot.q_w = 1;
|
|
// if there is selected model instance ,add as child
|
|
pmiSelected->mi_cmiChildren.Add(pcmi);
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
// add mesh lod to existing CMesh in selected model instance
|
|
void CSeriousSkaStudioView::OnAddMeshlod()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
|
|
// if mesh list does not exist
|
|
INDEX ctmshi = pmiSelected->mi_aMeshInst.Count();
|
|
if(ctmshi < 1)
|
|
{
|
|
theApp.ErrorMessage("Model instance must have mesh lod list to add mesh lod to it");
|
|
return;
|
|
}
|
|
// get pointer to selected item
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
INDEX iSelected = m_TreeCtrl.GetItemData(hSelected);
|
|
NodeInfo &niSelected = theApp.aNodeInfo[iSelected];
|
|
MeshInstance *pmshi;
|
|
|
|
// get selected mesh instance
|
|
if(niSelected.ni_iType == NT_MESHLODLIST)
|
|
{
|
|
// selected item is mesh instance so use its pointer as current mesh instance
|
|
pmshi=(MeshInstance*)niSelected.ni_pPtr;
|
|
}
|
|
else if(niSelected.ni_iType == NT_MESHLOD)
|
|
{
|
|
// selected item is mesh lod, so get his parent and use his pointer as current mesh instance
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hSelected);
|
|
INDEX iParent = m_TreeCtrl.GetItemData(hParent);
|
|
NodeInfo &niParent = theApp.aNodeInfo[iParent];
|
|
pmshi=(MeshInstance*)niParent.ni_pPtr;
|
|
}
|
|
else
|
|
{
|
|
// other item is selected, curent mesh instance is first mesh instance in model instance
|
|
pmshi=&pmiSelected->mi_aMeshInst[0];
|
|
}
|
|
|
|
CMesh *pMesh = pmshi->mi_pMesh;
|
|
|
|
CDynamicArray<CTFileName> afnMesh;
|
|
_EngineGUI.FileRequester( "Open ASCII intermediate files",
|
|
FILTER_MESH,
|
|
"Open directory", "Models\\", "", &afnMesh);
|
|
|
|
// return if no files selected
|
|
if(afnMesh.Count()<=0) return;
|
|
FLOAT fMaxDistance = 10;
|
|
INDEX ctmlod = pMesh->msh_aMeshLODs.Count();
|
|
// for each lod in skeleton
|
|
INDEX imlod=0;
|
|
for(;imlod<ctmlod;imlod++)
|
|
{
|
|
// find current max distance in skeleton
|
|
if((fMaxDistance-5)<pMesh->msh_aMeshLODs[imlod].mlod_fMaxDistance)
|
|
fMaxDistance = pMesh->msh_aMeshLODs[imlod].mlod_fMaxDistance;
|
|
}
|
|
// create new skeleton list that holds only new skeleton lods
|
|
CTString strMeshList;
|
|
strMeshList = "MESHLODLIST\n{\n";
|
|
|
|
FOREACHINDYNAMICARRAY( afnMesh, CTFileName, itMesh)
|
|
{
|
|
fMaxDistance+=5;
|
|
CTString strLine;
|
|
strLine.PrintF(" MAX_DISTANCE %g;\n #INCLUDE \"%s\"\n",fMaxDistance,(const char*)itMesh.Current());
|
|
// add this file to mesh list file
|
|
strMeshList += strLine;
|
|
}
|
|
strMeshList += "}\n";
|
|
|
|
CTFileName fnMeshList = (CTString)"Temp/mesh.aml";
|
|
CTFileName fnMeshBin = (CTString)"Temp/mesh.bm";
|
|
|
|
CMesh mshTemp;
|
|
try
|
|
{
|
|
// save list file
|
|
strMeshList.Save_t(fnMeshList);
|
|
// convert animset list file
|
|
if(!theApp.ConvertMesh(fnMeshList))
|
|
{
|
|
RemoveFile(fnMeshList);
|
|
return;
|
|
}
|
|
// load it
|
|
mshTemp.Load_t(fnMeshBin);
|
|
}
|
|
catch(char *strErr)
|
|
{
|
|
theApp.ErrorMessage(strErr);
|
|
mshTemp.Clear();
|
|
RemoveFile(fnMeshBin);
|
|
return;
|
|
}
|
|
RemoveFile(fnMeshList);
|
|
RemoveFile(fnMeshBin);
|
|
|
|
// count new skleton lods in temp skeleton list
|
|
INDEX ctNewMlods = mshTemp.msh_aMeshLODs.Count();
|
|
// for each new skeleton in temp skeleton lod list
|
|
for(imlod=0;imlod<ctNewMlods;imlod++)
|
|
{
|
|
// add skeleton lod to selected skeleton
|
|
pMesh->AddMeshLod(mshTemp.msh_aMeshLODs[imlod]);
|
|
}
|
|
// clear temp mesh
|
|
mshTemp.Clear();
|
|
// update model instance
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
// add skeleton lod to existing CSkeleton in selected model instance
|
|
void CSeriousSkaStudioView::OnAddSkeletonlod()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
|
|
if(pmiSelected == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
|
|
CSkeleton *pSkeleton = pmiSelected->mi_psklSkeleton;
|
|
if(pSkeleton == NULL)
|
|
{
|
|
theApp.ErrorMessage("Model instance must have Skeleton list to add skeleton lod to it");
|
|
return;
|
|
}
|
|
|
|
CDynamicArray<CTFileName> afnSkeleton;
|
|
_EngineGUI.FileRequester( "Open ASCII intermediate files",
|
|
FILTER_SKELETON,
|
|
"Open directory", "Models\\", "", &afnSkeleton);
|
|
|
|
// return if no files selected
|
|
if(afnSkeleton.Count()<=0) return;
|
|
|
|
FLOAT fMaxDistance=10;
|
|
INDEX ctslod = pSkeleton->skl_aSkeletonLODs.Count();
|
|
// for each lod in skeleton
|
|
for(INDEX ilod=0;ilod<ctslod;ilod++)
|
|
{
|
|
// find current max distance in skeleton
|
|
if((fMaxDistance-5)<pSkeleton->skl_aSkeletonLODs[ilod].slod_fMaxDistance) fMaxDistance = pSkeleton->skl_aSkeletonLODs[ilod].slod_fMaxDistance;
|
|
}
|
|
|
|
// create new skeleton list that holds only new skeleton lods
|
|
CTString strSkeletonList;
|
|
strSkeletonList = "SKELETONLODLIST\n{\n";
|
|
|
|
FOREACHINDYNAMICARRAY( afnSkeleton, CTFileName, itSkeleton)
|
|
{
|
|
fMaxDistance+=5;
|
|
CTString strLine;
|
|
strLine.PrintF(" MAX_DISTANCE %g;\n #INCLUDE \"%s\"\n",fMaxDistance,(const char*)itSkeleton.Current());
|
|
// add this file to skeleton list file
|
|
strSkeletonList += strLine;
|
|
}
|
|
strSkeletonList += "}\n";
|
|
|
|
CTFileName fnSklList = (CTString)"Temp/skeleton.asl";
|
|
CTFileName fnSklBin = (CTString)"Temp/skeleton.bs";
|
|
CSkeleton slTemp;
|
|
|
|
try
|
|
{
|
|
// save list file
|
|
strSkeletonList.Save_t(fnSklList);
|
|
// convert animset list file
|
|
if(!theApp.ConvertSkeleton(fnSklList))
|
|
{
|
|
slTemp.Clear();
|
|
RemoveFile(fnSklList);
|
|
return;
|
|
}
|
|
// load it
|
|
slTemp.Load_t(fnSklBin);
|
|
}
|
|
catch(char *strErr)
|
|
{
|
|
theApp.ErrorMessage(strErr);
|
|
slTemp.Clear();
|
|
RemoveFile(fnSklBin);
|
|
return;
|
|
}
|
|
RemoveFile(fnSklList);
|
|
RemoveFile(fnSklBin);
|
|
|
|
// count new skleton lods in temp skeleton list
|
|
INDEX ctNewSlods = slTemp.skl_aSkeletonLODs.Count();
|
|
// for each new skeleton in temp skeleton lod list
|
|
for(INDEX isl=0;isl<ctNewSlods;isl++)
|
|
{
|
|
// add skeleton lod to selected skeleton
|
|
pSkeleton->AddSkletonLod(slTemp.skl_aSkeletonLODs[isl]);
|
|
}
|
|
// clear temp skeleton
|
|
slTemp.Clear();
|
|
// update model instance
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
// add animation to existing Anim set in selected model instance
|
|
void CSeriousSkaStudioView::OnAddAnimation()
|
|
{
|
|
// check for selected model instance
|
|
if(pmiSelected == NULL) {
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
// get animset count
|
|
INDEX ctas = pmiSelected->mi_aAnimSet.Count();
|
|
if(ctas < 1) {
|
|
theApp.ErrorMessage("Model instance must have Anim set to add animations to it");
|
|
return;
|
|
}
|
|
// get document
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CDynamicArray<CTFileName> afnAnimation;
|
|
_EngineGUI.FileRequester( "Open ASCII intermediate files",
|
|
FILTER_ANIMATION,
|
|
"Open directory", "Models\\", "", &afnAnimation);
|
|
|
|
// return if no files selected
|
|
if(afnAnimation.Count()<=0) return;
|
|
|
|
// get pointer to seleceted animset
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
INDEX iSelected = m_TreeCtrl.GetItemData(hSelected);
|
|
NodeInfo &niSelected = theApp.aNodeInfo[iSelected];
|
|
CAnimSet *pas=NULL;
|
|
if(niSelected.ni_iType == NT_ANIMSET) {
|
|
// selected item is animset
|
|
pas = (CAnimSet*)niSelected.ni_pPtr;
|
|
} else if(niSelected.ni_iType == NT_ANIMATION) {
|
|
// selected item is animation, get its animset
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hSelected);
|
|
INDEX iParent = m_TreeCtrl.GetItemData(hParent);
|
|
NodeInfo &niParent = theApp.aNodeInfo[iParent];
|
|
pas = (CAnimSet*)niParent.ni_pPtr;
|
|
} else {
|
|
// something else is selected, use first animset in model instance
|
|
pas = &pmiSelected->mi_aAnimSet[0];
|
|
}
|
|
|
|
// create new animset that holds only new animations
|
|
CTString strAnimSet;
|
|
strAnimSet = "ANIMSETLIST\n{\n";
|
|
// for each selected file
|
|
FOREACHINDYNAMICARRAY( afnAnimation, CTFileName, itAnimation)
|
|
{
|
|
// add this file to animset list file
|
|
CTString strLine;
|
|
strLine.PrintF(" TRESHOLD 0;\n COMPRESION FALSE;\n #INCLUDE \"%s\"\n",(const char*)itAnimation.Current());
|
|
strAnimSet += strLine;
|
|
}
|
|
strAnimSet += "}\n";
|
|
|
|
CTFileName fnAnimSetList = (CTString)"Temp/animset.aal";
|
|
CTFileName fnAnimSetBin = (CTString)"Temp/animset.ba";
|
|
CAnimSet asTemp;
|
|
|
|
try
|
|
{
|
|
// save list file
|
|
strAnimSet.Save_t(fnAnimSetList);
|
|
// convert animset list file
|
|
if(!theApp.ConvertAnimSet(fnAnimSetList))
|
|
{
|
|
RemoveFile(fnAnimSetList);
|
|
return;
|
|
}
|
|
// load it
|
|
asTemp.Load_t(fnAnimSetBin);
|
|
}
|
|
catch(char *strErr)
|
|
{
|
|
theApp.ErrorMessage(strErr);
|
|
asTemp.Clear();
|
|
RemoveFile(fnAnimSetBin);
|
|
return;
|
|
}
|
|
RemoveFile(fnAnimSetList);
|
|
RemoveFile(fnAnimSetBin);
|
|
|
|
// count new animations in temp animset
|
|
INDEX ctan = asTemp.as_Anims.Count();
|
|
// for each new animation in temp animset
|
|
for(INDEX ian=0;ian<ctan;ian++)
|
|
{
|
|
Animation &anTemp = asTemp.as_Anims[ian];
|
|
// add animation to selected animset
|
|
pas->AddAnimation(&anTemp);
|
|
}
|
|
// clear temp animset
|
|
asTemp.Clear();
|
|
// update model instance
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
|
|
// add texture to existing mesh instance
|
|
void CSeriousSkaStudioView::AddTexture(CTFileName &fnFull)
|
|
{
|
|
if(pmiSelected == NULL) {
|
|
theApp.ErrorMessage("Model instance is not selected!");
|
|
return;
|
|
}
|
|
|
|
INDEX ctmshi = pmiSelected->mi_aMeshInst.Count();
|
|
if(ctmshi < 1) {
|
|
theApp.ErrorMessage("Model instance must have mesh lod list to add texture to it");
|
|
return;
|
|
}
|
|
|
|
// get selected item in tree view
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
INDEX iSelected = m_TreeCtrl.GetItemData(hSelected);
|
|
NodeInfo &niSelected = theApp.aNodeInfo[iSelected];
|
|
MeshInstance *pmshi;
|
|
// get selected mesh instance
|
|
if(niSelected.ni_iType == NT_MESHLODLIST) {
|
|
// selected item is mesh instance so use its pointer as current mesh instance
|
|
pmshi=(MeshInstance*)niSelected.ni_pPtr;
|
|
} else if(niSelected.ni_iType == NT_MESHLOD) {
|
|
// selected item is mesh lod, so get his parent and use his pointer as current mesh instance
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hSelected);
|
|
INDEX iParent = m_TreeCtrl.GetItemData(hParent);
|
|
NodeInfo &niParent = theApp.aNodeInfo[iParent];
|
|
pmshi=(MeshInstance*)niParent.ni_pPtr;
|
|
} else {
|
|
// other item is selected, curent mesh instance is first mesh instance in model instance
|
|
pmshi=&pmiSelected->mi_aMeshInst[0];
|
|
}
|
|
/*
|
|
// check if file exists
|
|
if(!FileExists(fnFull)) {
|
|
theApp.ErrorMessage("Texture file '%s' does not exists",fnFull);
|
|
continue;
|
|
}
|
|
*/
|
|
// try adding texture to model instance
|
|
try {
|
|
pmiSelected->AddTexture_t(fnFull,fnFull.FileName(),pmshi);
|
|
} catch(char *strError) {
|
|
theApp.ErrorMessage(strError);
|
|
//continue;
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::BrowseTexture(CTString strTextureDir)
|
|
{
|
|
CString strRegKeyName = "";
|
|
if(strTextureDir=="Models\\") {
|
|
strTextureDir = "Open directory";
|
|
}
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CDynamicArray<CTFileName> afnTexture;
|
|
_EngineGUI.FileRequester( "Open texture files",
|
|
FILTER_TEXTURE,
|
|
(char*)(const char*)strTextureDir, strTextureDir, "", &afnTexture);
|
|
|
|
// return if no files selected
|
|
if(afnTexture.Count()<=0) return;
|
|
// for each selected filename
|
|
FOREACHINDYNAMICARRAY( afnTexture, CTFileName, itTexture) {
|
|
CTFileName fnFull;
|
|
fnFull = itTexture.Current();
|
|
AddTexture(fnFull);
|
|
}
|
|
pDoc->MarkAsChanged();
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
|
|
// add texture to existing mesh instance
|
|
void CSeriousSkaStudioView::OnAddTexture()
|
|
{
|
|
BrowseTexture("Models\\");
|
|
}
|
|
void CSeriousSkaStudioView::OnAddTextureBump()
|
|
{
|
|
BrowseTexture("Models\\BumpTextures\\");
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAddTextureReflection()
|
|
{
|
|
BrowseTexture("Models\\ReflectionTextures\\");
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAddTextureSpecular()
|
|
{
|
|
BrowseTexture("Models\\SpecularTextures\\");
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnCreateAddTexture()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CTFileName fn = (CTString)pMainFrame->CreateTexture();
|
|
if(fn!="") {
|
|
AddTexture(fn);
|
|
pDoc->MarkAsChanged();
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAddColisionbox()
|
|
{
|
|
if(pmiSelected == NULL) return;
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
|
|
INDEX ctcb = pmiSelected->mi_cbAABox.Count();
|
|
FLOAT3D vMin = FLOAT3D(-.5f,0,-.5f);
|
|
FLOAT3D vMax = FLOAT3D(.5f,1,.5f);
|
|
CTString strName = CTString(0,"Default %d",ctcb);
|
|
pmiSelected->AddColisionBox(strName,vMin,vMax);
|
|
theApp.UpdateRootModelInstance();
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
|
|
// delete selected item in tree view control
|
|
void CSeriousSkaStudioView::OnDeleteselected()
|
|
{
|
|
// get tree ctrl
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
// get current document
|
|
CSeriousSkaStudioDoc *pDoc = GetDocument();
|
|
// get selected item and its parent
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelected == NULL) return;
|
|
INDEX iSelIndex = m_TreeCtrl.GetItemData(hSelected);
|
|
INDEX iParentIndex = -1;
|
|
NodeInfo *pniParent = NULL;
|
|
NodeInfo *pni = &theApp.aNodeInfo[iSelIndex];
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hSelected);
|
|
if(hParent != NULL)
|
|
{
|
|
iParentIndex = m_TreeCtrl.GetItemData(hParent);
|
|
pniParent = &theApp.aNodeInfo[iParentIndex];
|
|
}
|
|
// switch type of selected item
|
|
switch(pni->ni_iType)
|
|
{
|
|
case NT_MODELINSTANCE:
|
|
{
|
|
// find parent of selected model instance
|
|
CModelInstance *pmiParent = pmiSelected->GetParent(pDoc->m_ModelInstance);
|
|
if(pmiParent != NULL) {
|
|
// remove selected model instance form parent
|
|
pmiParent->RemoveChild(pmiSelected);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
} else {
|
|
// root item is selected
|
|
theApp.ErrorMessage("Can't delete root model instance");
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case NT_MESHLODLIST:
|
|
{
|
|
// get pointer to mesh instance
|
|
MeshInstance *pmshi = (MeshInstance*)pni->ni_pPtr;
|
|
// get pointer to mesh
|
|
CMesh *pMesh = pmshi->mi_pMesh;
|
|
// release mesh
|
|
_pMeshStock->Release(pMesh);
|
|
// count textures
|
|
INDEX ctti=pmshi->mi_tiTextures.Count();
|
|
// for each texture in selected mesh instance
|
|
for(INDEX iti=0;iti<ctti;iti++) {
|
|
// release texture from stock
|
|
TextureInstance &ti = pmshi->mi_tiTextures[iti];
|
|
ti.ti_toTexture.SetData(NULL);
|
|
//CTextureData &td = *ti.ti_tdTexture;
|
|
//_pTextureStock->Release(&td);
|
|
}
|
|
// count mesh instances
|
|
INDEX ctmshi=pmiSelected->mi_aMeshInst.Count();
|
|
INDEX itmpmshi=0;
|
|
CStaticArray<struct MeshInstance> atmpMeshInst;
|
|
// create array for mesh instances
|
|
atmpMeshInst.New(ctmshi-1);
|
|
// for each mesh instance in selected model instance
|
|
for(INDEX imshi=0;imshi<ctmshi;imshi++) {
|
|
MeshInstance *ptmpmshi = &pmiSelected->mi_aMeshInst[imshi];
|
|
// if mesh instance is diferent then selected mesh instance
|
|
if(ptmpmshi != pmshi) {
|
|
// copy it to temp array
|
|
atmpMeshInst[itmpmshi] = *ptmpmshi;
|
|
itmpmshi++;
|
|
}
|
|
}
|
|
// clear mesh instance
|
|
pmiSelected->mi_aMeshInst.Clear();
|
|
pmiSelected->mi_aMeshInst.CopyArray(atmpMeshInst);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_MESHLOD:
|
|
{
|
|
ASSERT(pniParent!=NULL);
|
|
MeshLOD *pmlodSelected = (MeshLOD*)pni->ni_pPtr;
|
|
MeshInstance *pmshi = (MeshInstance*)pniParent->ni_pPtr;
|
|
CMesh *pmesh = pmshi->mi_pMesh;
|
|
pmesh->RemoveMeshLod(pmlodSelected);
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_TEXINSTANCE:
|
|
{
|
|
// get pointers to texture and mesh instances
|
|
TextureInstance *pti = (TextureInstance*)pni->ni_pPtr;
|
|
MeshInstance *pmshi = (MeshInstance*)pniParent->ni_pPtr;
|
|
ASSERT(pti!=NULL);
|
|
ASSERT(pmshi!=NULL);
|
|
|
|
pmiSelected->RemoveTexture(pti,pmshi);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_SKELETONLODLIST:
|
|
{
|
|
CSkeleton *skl = pmiSelected->mi_psklSkeleton;
|
|
_pSkeletonStock->Release(skl);
|
|
pmiSelected->mi_psklSkeleton = NULL;
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();//!!!
|
|
}
|
|
break;
|
|
case NT_SKELETONLOD:
|
|
{
|
|
// get pointers to skeleton and skeleton lod
|
|
SkeletonLOD *pslodSelected = (SkeletonLOD*)pni->ni_pPtr;
|
|
CSkeleton *pskl = (CSkeleton*)pniParent->ni_pPtr;
|
|
pskl->RemoveSkeletonLod(pslodSelected);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_BONE:
|
|
{
|
|
return;
|
|
}
|
|
break;
|
|
case NT_ANIM_BONEENV:
|
|
{
|
|
return;
|
|
}
|
|
break;
|
|
case NT_MESHSURFACE:
|
|
{
|
|
return;
|
|
}
|
|
break;
|
|
case NT_ANIMSET:
|
|
{
|
|
CAnimSet *pas = (CAnimSet*)pni->ni_pPtr;
|
|
pmiSelected->mi_aAnimSet.Remove(pas);
|
|
_pAnimSetStock->Release(pas);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_ANIMATION:
|
|
{
|
|
// take pointer to anim set
|
|
Animation *panSelected = (Animation*)pni->ni_pPtr;
|
|
CAnimSet *pas = (CAnimSet*)pniParent->ni_pPtr;
|
|
pas->RemoveAnimation(panSelected);
|
|
// update model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
case NT_COLISIONBOX:
|
|
{
|
|
ColisionBox *pcbSelected = (ColisionBox*)pni->ni_pPtr;
|
|
// find colision box
|
|
INDEX iIndex = -1;
|
|
// count colision boxes
|
|
INDEX ctcb = pmiSelected->mi_cbAABox.Count();
|
|
// for each colision box in model instance
|
|
for(INDEX icb=0;icb<ctcb;icb++) {
|
|
ColisionBox *pcb2 = &pmiSelected->mi_cbAABox[icb];
|
|
if(pcbSelected == pcb2) {
|
|
// remember index of selected colision box
|
|
iIndex = icb;
|
|
break;
|
|
}
|
|
}
|
|
// return if no index
|
|
if(iIndex<0) return;
|
|
// remove bounding box from mi
|
|
pmiSelected->RemoveColisionBox(iIndex);
|
|
// update root model instance
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
break;
|
|
}
|
|
pDoc->MarkAsChanged();
|
|
}
|
|
|
|
// fill tree view with new selected document
|
|
void CSeriousSkaStudioView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
|
|
{
|
|
if(bActivate) {
|
|
// refresh tree view for curent view
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hRoot = m_TreeCtrl.GetRootItem();
|
|
|
|
if(pDoc == NULL) {
|
|
theApp.m_dlgBarTreeView.UpdateModelInstInfo(NULL);
|
|
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
|
|
return;
|
|
}
|
|
if(hRoot == NULL) {
|
|
theApp.UpdateRootModelInstance();
|
|
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
|
|
return;
|
|
}
|
|
|
|
INDEX iRoot = m_TreeCtrl.GetItemData(hRoot);
|
|
NodeInfo &ni = theApp.aNodeInfo[iRoot];
|
|
// update only ih root model changed
|
|
if(ni.ni_pPtr != pDoc->m_ModelInstance) {
|
|
theApp.UpdateRootModelInstance();
|
|
}
|
|
}
|
|
CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
|
|
}
|
|
|
|
void SyncModelInstance(CModelInstance *pmi,FLOAT fTime)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
|
|
AnimQueue &anq = pmi->mi_aqAnims;
|
|
INDEX ctal = anq.aq_Lists.Count();
|
|
// for each anim list
|
|
for(INDEX ial=0;ial<ctal;ial++)
|
|
{
|
|
AnimList &al = anq.aq_Lists[ial];
|
|
al.al_fStartTime = fTime;
|
|
|
|
// for each played anim
|
|
INDEX ctpa=al.al_PlayedAnims.Count();
|
|
for(INDEX ipa=0;ipa<ctpa;ipa++)
|
|
{
|
|
PlayedAnim &pa = al.al_PlayedAnims[ipa];
|
|
pa.pa_fStartTime = fTime;
|
|
|
|
if(pDoc->bAnimLoop) {
|
|
pa.pa_ulFlags |= AN_LOOPING;
|
|
} else {
|
|
pa.pa_ulFlags &= ~AN_LOOPING;
|
|
}
|
|
}
|
|
}
|
|
|
|
INDEX ctmi = pmi->mi_cmiChildren.Count();
|
|
// for each child
|
|
for(INDEX imi=0;imi<ctmi;imi++)
|
|
{
|
|
CModelInstance &cmi = pmi->mi_cmiChildren[imi];
|
|
SyncModelInstance(&cmi,fTime);
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAnimSync()
|
|
{
|
|
SyncModelInstance(theApp.GetDocument()->m_ModelInstance,_pTimer->CurrentTick());
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAnimLoop()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->bAnimLoop=!pDoc->bAnimLoop;
|
|
SyncModelInstance(theApp.GetDocument()->m_ModelInstance,_pTimer->CurrentTick());
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateAnimLoop(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bAnimLoop);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAnimPause()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->m_bViewPaused = !pDoc->m_bViewPaused;
|
|
// if now unpaused
|
|
if(!pDoc->m_bViewPaused) {
|
|
// calculate time in pause
|
|
pDoc->m_tvPauseTime += _pTimer->GetHighPrecisionTimer() - pDoc->m_tvPauseStart;
|
|
}
|
|
pDoc->m_tvPauseStart = _pTimer->GetHighPrecisionTimer();
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateAnimPause(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pCmdUI->SetCheck(pDoc->m_bViewPaused);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkEscape()
|
|
{
|
|
// if error list is visible
|
|
if(theApp.IsErrorDlgVisible()) {
|
|
// hide it
|
|
theApp.ShowErrorDlg(FALSE);
|
|
// else
|
|
} else {
|
|
// stop all animations
|
|
OnAnimStop();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAnimStop()
|
|
{
|
|
CModelInstance *pmi = theApp.GetDocument()->m_ModelInstance;
|
|
pmi->StopAllAnimations(0);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAutoMiping()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->bAutoMiping=!pDoc->bAutoMiping;
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateAutoMiping(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bAutoMiping);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowGround()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->bShowGround=!pDoc->bShowGround;
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateShowGround(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bShowGround);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowSkeleton()
|
|
{
|
|
if(RM_GetFlags() & RMF_SHOWSKELETON) RM_RemoveFlag(RMF_SHOWSKELETON);
|
|
else RM_AddFlag(RMF_SHOWSKELETON);
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateShowSkeleton(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck((RM_GetFlags() & RMF_SHOWSKELETON) ? 1:0);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowActiveSkeleton()
|
|
{
|
|
if(RM_GetFlags() & RMF_SHOWACTIVEBONES) RM_RemoveFlag(RMF_SHOWACTIVEBONES);
|
|
else RM_AddFlag(RMF_SHOWACTIVEBONES);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateShowActiveSkeleton(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck((RM_GetFlags() & RMF_SHOWACTIVEBONES) ? 1:0);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowTexture()
|
|
{
|
|
if(RM_GetFlags() & RMF_SHOWTEXTURE) RM_RemoveFlag(RMF_SHOWTEXTURE);
|
|
else RM_AddFlag(RMF_SHOWTEXTURE);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowNormals()
|
|
{
|
|
if(RM_GetFlags() & RMF_SHOWNORMALS) RM_RemoveFlag(RMF_SHOWNORMALS);
|
|
else RM_AddFlag(RMF_SHOWNORMALS);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateShowNormals(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck((RM_GetFlags() & RMF_SHOWNORMALS) ? 1:0);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateShowTexture(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck((RM_GetFlags() & RMF_SHOWTEXTURE) ? 1:0);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowWireframe()
|
|
{
|
|
if(RM_GetFlags() & RMF_WIREFRAME) RM_RemoveFlag(RMF_WIREFRAME);
|
|
else RM_AddFlag(RMF_WIREFRAME);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateShowWireframe(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck((RM_GetFlags() & RMF_WIREFRAME) ? 1:0);
|
|
}
|
|
|
|
|
|
void CSeriousSkaStudioView::OnShowColision()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) {
|
|
pDoc->bShowColisionBox = !pDoc->bShowColisionBox;
|
|
}
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateShowColision(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bShowColisionBox);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowAllFramesBbox()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) {
|
|
pDoc->bShowAllFramesBBox = !pDoc->bShowAllFramesBBox;
|
|
}
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateShowAllFramesBbox(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bShowAllFramesBBox);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowAnimQueue()
|
|
{
|
|
theApp.bShowAnimQueue=!theApp.bShowAnimQueue;
|
|
}
|
|
void CSeriousSkaStudioView::OnUpdateShowAnimQueue(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(theApp.bShowAnimQueue);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnFileSaveModel()
|
|
{
|
|
theApp.SaveRootModel();
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnFileSavemiAs()
|
|
{
|
|
theApp.SaveRootModelAs();
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnShowLights()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->bShowLights=!pDoc->bShowLights;
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateShowLights(CCmdUI* pCmdUI)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc!=NULL) pCmdUI->SetCheck(pDoc->bShowLights);
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnChangeAmbientcolor()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
|
|
COLORREF acrCustClr[16];
|
|
CHOOSECOLOR cc;
|
|
acrCustClr[ 0] = CLRF_CLR(C_BLACK);
|
|
acrCustClr[ 1] = CLRF_CLR(C_WHITE);
|
|
acrCustClr[ 2] = CLRF_CLR(C_dGRAY);
|
|
acrCustClr[ 3] = CLRF_CLR(C_GRAY);
|
|
acrCustClr[ 4] = CLRF_CLR(C_lGRAY);
|
|
acrCustClr[ 5] = CLRF_CLR(C_dRED);
|
|
acrCustClr[ 6] = CLRF_CLR(C_dGREEN);
|
|
acrCustClr[ 7] = CLRF_CLR(C_dBLUE);
|
|
acrCustClr[ 8] = CLRF_CLR(C_dCYAN);
|
|
acrCustClr[ 9] = CLRF_CLR(C_dMAGENTA);
|
|
acrCustClr[10] = CLRF_CLR(C_dYELLOW);
|
|
acrCustClr[11] = CLRF_CLR(C_dORANGE);
|
|
acrCustClr[12] = CLRF_CLR(C_dBROWN);
|
|
acrCustClr[13] = CLRF_CLR(C_dPINK);
|
|
acrCustClr[14] = CLRF_CLR(C_lORANGE);
|
|
acrCustClr[15] = CLRF_CLR(C_lBROWN);
|
|
|
|
pDoc->m_colAmbient &= 0xFFFFFF00;
|
|
|
|
memset(&cc, 0, sizeof(CHOOSECOLOR));
|
|
cc.lStructSize = sizeof(CHOOSECOLOR);
|
|
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
|
|
cc.rgbResult = ByteSwap(pDoc->m_colAmbient);
|
|
cc.hwndOwner = GetSafeHwnd();
|
|
cc.lpCustColors = (LPDWORD) acrCustClr;
|
|
if(ChooseColor(&cc))
|
|
{
|
|
COLOR colAmbient = ByteSwap(cc.rgbResult);
|
|
colAmbient |= 0xFF;
|
|
pDoc->m_colAmbient = colAmbient;
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnChangeLightcolor()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
|
|
COLORREF acrCustClr[16];
|
|
CHOOSECOLOR cc;
|
|
acrCustClr[ 0] = CLRF_CLR(C_BLACK);
|
|
acrCustClr[ 1] = CLRF_CLR(C_WHITE);
|
|
acrCustClr[ 2] = CLRF_CLR(C_dGRAY);
|
|
acrCustClr[ 3] = CLRF_CLR(C_GRAY);
|
|
acrCustClr[ 4] = CLRF_CLR(C_lGRAY);
|
|
acrCustClr[ 5] = CLRF_CLR(C_dRED);
|
|
acrCustClr[ 6] = CLRF_CLR(C_dGREEN);
|
|
acrCustClr[ 7] = CLRF_CLR(C_dBLUE);
|
|
acrCustClr[ 8] = CLRF_CLR(C_dCYAN);
|
|
acrCustClr[ 9] = CLRF_CLR(C_dMAGENTA);
|
|
acrCustClr[10] = CLRF_CLR(C_dYELLOW);
|
|
acrCustClr[11] = CLRF_CLR(C_dORANGE);
|
|
acrCustClr[12] = CLRF_CLR(C_dBROWN);
|
|
acrCustClr[13] = CLRF_CLR(C_dPINK);
|
|
acrCustClr[14] = CLRF_CLR(C_lORANGE);
|
|
acrCustClr[15] = CLRF_CLR(C_lBROWN);
|
|
|
|
pDoc->m_colLight &= 0xFFFFFF00;
|
|
memset(&cc, 0, sizeof(CHOOSECOLOR));
|
|
cc.lStructSize = sizeof(CHOOSECOLOR);
|
|
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
|
|
cc.rgbResult = ByteSwap(pDoc->m_colLight);
|
|
cc.hwndOwner = GetSafeHwnd();
|
|
cc.lpCustColors = (LPDWORD) acrCustClr;
|
|
if(ChooseColor(&cc))
|
|
{
|
|
COLOR colDiffuse = ByteSwap(cc.rgbResult);
|
|
colDiffuse |= 0xFF;
|
|
pDoc->m_colLight = colDiffuse;
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
/*
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(nChar==VK_LEFT) {
|
|
if(!pDoc->m_bViewPaused) {
|
|
OnAnimPause();
|
|
} else {
|
|
pDoc->m_tvPauseStart.tv_llValue -= 10000000;
|
|
}
|
|
return;
|
|
}
|
|
if(nChar==VK_RIGHT) {
|
|
if(!pDoc->m_bViewPaused) {
|
|
OnAnimPause();
|
|
} else {
|
|
pDoc->m_tvPauseStart.tv_llValue += 10000000;
|
|
}
|
|
return;
|
|
}
|
|
*/
|
|
CView::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
|
|
|
|
void CSeriousSkaStudioView::OnFileRecreatetexture()
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
// if selected item exists
|
|
if(hSelected!=NULL) {
|
|
NodeInfo &niSelected = theApp.m_dlgBarTreeView.GetNodeInfo(hSelected);
|
|
// is selected item texture instance
|
|
if(niSelected.ni_iType == NT_TEXINSTANCE) {
|
|
// recreate texture
|
|
theApp.m_dlgBarTreeView.m_dlgTexture.OnBtRecreateTexture();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnUpdateFileRecreatetexture(CCmdUI* pCmdUI)
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
// if selected item exists
|
|
if(hSelected!=NULL) {
|
|
NodeInfo &niSelected = theApp.m_dlgBarTreeView.GetNodeInfo(hSelected);
|
|
// is selected item texture instance
|
|
if(niSelected.ni_iType == NT_TEXINSTANCE) {
|
|
// enable recreate texture menu item
|
|
pCmdUI->Enable(TRUE);
|
|
} else {
|
|
// disable recreate texture menu item
|
|
pCmdUI->Enable(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkDown()
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelected!=NULL) {
|
|
HTREEITEM hNext = m_TreeCtrl.GetNextItem(hSelected,TVGN_NEXTVISIBLE);
|
|
if(hNext!=NULL) {
|
|
m_TreeCtrl.SelectItem(hNext);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkUp()
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelected!=NULL) {
|
|
HTREEITEM hNext = m_TreeCtrl.GetNextItem(hSelected,TVGN_PREVIOUSVISIBLE);
|
|
if(hNext!=NULL) {
|
|
m_TreeCtrl.SelectItem(hNext);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void SelectLeftItemInTree()
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelected!=NULL) {
|
|
UINT uiMask = TVIF_STATE;
|
|
UINT uiState = m_TreeCtrl.GetItemState(hSelected,uiMask);
|
|
if(uiState&TVIS_EXPANDED) {
|
|
m_TreeCtrl.Expand(hSelected,TVE_COLLAPSE);
|
|
} else {
|
|
HTREEITEM hParent = m_TreeCtrl.GetNextItem(hSelected,TVGN_PARENT);
|
|
if(hParent!=NULL) {
|
|
m_TreeCtrl.SelectItem(hParent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
static void SelectRightItemInTree()
|
|
{
|
|
CModelTreeCtrl &m_TreeCtrl = theApp.m_dlgBarTreeView.m_TreeCtrl;
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
if(hSelected!=NULL) {
|
|
UINT uiMask = TVIF_STATE;
|
|
UINT uiState = m_TreeCtrl.GetItemState(hSelected,uiMask);
|
|
if(uiState&TVIS_EXPANDED) {
|
|
HTREEITEM hClild = m_TreeCtrl.GetNextItem(hSelected,TVGN_CHILD);
|
|
if(hClild!=NULL) {
|
|
m_TreeCtrl.SelectItem(hClild);
|
|
}
|
|
} else {
|
|
m_TreeCtrl.Expand(hSelected,TVE_EXPAND);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void NextFrame()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->m_tvPauseStart.tv_llValue += 10000000;
|
|
}
|
|
static void PrevFrame()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
pDoc->m_tvPauseStart.tv_llValue -= 10000000;
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkLeft()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc->m_bViewPaused) {
|
|
PrevFrame();
|
|
} else {
|
|
SelectLeftItemInTree();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkRight()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc->m_bViewPaused) {
|
|
NextFrame();
|
|
} else {
|
|
SelectRightItemInTree();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkLeftWithCtrl()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc->m_bViewPaused) {
|
|
SelectLeftItemInTree();
|
|
} else {
|
|
OnAnimPause();
|
|
PrevFrame();
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnVkRightWithCtrl()
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
if(pDoc->m_bViewPaused) {
|
|
SelectRightItemInTree();
|
|
} else {
|
|
OnAnimPause();
|
|
NextFrame();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Menus
|
|
*/
|
|
|
|
void CSeriousSkaStudioView::OnModelinstanceSavewithoffset()
|
|
{
|
|
NodeInfo &ni = theApp.m_dlgBarTreeView.GetSelectedNodeInfo();
|
|
if(ni.ni_iType == NT_MODELINSTANCE) {
|
|
CModelInstance *pmi = (CModelInstance*)ni.ni_pPtr;
|
|
CModelInstance *pmiParent = pmi->GetParent(theApp.GetDocument()->m_ModelInstance);
|
|
|
|
CString fnOldSmcFile;
|
|
// if parent of model instance exists
|
|
if(pmiParent!=NULL) {
|
|
// remmeber current fn of model instance
|
|
fnOldSmcFile = pmi->mi_fnSourceFile;
|
|
// temporary remove it to save offset of model instance in same file
|
|
pmiParent->RemoveChild(pmi);
|
|
}
|
|
|
|
// save model instance
|
|
theApp.SaveModelAs(pmi);
|
|
|
|
// if there was a parent for model instance
|
|
if(pmiParent!=NULL) {
|
|
// return model instance to his parent
|
|
pmiParent->AddChild(pmi);
|
|
// restore old filename
|
|
pmi->mi_fnSourceFile = CTString(CStringA(fnOldSmcFile));
|
|
}
|
|
} else {
|
|
ASSERT(FALSE); // This must be model instance
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnConvertSelected()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgListOpt) {
|
|
pDlgCurrent->OnBtConvert();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be listopt dialog
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnResetColisionbox()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgColision) {
|
|
pDlgCurrent->OnBtResetColision();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be colision dialog
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnAllFramesRecalc()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgAllFrames) {
|
|
pDlgCurrent->OnBtCalcAllframesBbox();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be allframes dialog
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnReloadTexture()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgTexture) {
|
|
pDlgCurrent->OnBtReloadTexture();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be texture dialog
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnRecreateTexture()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgTexture) {
|
|
pDlgCurrent->OnBtRecreateTexture();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be texture dialog
|
|
}
|
|
}
|
|
|
|
void CSeriousSkaStudioView::OnBrowseTexture()
|
|
{
|
|
CDlgClient *pDlgCurrent = (CDlgClient*)theApp.m_dlgBarTreeView.pdlgCurrent;
|
|
if(pDlgCurrent == &theApp.m_dlgBarTreeView.m_dlgTexture) {
|
|
pDlgCurrent->OnBtBrowseTexture();
|
|
} else {
|
|
ASSERT(FALSE); // Current client dialog must be texture dialog
|
|
}
|
|
}
|