mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-29 21:25:54 +01:00
1753 lines
58 KiB
C++
1753 lines
58 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
// DlgBarTreeView.cpp: implementation of the CDlgBarTreeView class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "SeriousSkaStudio.h"
|
|
#include "DlgBarTreeView.h"
|
|
#include "resource.h"
|
|
#include "MainFrm.h"
|
|
#include "ChildFrm.h"
|
|
#include "DlgTemplate.h"
|
|
#include <Engine\Base\Stream.h>
|
|
#include <Engine\Ska\Skeleton.h>
|
|
|
|
#ifdef _DEBUG
|
|
#undef new
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// array of depth in recursion to selected item
|
|
CStaticStackArray<INDEX> _aSelectItem;
|
|
// array of selected mesh surfaces
|
|
CStaticStackArray<INDEX> _aiSelectedMeshSurfaces;
|
|
|
|
|
|
CStaticArray<class CTextureControl> _atxcTexControls;
|
|
CStaticArray<class CTexCoordControl> _atxccTexCoordControls;
|
|
CStaticArray<class CFloatControl> _afcFloatControls;
|
|
CStaticArray<class CFlagControl> _afcFlagControls;
|
|
CStaticArray<class CColorControl> _accColors;
|
|
extern INDEX iCustomControlID;
|
|
|
|
BEGIN_MESSAGE_MAP(CDlgBarTreeView, CDlgTemplate)
|
|
//{{AFX_MSG_MAP(CDlgBarTreeView)
|
|
ON_NOTIFY(TCN_SELCHANGE, IDC_MODE_SELECT_TAB, OnSelchangeModeSelectTab)
|
|
ON_WM_SIZE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
CDlgBarTreeView::CDlgBarTreeView()
|
|
{
|
|
pdlgCurrent = NULL;
|
|
}
|
|
CDlgBarTreeView::~CDlgBarTreeView()
|
|
{
|
|
}
|
|
// returns info of item in tree view
|
|
NodeInfo &CDlgBarTreeView::GetNodeInfo(HTREEITEM hItem)
|
|
{
|
|
ASSERT(hItem!=NULL);
|
|
INDEX iNodeIndex = m_TreeCtrl.GetItemData(hItem);
|
|
return theApp.aNodeInfo[iNodeIndex];
|
|
}
|
|
|
|
// returns infog of selected item in tree view
|
|
NodeInfo &CDlgBarTreeView::GetSelectedNodeInfo()
|
|
{
|
|
HTREEITEM hSelected = m_TreeCtrl.GetSelectedItem();
|
|
ASSERT(hSelected!=NULL);
|
|
// aditional check
|
|
INDEX iNodeIndex = 0;
|
|
if(hSelected!=NULL) {
|
|
iNodeIndex = m_TreeCtrl.GetItemData(hSelected);
|
|
}
|
|
return theApp.aNodeInfo[iNodeIndex];
|
|
}
|
|
|
|
|
|
// chose control group to show
|
|
void CDlgBarTreeView::ShowControlGroup(INDEX iGroup)
|
|
{
|
|
CDialog *pLastVisibleDlg = pdlgCurrent;
|
|
switch(iGroup)
|
|
{
|
|
case GR_PARENT:
|
|
pdlgCurrent = &m_dlgParent;
|
|
break;
|
|
case GR_ANIMSET:
|
|
pdlgCurrent = &m_dlgAnimSet;
|
|
break;
|
|
case GR_COLISION:
|
|
pdlgCurrent = &m_dlgColision;
|
|
break;
|
|
case GR_ALLFRAMES_BBOX:
|
|
pdlgCurrent = &m_dlgAllFrames;
|
|
break;
|
|
case GR_LOD:
|
|
pdlgCurrent = &m_dlgLod;
|
|
break;
|
|
case GR_BONE:
|
|
pdlgCurrent = &m_dlgBone;
|
|
break;
|
|
case GR_TEXTURE:
|
|
pdlgCurrent = &m_dlgTexture;
|
|
break;
|
|
case GR_LISTOPTIONS:
|
|
pdlgCurrent = &m_dlgListOpt;
|
|
break;
|
|
case GR_SHADERS:
|
|
pdlgCurrent = &m_dlgShader;
|
|
break;
|
|
default:
|
|
pdlgCurrent = NULL;
|
|
break;
|
|
}
|
|
if(pLastVisibleDlg!=pdlgCurrent) {
|
|
if(pLastVisibleDlg!=NULL) {
|
|
// hide current dialog
|
|
pLastVisibleDlg->ShowWindow(SW_HIDE);
|
|
}
|
|
if(pdlgCurrent!=NULL) {
|
|
// show new dialog
|
|
pdlgCurrent->ShowWindow(SW_SHOW);
|
|
}
|
|
}
|
|
}
|
|
|
|
// select surface in tree view
|
|
void CDlgBarTreeView::SelectMeshSurface(HTREEITEM hItem)
|
|
{
|
|
INDEX iNodeIndex = m_TreeCtrl.GetItemData(hItem);
|
|
INDEX iIcon = 12;
|
|
NodeInfo &ni = theApp.aNodeInfo[iNodeIndex];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
|
|
// count selected mesh surfaces
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surface in array
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
INDEX &iIndex = _aiSelectedMeshSurfaces[isms];
|
|
// check if surface is allready selected
|
|
if(iIndex == iNodeIndex)
|
|
{
|
|
// surface is allready selected, return
|
|
return;
|
|
}
|
|
}
|
|
// add surface to selection array
|
|
INDEX &iIndex = _aiSelectedMeshSurfaces.Push();
|
|
iIndex = iNodeIndex;
|
|
// set new icon
|
|
m_TreeCtrl.SetItemImage(hItem,iIcon,iIcon);
|
|
}
|
|
|
|
// Seselect surface in tree view
|
|
void CDlgBarTreeView::DeselectMeshSurface(HTREEITEM hItem)
|
|
{
|
|
INDEX iNodeIndex = m_TreeCtrl.GetItemData(hItem);
|
|
INDEX iIcon = 11;
|
|
NodeInfo &ni = theApp.aNodeInfo[iNodeIndex];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
|
|
// count selected mesh surfaces
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surface in array
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
INDEX &iIndex = _aiSelectedMeshSurfaces[isms];
|
|
// check if this is clicked item
|
|
if(iIndex == iNodeIndex)
|
|
{
|
|
// remove one item
|
|
INDEX iLastIndex = _aiSelectedMeshSurfaces.Pop();
|
|
iIndex = iLastIndex;
|
|
// set new icon
|
|
m_TreeCtrl.SetItemImage(hItem,iIcon,iIcon);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Togle surface selection in tree view
|
|
void CDlgBarTreeView::TogleSurfaceSelection(HTREEITEM hItem)
|
|
{
|
|
INDEX iNodeIndex = m_TreeCtrl.GetItemData(hItem);
|
|
NodeInfo &ni = theApp.aNodeInfo[iNodeIndex];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
|
|
// count selected mesh surfaces
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surface in array
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
INDEX &iIndex = _aiSelectedMeshSurfaces[isms];
|
|
// check if this is clicked item
|
|
if(iIndex == iNodeIndex)
|
|
{
|
|
// deselect surface
|
|
DeselectMeshSurface(hItem);
|
|
return;
|
|
}
|
|
}
|
|
// if item was't previously selected, select it
|
|
SelectMeshSurface(hItem);
|
|
}
|
|
|
|
// Deselect all surfaces
|
|
void CDlgBarTreeView::DeSelectAllSurfaces(HTREEITEM hParent/*=NULL*/)
|
|
{
|
|
INDEX iIcon=11;
|
|
if(hParent==NULL)
|
|
{
|
|
hParent = m_TreeCtrl.GetRootItem();
|
|
_aiSelectedMeshSurfaces.PopAll();
|
|
}
|
|
|
|
HTREEITEM hChild = m_TreeCtrl.GetChildItem(hParent);
|
|
while(hChild!=NULL)
|
|
{
|
|
DeSelectAllSurfaces(hChild);
|
|
NodeInfo &ni = GetNodeInfo(hChild);
|
|
if(ni.ni_iType == NT_MESHSURFACE)
|
|
{
|
|
m_TreeCtrl.SetItemImage(hChild,iIcon,iIcon);
|
|
}
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
}
|
|
}
|
|
|
|
// select all surfaces if item is not selected, otherwise deselect all
|
|
void CDlgBarTreeView::SelectAllSurfaces(HTREEITEM hItem)
|
|
{
|
|
INDEX iIcon = -1;
|
|
INDEX iNodeIndex = m_TreeCtrl.GetItemData(hItem);
|
|
NodeInfo &ni = theApp.aNodeInfo[iNodeIndex];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
// clicked item is allready selected, deselect all surfaces
|
|
BOOL bSelect = IsSurfaceSelected(*pmsrf);
|
|
// get parent
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hItem);
|
|
INDEX iParentIndex = m_TreeCtrl.GetItemData(hParent);
|
|
NodeInfo &niParent = theApp.aNodeInfo[iParentIndex];
|
|
ASSERT(niParent.ni_iType == NT_MESHLOD);
|
|
MeshLOD *pmlod = (MeshLOD*)niParent.ni_pPtr;
|
|
// get children of mesh lod
|
|
HTREEITEM hChild = m_TreeCtrl.GetChildItem(hParent);
|
|
while(hChild!=NULL)
|
|
{
|
|
// select surface
|
|
if(!bSelect) SelectMeshSurface(hChild);
|
|
else DeselectMeshSurface(hChild);
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
}
|
|
}
|
|
|
|
// check if surface is selected
|
|
BOOL CDlgBarTreeView::IsSurfaceSelected(MeshSurface &msrf)
|
|
{
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
// check if this is selected surface
|
|
if(pmsrf == &msrf) return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// change texture for all selected surfaces
|
|
void CDlgBarTreeView::ChangeTextureOnSelectedSurfaces(CTString strControlID,CTString strNewTexID)
|
|
{
|
|
// get id of texture
|
|
INDEX iTextureID = ska_GetIDFromStringTable(strNewTexID);
|
|
// get selected surfaces count
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
// get pointer to mesh surface
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
if(pmsrf->msrf_pShader==NULL) continue;
|
|
// get surface description and find witch param has same id as control that was modified
|
|
ShaderDesc shDesc;
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX cttx = shDesc.sd_astrTextureNames.Count();
|
|
// for each texture in shader
|
|
for(INDEX itx=0;itx<cttx;itx++)
|
|
{
|
|
// if this surface has shader param that has text same as control that changed value
|
|
if(shDesc.sd_astrTextureNames[itx] == strControlID)
|
|
{
|
|
// change it
|
|
pmsrf->msrf_ShadingParams.sp_aiTextureIDs[itx] = iTextureID;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// change texture coord index for all selected surfaces
|
|
void CDlgBarTreeView::ChangeTextureCoordsOnSelectedSurfaces(CTString strControlID,INDEX iNewTexCoordsIndex)
|
|
{
|
|
// get selected surfaces count
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
// get pointer to mesh surface
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
if(pmsrf->msrf_pShader==NULL) continue;
|
|
// get surface description and find witch param has same id as control that was modified
|
|
ShaderDesc shDesc;
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX cttxc = shDesc.sd_astrTexCoordNames.Count();
|
|
// for each texture in shader
|
|
for(INDEX itxc=0;itxc<cttxc;itxc++)
|
|
{
|
|
// if this surface has shader param that has text same as control that changed value
|
|
if(shDesc.sd_astrTexCoordNames[itxc] == strControlID)
|
|
{
|
|
// change it
|
|
pmsrf->msrf_ShadingParams.sp_aiTexCoordsIndex[itxc] = iNewTexCoordsIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// change color on curently selected model instance
|
|
void CDlgBarTreeView::ChangeColorOnSelectedModel(COLOR colNewColor)
|
|
{
|
|
ASSERT(pmiSelected!=NULL);
|
|
pmiSelected->mi_colModelColor = colNewColor;
|
|
}
|
|
|
|
// change color on all selected mesh surfaces
|
|
void CDlgBarTreeView::ChangeColorOnSelectedSurfaces(CTString strControlID,COLOR colNewColor)
|
|
{
|
|
// get selected surfaces count
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++)
|
|
{
|
|
// get pointer to mesh surface
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
if(pmsrf->msrf_pShader==NULL) continue;
|
|
// get surface description and find witch param has same id as control that was modified
|
|
ShaderDesc shDesc;
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX ctcl = shDesc.sd_astrColorNames.Count();
|
|
// for each color in shader
|
|
for(INDEX icl=0;icl<ctcl;icl++)
|
|
{
|
|
// if this surface has shader param that has text same as control that changed value
|
|
if(shDesc.sd_astrColorNames[icl] == strControlID)
|
|
{
|
|
// change it
|
|
pmsrf->msrf_ShadingParams.sp_acolColors[icl] = colNewColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// change floats on all selected mesh surfaces
|
|
void CDlgBarTreeView::ChangeFloatOnSelectedSurfaces(CTString strControlID,FLOAT fNewFloat)
|
|
{
|
|
// get selected surfaces count
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++) {
|
|
// get pointer to mesh surface
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
if(pmsrf->msrf_pShader==NULL) continue;
|
|
// get surface description and find witch param has same id as control that was modified
|
|
ShaderDesc shDesc;
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX ctfl = shDesc.sd_astrFloatNames.Count();
|
|
// for each float in shader
|
|
for(INDEX ifl=0;ifl<ctfl;ifl++) {
|
|
// if this surface has shader param that has text same as control that changed value
|
|
if(shDesc.sd_astrFloatNames[ifl] == strControlID) {
|
|
// change it
|
|
pmsrf->msrf_ShadingParams.sp_afFloats[ifl] = fNewFloat;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDlgBarTreeView::ChangeFlagOnSelectedSurfaces(CTString strControlID, BOOL bChecked, INDEX iFlagIndex)
|
|
{
|
|
ULONG ulNewFlag = (1UL<<iFlagIndex);
|
|
// get selected surfaces count
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++) {
|
|
// get pointer to mesh surface
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
if(pmsrf->msrf_pShader==NULL) continue;
|
|
// get surface description and find witch param has same id as control that was modified
|
|
ShaderDesc shDesc;
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX ctfl = shDesc.sd_astrFlagNames.Count();
|
|
// for each flag in shader
|
|
for(INDEX ifl=0;ifl<ctfl;ifl++) {
|
|
// if this surface has shader param that has text same as control that changed value
|
|
if(shDesc.sd_astrFlagNames[ifl] == strControlID) {
|
|
// if now checked
|
|
if(bChecked) {
|
|
// add this flag
|
|
pmsrf->msrf_ShadingParams.sp_ulFlags |= ulNewFlag;
|
|
// if unchecked
|
|
} else {
|
|
// remove this flag
|
|
pmsrf->msrf_ShadingParams.sp_ulFlags &= ~ulNewFlag;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// change shader for all surfaces that are in selection array
|
|
void CDlgBarTreeView::ChangeShaderOnSelectedSurfaces(CTString fnNewShader)
|
|
{
|
|
#pragma message(">> Remove: Warning if usage of Double sided shader")
|
|
// TEMP
|
|
if(fnNewShader.FindSubstr("DS")!=(-1)) {
|
|
theApp.ErrorMessage("Usage of double sided shader");
|
|
}
|
|
|
|
INDEX ctsms = _aiSelectedMeshSurfaces.Count();
|
|
// for each selected mesh surfaces
|
|
for(INDEX isms=0;isms<ctsms;isms++) {
|
|
NodeInfo &ni = theApp.aNodeInfo[_aiSelectedMeshSurfaces[isms]];
|
|
ASSERT(ni.ni_iType == NT_MESHSURFACE);
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
ASSERT(pmsrf!=NULL);
|
|
try {
|
|
// try to change surface shader
|
|
ChangeSurfaceShader_t(*pmsrf,fnNewShader);
|
|
} catch(char *strErr) {
|
|
theApp.ErrorMessage(strErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// notification that item was clicked
|
|
void CDlgBarTreeView::OnItemClick(HTREEITEM hItem,HTREEITEM hLastSelected)
|
|
{
|
|
BOOL bControl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
|
|
BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
|
|
ASSERT(hItem != NULL);
|
|
NodeInfo &ni = theApp.aNodeInfo[m_TreeCtrl.GetItemData(hItem)];
|
|
if(ni.ni_iType == NT_MESHSURFACE) {
|
|
if (bShift) {
|
|
if(hLastSelected!=NULL) {
|
|
NodeInfo &niLastSelected = GetNodeInfo(hLastSelected);
|
|
if(niLastSelected.ni_iType == NT_MESHSURFACE) {
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hItem);
|
|
HTREEITEM hLastParent = m_TreeCtrl.GetParentItem(hLastSelected);
|
|
ASSERT(hParent!=NULL);
|
|
ASSERT(hLastParent!=NULL);
|
|
if(hParent==hLastParent) {
|
|
// deselect all items
|
|
if(!bControl) DeSelectAllSurfaces();
|
|
// get first child
|
|
HTREEITEM hChild = m_TreeCtrl.GetChildItem(hParent);
|
|
// find first item or last selected item
|
|
while((hChild!=hItem)&&(hChild!=hLastSelected)) {
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
ASSERT(hChild!=NULL);
|
|
}
|
|
// select first item
|
|
SelectMeshSurface(hChild);
|
|
if(hItem!=hLastSelected) hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
// select all items until item or last selected item
|
|
while((hChild!=hItem)&&(hChild!=hLastSelected)) {
|
|
SelectMeshSurface(hChild);
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
ASSERT(hChild!=NULL);
|
|
}
|
|
SelectMeshSurface(hChild);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if(bControl) {
|
|
// select curent surface
|
|
TogleSurfaceSelection(hItem);
|
|
return;
|
|
}
|
|
// deselect all items
|
|
DeSelectAllSurfaces();
|
|
// select curent surface
|
|
SelectMeshSurface(hItem);
|
|
}
|
|
}
|
|
|
|
// notification that item icons was clicked
|
|
void CDlgBarTreeView::OnItemIconClick(HTREEITEM hItem)
|
|
{
|
|
NodeInfo &ni = GetNodeInfo(hItem);
|
|
if(ni.ni_iType == NT_MESHSURFACE) {
|
|
TogleSurfaceSelection(hItem);
|
|
}
|
|
}
|
|
|
|
// show shader for surface
|
|
void CDlgBarTreeView::ShowSurfaceShader(MeshSurface *pmsrf,MeshLOD *pmlod,MeshInstance *pmshi)
|
|
{
|
|
ASSERT(pmsrf!=NULL);
|
|
ASSERT(pmlod!=NULL);
|
|
ASSERT(pmshi!=NULL);
|
|
|
|
// remember vertical scroll pos
|
|
INDEX ivScroll = m_dlgShader.GetScrollPos(SB_VERT);
|
|
// set scroll to 0
|
|
m_dlgShader.SetScrollPos(SB_VERT,0);
|
|
VScrollControls(&m_dlgShader);
|
|
// clear shader dlg
|
|
RemoveDialogControls(&m_dlgShader);
|
|
CComboBox *cbShader = ((CComboBox*)m_dlgShader.GetDlgItem(IDC_CB_SHADER));
|
|
|
|
_atxcTexControls.Clear();
|
|
_atxccTexCoordControls.Clear();
|
|
_accColors.Clear();
|
|
_afcFloatControls.Clear();
|
|
_afcFlagControls.Clear();
|
|
iCustomControlID=FIRSTSHADEID;
|
|
|
|
ShaderDesc shDesc;
|
|
|
|
INDEX ctTextures = 0;
|
|
INDEX ctTexCoords = 0;
|
|
INDEX ctColors = 0;
|
|
INDEX ctFloats = 0;
|
|
INDEX ctFlags = 0;
|
|
|
|
// if surface has shader
|
|
if(pmsrf->msrf_pShader!=NULL) {
|
|
pmsrf->msrf_pShader->GetShaderDesc(shDesc);
|
|
ctTextures = shDesc.sd_astrTextureNames.Count();
|
|
ctTexCoords = shDesc.sd_astrTexCoordNames.Count();
|
|
ctColors = shDesc.sd_astrColorNames.Count();
|
|
ctFloats = shDesc.sd_astrFloatNames.Count();
|
|
ctFlags = shDesc.sd_astrFlagNames.Count();
|
|
// select shader in combo box
|
|
CTFileName fnShader = pmsrf->msrf_pShader->GetName();
|
|
CTString strShader = fnShader.FileName();
|
|
ASSERT(cbShader!=NULL);
|
|
if(cbShader->SelectString(-1,CString(strShader)) == CB_ERR) {
|
|
// error: shader is not found in list of shaders
|
|
return;
|
|
}
|
|
ShaderParams &mspParams = pmsrf->msrf_ShadingParams;
|
|
|
|
// ASSERT(pmsrf->msrf_ShadingParams.sp_acolColors.Count() == ctColors);
|
|
|
|
_atxcTexControls.New(ctTextures);
|
|
_atxccTexCoordControls.New(ctTexCoords);
|
|
_accColors.New(ctColors);
|
|
_afcFloatControls.New(ctFloats);
|
|
_afcFlagControls.New(ctFlags);
|
|
|
|
// add texture controls to shader dialog
|
|
for(INDEX itx=0;itx<ctTextures;itx++) {
|
|
CTextureControl &txc = _atxcTexControls[itx];
|
|
txc.AddControl(shDesc.sd_astrTextureNames[itx],&pmsrf->msrf_ShadingParams.sp_aiTextureIDs[itx]);
|
|
// count texture instances
|
|
INDEX ctti=pmshi->mi_tiTextures.Count();
|
|
// for each texture instances
|
|
for(INDEX iti=0;iti<ctti;iti++) {
|
|
TextureInstance &ti = pmshi->mi_tiTextures[iti];
|
|
CTString strTexName = ska_GetStringFromTable(ti.GetID());
|
|
txc.txc_Combo.AddString(CString(strTexName));
|
|
}
|
|
INDEX iSelectTexID = mspParams.sp_aiTextureIDs[itx];
|
|
CTString strSelectTexID = ska_GetStringFromTable(iSelectTexID);
|
|
int iItemIndex = txc.txc_Combo.FindStringExact(-1,CString(strSelectTexID));
|
|
if(iItemIndex!=CB_ERR) txc.txc_Combo.SetCurSel(iItemIndex);
|
|
}
|
|
// add texcoord controls to shader dialog
|
|
for(INDEX itxc=0;itxc<ctTexCoords;itxc++) {
|
|
CTexCoordControl &txcc = _atxccTexCoordControls[itxc];
|
|
txcc.AddControl(shDesc.sd_astrTexCoordNames[itxc],&pmsrf->msrf_ShadingParams.sp_aiTexCoordsIndex[itxc]);
|
|
// count uvmaps
|
|
INDEX ctuv = pmlod->mlod_aUVMaps.Count();
|
|
// for each uvmap in lod
|
|
for(INDEX iuv=0;iuv<ctuv;iuv++) {
|
|
// add uvmap name in combo box
|
|
MeshUVMap &uvm = pmlod->mlod_aUVMaps[iuv];
|
|
CTString strUVMapName = ska_GetStringFromTable(uvm.muv_iID);
|
|
txcc.txcc_Combo.AddString(CString(strUVMapName));
|
|
}
|
|
|
|
INDEX iSelectTexCoordsIndex = mspParams.sp_aiTexCoordsIndex[itxc];
|
|
txcc.txcc_Combo.SetCurSel(iSelectTexCoordsIndex);
|
|
}
|
|
// add color controls to shader dialog
|
|
for(INDEX icc=0;icc<ctColors;icc++) {
|
|
CColorControl &cc = _accColors[icc];
|
|
cc.AddControl(shDesc.sd_astrColorNames[icc],&pmsrf->msrf_ShadingParams.sp_acolColors[icc]);
|
|
}
|
|
// add float controls to shader dialog
|
|
INDEX ifc=0;
|
|
for(;ifc<ctFloats;ifc++) {
|
|
CFloatControl &fc = _afcFloatControls[ifc];
|
|
fc.AddControl(shDesc.sd_astrFloatNames[ifc],&pmsrf->msrf_ShadingParams.sp_afFloats[ifc]);
|
|
}
|
|
// add flag controls to shader dialog
|
|
for(ifc=0;ifc<ctFlags;ifc++) {
|
|
CFlagControl &fc = _afcFlagControls[ifc];
|
|
fc.AddControl(shDesc.sd_astrFlagNames[ifc],ifc,mspParams.sp_ulFlags);
|
|
}
|
|
} else {
|
|
// clear text from combo box
|
|
cbShader->SetCurSel(-1);
|
|
}
|
|
|
|
|
|
CRect rcDlg;
|
|
m_dlgShader.GetWindowRect(rcDlg);
|
|
|
|
INDEX iCtrlCount = iCustomControlID-FIRSTSHADEID;
|
|
INDEX iDlgHeight = (rcDlg.bottom-rcDlg.top-15);
|
|
|
|
if(iDlgHeight<YPOS) m_dlgShader.SetScrollRange(SB_VERT,1,YPOS-iDlgHeight);
|
|
else m_dlgShader.SetScrollRange(SB_VERT,0,0);
|
|
|
|
AddDialogControls(&m_dlgShader);
|
|
// return old vertical scroll pos
|
|
m_dlgShader.SetScrollPos(SB_VERT,ivScroll);
|
|
VScrollControls(&m_dlgShader);
|
|
|
|
//m_dlgShader.Invalidate(FALSE);
|
|
}
|
|
|
|
void CDlgBarTreeView::VScrollControls(CDialog *pDlg)
|
|
{
|
|
//pDlg->SetRedraw(FALSE);
|
|
int iPosition = pDlg->GetScrollPos(SB_VERT);
|
|
// GetScrollPos returns values from 1 to n
|
|
if(iPosition>0) iPosition--;
|
|
INDEX ctctrl = dlg_aControls.Count();
|
|
// for each control in array of contrls
|
|
for(INDEX ictrl=0;ictrl<ctctrl;ictrl++) {
|
|
Control &ctrl = dlg_aControls[ictrl];
|
|
// check if its dialog is being scrolled
|
|
if(ctrl.ct_pParentDlg == pDlg) {
|
|
// move control
|
|
CRect rcCtrl;
|
|
pDlg->GetDlgItem(ctrl.ct_iID)->GetWindowRect(rcCtrl);
|
|
pDlg->ScreenToClient(rcCtrl);
|
|
rcCtrl.top = ctrl.ct_iTop - iPosition;
|
|
rcCtrl.bottom = ctrl.ct_iBottom - iPosition;
|
|
pDlg->GetDlgItem(ctrl.ct_iID)->MoveWindow(rcCtrl);
|
|
}
|
|
}
|
|
// pDlg->SetRedraw(TRUE);
|
|
// pDlg->Invalidate(TRUE);
|
|
}
|
|
|
|
// notification that selected item has changed
|
|
void CDlgBarTreeView::SelItemChanged(HTREEITEM hSelected)
|
|
{
|
|
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
|
|
BOOL bCtrl = (GetKeyState( VK_CONTROL)&0x8000) != 0;
|
|
BOOL bShift = (GetKeyState( VK_SHIFT)&0x8000) != 0;
|
|
BOOL bAlt = (GetKeyState( VK_MENU)&0x8000) != 0;
|
|
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
// reset selected bone in treeview
|
|
theApp.iSelectedBoneID = -1;
|
|
// if no item selected
|
|
if(hSelected == NULL) {
|
|
pmiSelected = NULL;
|
|
ResetControls();
|
|
}
|
|
// get index in node array of selected item
|
|
INDEX iSelIndex = m_TreeCtrl.GetItemData(hSelected);
|
|
// get node info of selected item
|
|
NodeInfo &ni = theApp.aNodeInfo[iSelIndex];
|
|
// get model instance that holds selected item
|
|
pmiSelected = ni.pmi;
|
|
// if selected item is model instance set it to be selected model instance
|
|
if(ni.ni_iType == NT_MODELINSTANCE) pmiSelected = (CModelInstance*)ni.ni_pPtr;
|
|
|
|
if(pmiSelected!=NULL) {
|
|
CTString strStretch = CTString(0,"%g",pmiSelected->mi_vStretch(1));
|
|
pMainFrame->m_ctrlMIStretch.SetWindowText(CString(strStretch));
|
|
}
|
|
// get parent of selected item
|
|
HTREEITEM hParent = m_TreeCtrl.GetParentItem(hSelected);
|
|
INDEX iParent=-1;
|
|
// if parent exists get ist index
|
|
if(hParent != NULL) iParent = m_TreeCtrl.GetItemData(hParent);
|
|
// get parent model isntance of selected model instance
|
|
CModelInstance *pmiParent = pmiSelected->GetParent(pDoc->m_ModelInstance);
|
|
// if parent exisits fill combo box with parent bones
|
|
if(pmiParent != NULL) {
|
|
// fill combo box with parent bones
|
|
if(pmiParent->mi_psklSkeleton != NULL) FillBonesToComboBox(pmiParent->mi_psklSkeleton,0);
|
|
// clear combo box for parent bones
|
|
else ((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->ResetContent();
|
|
} else {
|
|
// clear combo box for parent bones
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->ResetContent();
|
|
}
|
|
// get name of parent bone
|
|
CTString strBoneName = ska_GetStringFromTable(pmiSelected->mi_iParentBoneID);
|
|
// select parent bone in combo box
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->SelectString(-1,CString(strBoneName));
|
|
|
|
// select parent model instance in combo box
|
|
CComboBox *cbParentList = ((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTMODEL));
|
|
// count items in combo box
|
|
INDEX ctpl = cbParentList->GetCount();
|
|
// for each item in combo box
|
|
for(INDEX ipl=0;ipl<ctpl;ipl++) {
|
|
CModelInstance *pmiParentInList = (CModelInstance*)cbParentList->GetItemDataPtr(ipl);
|
|
// chech if this item is parent in current selected mi
|
|
if(pmiParentInList == pmiParent) {
|
|
cbParentList->SetCurSel(ipl);
|
|
break;
|
|
}
|
|
cbParentList->SetCurSel(-1);
|
|
}
|
|
|
|
// switch type of selected item
|
|
switch(ni.ni_iType)
|
|
{
|
|
case NT_MODELINSTANCE:
|
|
{
|
|
ShowControlGroup(GR_PARENT);
|
|
CModelInstance *pmi = (CModelInstance*)ni.ni_pPtr;
|
|
m_tbMiName.SetWindowText(CString(pmi->GetName()));
|
|
}
|
|
break;
|
|
case NT_ANIMSET:
|
|
case NT_MESHLODLIST:
|
|
case NT_SKELETONLODLIST:
|
|
ShowControlGroup(GR_LISTOPTIONS);
|
|
break;
|
|
case NT_TEXINSTANCE:
|
|
{
|
|
TextureInstance *pti = (TextureInstance*)ni.ni_pPtr;
|
|
CTString strTexName = ska_GetStringFromTable(pti->GetID());
|
|
m_tbTextureName.SetWindowText(CString(strTexName));
|
|
m_tvTexView.ChangeTexture(pti->ti_toTexture.GetName());
|
|
ShowControlGroup(GR_TEXTURE);
|
|
}
|
|
break;
|
|
case NT_MESHLOD:
|
|
{
|
|
MeshLOD *pmlod = (MeshLOD*)ni.ni_pPtr;
|
|
CTString strName;
|
|
strName.PrintF("%g",pmlod->mlod_fMaxDistance);
|
|
m_tbDistance.SetWindowText(CString(strName));
|
|
// set this mesh lod as forced lod
|
|
pDoc->fCustomMeshLodDist=pmlod->mlod_fMaxDistance-0.01f;
|
|
ShowControlGroup(GR_LOD);
|
|
SetCustomTabText(L"Mesh lod");
|
|
}
|
|
break;
|
|
case NT_SKELETONLOD:
|
|
{
|
|
SkeletonLOD *pslod = (SkeletonLOD*)ni.ni_pPtr;
|
|
CTString strName = CTString(0,"%g",pslod->slod_fMaxDistance);
|
|
m_tbDistance.SetWindowText(CString(strName));
|
|
// set this skleleton lod as forced lod
|
|
pDoc->fCustomSkeletonLodDist=pslod->slod_fMaxDistance-0.01f;
|
|
ShowControlGroup(GR_LOD);
|
|
SetCustomTabText(L"Skeleton lod");
|
|
}
|
|
break;
|
|
case NT_BONE:
|
|
{
|
|
SkeletonBone *pbone = (SkeletonBone*)ni.ni_pPtr;
|
|
theApp.iSelectedBoneID = pbone->sb_iID;
|
|
ShowControlGroup(GR_BONE);
|
|
}
|
|
break;
|
|
case NT_ANIMATION:
|
|
{
|
|
Animation *pan = (Animation*)ni.ni_pPtr;
|
|
// start playing selected animation
|
|
ULONG ulAnimFlags = 0;// | AN_NORESTART;
|
|
|
|
// if looping animations
|
|
if(pDoc->bAnimLoop) {
|
|
// if shift is not presed
|
|
if(!bShift) {
|
|
// loop animations
|
|
ulAnimFlags |= AN_LOOPING;
|
|
}
|
|
// if not looping and shift pressed
|
|
} else if(bShift) {
|
|
// loop anims
|
|
ulAnimFlags |= AN_LOOPING;
|
|
}
|
|
|
|
// if control is presed
|
|
if(bCtrl) {
|
|
// Add animation
|
|
pmiSelected->AddAnimation(pan->an_iID,ulAnimFlags|AN_CLONE,1.0f,0);
|
|
// if alt is presed
|
|
} else if(bAlt) {
|
|
// do new cloned state
|
|
pmiSelected->NewClonedState(0.2f);
|
|
// Add animation
|
|
pmiSelected->RemAnimation(pan->an_iID);
|
|
} else {
|
|
// Add animation
|
|
pmiSelected->AddAnimation(pan->an_iID,ulAnimFlags|AN_CLEAR,1,0);
|
|
}
|
|
|
|
// Set timer for current document
|
|
pDoc->SetTimerForDocument();
|
|
CTString strTreshold;
|
|
CTString strSecPerFrame;
|
|
CTString strZSpeed;
|
|
CTString strLoopSec;
|
|
strTreshold.PrintF("%g",pan->an_fTreshold);
|
|
strSecPerFrame.PrintF("%g",pan->an_fSecPerFrame);
|
|
strZSpeed.PrintF("%g",pDoc->m_fSpeedZ);
|
|
strLoopSec.PrintF("%g",pDoc->m_fLoopSecends);
|
|
m_tbTreshold.SetWindowText(CString(strTreshold));
|
|
m_tbAnimSpeed.SetWindowText(CString(strSecPerFrame));
|
|
m_tbWalkSpeed.SetWindowText(CString(strZSpeed));
|
|
m_tbWalkLoopSec.SetWindowText(CString(strLoopSec));
|
|
// check compresion
|
|
((CButton*)m_dlgAnimSet.GetDlgItem(IDC_CB_COMPRESION))->SetCheck(pan->an_bCompresed);
|
|
CheckSecPerFrameCtrl(pan->an_bCustomSpeed);
|
|
ShowControlGroup(GR_ANIMSET);
|
|
SetCustomTabText(L"Animation");
|
|
}
|
|
break;
|
|
case NT_MESHSURFACE:
|
|
{
|
|
// get mesh instance
|
|
HTREEITEM hParentsParent = m_TreeCtrl.GetParentItem(hParent);
|
|
NodeInfo &niParent = GetNodeInfo(hParent);
|
|
NodeInfo &niParentsParent = GetNodeInfo(hParentsParent);
|
|
|
|
MeshSurface *pmsrf = (MeshSurface*)ni.ni_pPtr;
|
|
MeshLOD *pmlod = (MeshLOD*)niParent.ni_pPtr;
|
|
MeshInstance *pmshi = (MeshInstance*)niParentsParent.ni_pPtr;
|
|
|
|
ShowControlGroup(GR_SHADERS);
|
|
ShowSurfaceShader(pmsrf,pmlod,pmshi);
|
|
}
|
|
break;
|
|
case NT_COLISIONBOX:
|
|
{
|
|
ColisionBox *pcb = (ColisionBox*)ni.ni_pPtr;
|
|
INDEX iIndex = -1;
|
|
// get colision box count
|
|
INDEX ctcb = pmiSelected->mi_cbAABox.Count();
|
|
// for each colision box in array
|
|
for(INDEX icb=0;icb<ctcb;icb++) {
|
|
ColisionBox *pcb2 = &pmiSelected->mi_cbAABox[icb];
|
|
if(pcb == pcb2) {
|
|
iIndex = icb;
|
|
break;
|
|
}
|
|
}
|
|
if(iIndex<0) return;
|
|
// set it to be curent colision box
|
|
pmiSelected->mi_iCurentBBox = iIndex;
|
|
ShowControlGroup(GR_COLISION);
|
|
SetCustomTabText(L"Colision");
|
|
}
|
|
break;
|
|
case NT_ALLFRAMESBBOX:
|
|
{
|
|
ShowControlGroup(GR_ALLFRAMES_BBOX);
|
|
SetCustomTabText(L"All frames");
|
|
}
|
|
break;
|
|
default:
|
|
// no custom group
|
|
//iShowCustomGroup = -1;
|
|
ShowControlGroup(-1);
|
|
SetCustomTabText(L"Custom");
|
|
break;
|
|
}
|
|
|
|
// show name of selected model instance
|
|
GetDlgItem(IDC_SELECTEDMI)->SetWindowText(CString(pmiSelected->GetName()));
|
|
|
|
// show offset of model instance
|
|
FLOATmatrix3D mat;
|
|
FLOAT3D vPos = pmiSelected->mi_qvOffset.vPos;
|
|
ANGLE3D aRot;
|
|
pmiSelected->mi_qvOffset.qRot.ToMatrix(mat);
|
|
DecomposeRotationMatrix(aRot,mat);
|
|
|
|
m_tbOffPosX.SetWindowText(CString(CTString(0,"%g",vPos(1))));
|
|
m_tbOffPosY.SetWindowText(CString(CTString(0,"%g",vPos(2))));
|
|
m_tbOffPosZ.SetWindowText(CString(CTString(0,"%g",vPos(3))));
|
|
m_tbOffRotH.SetWindowText(CString(CTString(0,"%g",aRot(1))));
|
|
m_tbOffRotP.SetWindowText(CString(CTString(0,"%g",aRot(2))));
|
|
m_tbOffRotB.SetWindowText(CString(CTString(0,"%g",aRot(3))));
|
|
|
|
// show collision box values
|
|
if((pmiSelected->mi_iCurentBBox >= 0) && (pmiSelected->mi_iCurentBBox < pmiSelected->mi_cbAABox.Count()))
|
|
{
|
|
ColisionBox &cb = pmiSelected->mi_cbAABox[pmiSelected->mi_iCurentBBox];
|
|
FLOAT fWidth = (cb.Max()(1)-cb.Min()(1));
|
|
FLOAT fHeight = (cb.Max()(2)-cb.Min()(2));
|
|
FLOAT fLength = (cb.Max()(3)-cb.Min()(3));
|
|
FLOAT fPosX = (cb.Max()(1)+cb.Min()(1)) / 2;
|
|
FLOAT fPosY = (cb.Max()(2)+cb.Min()(2)) / 2;
|
|
FLOAT fPosZ = (cb.Max()(3)+cb.Min()(3)) / 2;
|
|
fPosY -= fHeight/2;
|
|
m_tbColName.SetWindowText( CString(cb.GetName()));
|
|
m_tbColWidth.SetWindowText( CString(CTString(0,"%g",fWidth)));
|
|
m_tbColHeight.SetWindowText(CString(CTString(0,"%g",fHeight)));
|
|
m_tbColLength.SetWindowText(CString(CTString(0,"%g",fLength)));
|
|
m_tbColPosX.SetWindowText( CString(CTString(0,"%g",fPosX)));
|
|
m_tbColPosY.SetWindowText( CString(CTString(0,"%g",fPosY)));
|
|
m_tbColPosZ.SetWindowText( CString(CTString(0,"%g",fPosZ)));
|
|
}
|
|
// show all frames bbox
|
|
ColisionBox &cb = pmiSelected->mi_cbAllFramesBBox;
|
|
FLOAT fWidth = (cb.Max()(1)-cb.Min()(1));
|
|
FLOAT fHeight = (cb.Max()(2)-cb.Min()(2));
|
|
FLOAT fLength = (cb.Max()(3)-cb.Min()(3));
|
|
FLOAT fPosX = (cb.Max()(1)+cb.Min()(1)) / 2;
|
|
FLOAT fPosY = (cb.Max()(2)+cb.Min()(2)) / 2;
|
|
FLOAT fPosZ = (cb.Max()(3)+cb.Min()(3)) / 2;
|
|
fPosY -= fHeight/2;
|
|
m_tbAFBBWidth.SetWindowText( CString(CTString(0,"%g",fWidth)));
|
|
m_tbAFBBHeight.SetWindowText(CString(CTString(0,"%g",fHeight)));
|
|
m_tbAFBBLength.SetWindowText(CString(CTString(0,"%g",fLength)));
|
|
m_tbAFBBPosX.SetWindowText( CString(CTString(0,"%g",fPosX)));
|
|
m_tbAFBBPosY.SetWindowText( CString(CTString(0,"%g",fPosY)));
|
|
m_tbAFBBPosZ.SetWindowText( CString(CTString(0,"%g",fPosZ)));
|
|
// change custom controls visibility
|
|
// ShowControlGroup(iVisibleGroup);
|
|
}
|
|
|
|
// calculate size of tree view
|
|
CSize CDlgBarTreeView::CalcLayout(int nLength, DWORD nMode)
|
|
{
|
|
CSize csResult;
|
|
// Return default if it is being docked or floated
|
|
if(nMode & LM_VERTDOCK)
|
|
{
|
|
csResult = m_Size;
|
|
CRect rc;
|
|
// get main frm
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
// get his child
|
|
CMDIClientWnd *pMDIClient = &pMainFrame->m_wndMDIClient;
|
|
pMDIClient->GetWindowRect(rc);
|
|
csResult.cy = rc.bottom - rc.top;
|
|
}
|
|
else if((nMode & LM_VERTDOCK) || (nMode & LM_HORZDOCK))
|
|
{
|
|
if (nMode & LM_STRETCH) // if not docked stretch to fit
|
|
{
|
|
csResult = CSize((nMode & LM_HORZ) ? 32767 : m_Size.cx,
|
|
(nMode & LM_HORZ) ? m_Size.cy : 32767);
|
|
}
|
|
else
|
|
{
|
|
csResult = m_Size;
|
|
}
|
|
}
|
|
else if (nMode & LM_MRUWIDTH)
|
|
{
|
|
csResult = m_Size;
|
|
}
|
|
// In all other cases, accept the dynamic length
|
|
else
|
|
{
|
|
if (nMode & LM_LENGTHY)
|
|
{
|
|
// Note that we don't change m_Size.cy because we disabled vertical sizing
|
|
csResult = CSize( m_Size.cx, m_Size.cy = nLength);
|
|
}
|
|
else
|
|
{
|
|
csResult = CSize( m_Size.cx = nLength, m_Size.cy);
|
|
}
|
|
}
|
|
// csResult = CSize(300,300);
|
|
return csResult;
|
|
}
|
|
|
|
// resize dialog
|
|
CSize CDlgBarTreeView::CalcDynamicLayout(int nLength, DWORD nMode)
|
|
{
|
|
// return CDlgTemplate::CalcDynamicLayout(nLength, nMode);
|
|
CSize csResult = CalcLayout(nLength,nMode);
|
|
if(theApp.IsErrorDlgVisible()) {
|
|
csResult.cy+=theApp.GetLogDlgSize().cy;
|
|
}
|
|
|
|
#define H_BORDER 20
|
|
#define V_BORDER 10
|
|
#define LINE1 15
|
|
#define LINE2 35
|
|
#define LINE3 55
|
|
#define LINE1U 5
|
|
#define LINE2U 25
|
|
#define LINE3U 45
|
|
#define LINE4U 65
|
|
|
|
#define WIT (csResult.cx-2*H_BORDER)/4
|
|
#define YOFFSET csResult.cy - V_BORDER - 140
|
|
// move tab control
|
|
GetDlgItem(IDC_MODE_SELECT_TAB)->MoveWindow(CRect(H_BORDER/2,YOFFSET-30,csResult.cx-H_BORDER/2,YOFFSET + 140));
|
|
// move dialogs
|
|
CRect rcDlg = CRect(2,6,csResult.cx-H_BORDER/2-13,165); // !!! fix
|
|
ResizeDlgWithChildren(&m_dlgParent,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgAnimSet,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgColision,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgAllFrames,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgLod,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgBone,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgTexture,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgListOpt,rcDlg);
|
|
ResizeDlgWithChildren(&m_dlgShader,rcDlg);
|
|
|
|
AdjustSplitter();
|
|
|
|
/*
|
|
if(iDockSide == AFX_IDW_DOCKBAR_LEFT)
|
|
{
|
|
GetDlgItem(IDC_SPLITER_FRAME)->MoveWindow(CRect(csResult.cx-SPLITTER_WITDH,0,csResult.cx,csResult.cy));
|
|
GetDlgItem(IDC_SPLITER_FRAME)->ShowWindow(SW_SHOW);
|
|
}
|
|
else if(iDockSide == AFX_IDW_DOCKBAR_RIGHT)
|
|
{
|
|
GetDlgItem(IDC_SPLITER_FRAME)->MoveWindow(CRect(0,0,SPLITTER_WITDH,csResult.cy));
|
|
GetDlgItem(IDC_SPLITER_FRAME)->ShowWindow(SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
GetDlgItem(IDC_SPLITER_FRAME)->ShowWindow(SW_HIDE);
|
|
}
|
|
*/
|
|
|
|
// move label that display curent selected mi
|
|
GetDlgItem(IDC_SELECTEDMI)->MoveWindow(CRect(H_BORDER ,3,csResult.cx-H_BORDER,V_BORDER + 15));
|
|
// move tree ctrl
|
|
CRect NewTreePos;
|
|
NewTreePos = CRect(H_BORDER/2, V_BORDER + 15, csResult.cx - H_BORDER/2, csResult.cy - V_BORDER - 180);
|
|
CWnd *pwndTree = GetDlgItem(IDC_TREE1);
|
|
pwndTree->MoveWindow(NewTreePos);
|
|
pwndTree->UpdateWindow();
|
|
UpdateWindow();
|
|
return csResult;
|
|
}
|
|
|
|
void CDlgBarTreeView::ResizeDlgWithChildren(CDialog *pDlg,CRect rcDlg)
|
|
{
|
|
INDEX iDlgWidth = rcDlg.right - rcDlg.left;
|
|
INDEX ctctrl = dlg_aControls.Count();
|
|
// for each control in array of contrls
|
|
for(INDEX ictrl=0;ictrl<ctctrl;ictrl++)
|
|
{
|
|
Control &ctrl = dlg_aControls[ictrl];
|
|
// check if its dialog is being resized
|
|
if(ctrl.ct_pParentDlg == pDlg)
|
|
{
|
|
// resize control
|
|
CRect rcCtrl;
|
|
rcCtrl.left = iDlgWidth * ctrl.ct_fLeft;
|
|
rcCtrl.right = iDlgWidth * ctrl.ct_fRight;
|
|
rcCtrl.top = ctrl.ct_iTop;
|
|
rcCtrl.bottom = ctrl.ct_iBottom;
|
|
pDlg->GetDlgItem(ctrl.ct_iID)->MoveWindow(rcCtrl);
|
|
}
|
|
}
|
|
// resize dialog
|
|
pDlg->MoveWindow(rcDlg);
|
|
}
|
|
|
|
// remove control form array
|
|
void CDlgBarTreeView::RemoveControlFromArray(CWnd *pChild, CDialog *pDlg)
|
|
{
|
|
// get control ID
|
|
INDEX ictrlID = pChild->GetDlgCtrlID();
|
|
// count controls in array
|
|
INDEX ctctrl = dlg_aControls.Count();
|
|
// for each control in array
|
|
for(INDEX ictrl=0;ictrl<ctctrl;ictrl++) {
|
|
Control &ctrl = dlg_aControls[ictrl];
|
|
// check if this is control to remove
|
|
if((ctrl.ct_iID == ictrlID) && (ctrl.ct_pParentDlg == pDlg)) {
|
|
// get last ctrl
|
|
Control &ctrlLast = dlg_aControls[ctctrl-1];
|
|
// copy last control insted of one that has to be removed
|
|
ctrl = ctrlLast;
|
|
// remove last control from array
|
|
dlg_aControls.Pop();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// add control to array witch stores all controls that need to be dynamicly resized
|
|
void CDlgBarTreeView::AddControlToArray(CWnd *pChild, CDialog *pDlg)
|
|
{
|
|
CRect rcParent;
|
|
CRect rcChild;
|
|
|
|
pDlg->GetWindowRect(rcParent);
|
|
pChild->GetWindowRect(rcChild);
|
|
|
|
INDEX iParentWidth = rcParent.right - rcParent.left;
|
|
// convert to parent coords
|
|
pDlg->ScreenToClient(rcChild);
|
|
|
|
Control &ctrl = dlg_aControls.Push();
|
|
ctrl.ct_iID = pChild->GetDlgCtrlID();
|
|
ctrl.ct_pParentDlg = pDlg;
|
|
ctrl.ct_iTop = rcChild.top;
|
|
ctrl.ct_iBottom = rcChild.bottom;
|
|
ctrl.ct_fLeft = ((FLOAT)rcChild.left/(FLOAT)iParentWidth);
|
|
ctrl.ct_fRight = ((FLOAT)rcChild.right/(FLOAT)iParentWidth);
|
|
}
|
|
|
|
// remove controls from array
|
|
void CDlgBarTreeView::RemoveDialogControls(CDialog *pDlg)
|
|
{
|
|
CWnd *pChild = pDlg->GetWindow(GW_CHILD);
|
|
while(pChild!=NULL) {
|
|
RemoveControlFromArray(pChild,pDlg);
|
|
pChild = pChild->GetWindow(GW_HWNDNEXT);
|
|
}
|
|
}
|
|
|
|
// add all controls from dialog to array
|
|
void CDlgBarTreeView::AddDialogControls(CDialog *pDlg)
|
|
{
|
|
CWnd *pChild = pDlg->GetWindow(GW_CHILD);
|
|
while(pChild!=NULL) {
|
|
AddControlToArray(pChild,pDlg);
|
|
pChild = pChild->GetWindow(GW_HWNDNEXT);
|
|
}
|
|
}
|
|
|
|
// create dialog
|
|
BOOL CDlgBarTreeView::Create( CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID)
|
|
{
|
|
CRect rectDummy(0,0,0,0);
|
|
if(!CDlgTemplate::Create(pParentWnd,nIDTemplate,nStyle,nID)) return FALSE;
|
|
m_Size = m_sizeDefault;
|
|
SetSplitterControlID(IDC_SPLITTER_TREE);
|
|
// spliter
|
|
// m_wndSpliterFrame.SubclassDlgItem(IDC_SPLITTER_TREE,this);
|
|
// m_wndSpliterFrame.SetDockingSide(AFX_IDW_DOCKBAR_FLOAT);
|
|
|
|
// tree ctrl
|
|
m_IconsImageList.Create( IDB_BITMAP1, 16, 32, CLR_NONE);
|
|
m_TreeCtrl.SubclassDlgItem(IDC_TREE1, this);
|
|
m_TreeCtrl.SetImageList( &m_IconsImageList, TVSIL_NORMAL);
|
|
// add tab control buttons
|
|
CTabCtrl *pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_MODE_SELECT_TAB);
|
|
|
|
// create dialogs
|
|
m_dlgParent.Create(IDD_PARENT,pTabCtrl);
|
|
m_dlgAnimSet.Create(IDD_ANIMSET,pTabCtrl);
|
|
m_dlgColision.Create(IDD_COLISION,pTabCtrl);
|
|
m_dlgAllFrames.Create(IDD_ALL_FRAMES_BBOX,pTabCtrl);
|
|
m_dlgLod.Create(IDD_LOD,pTabCtrl);
|
|
m_dlgBone.Create(IDD_BONE,pTabCtrl);
|
|
m_dlgTexture.Create(IDD_TEXTURE,pTabCtrl);
|
|
m_dlgListOpt.Create(IDD_LIST_OPTIONS,pTabCtrl);
|
|
m_dlgShader.Create(IDD_SHADER,pTabCtrl);
|
|
|
|
|
|
CRect rcDummy = CRect(0,0,100,20);
|
|
|
|
AddDialogControls(&m_dlgTexture);
|
|
AddDialogControls(&m_dlgListOpt);
|
|
AddDialogControls(&m_dlgParent);
|
|
AddDialogControls(&m_dlgAnimSet);
|
|
AddDialogControls(&m_dlgColision);
|
|
AddDialogControls(&m_dlgAllFrames);
|
|
AddDialogControls(&m_dlgLod);
|
|
AddDialogControls(&m_dlgBone);
|
|
AddDialogControls(&m_dlgShader);
|
|
|
|
// subclass controls in parent dialog
|
|
m_tbOffPosX.SubclassDlgItem(IDC_TB_OFFSET_POSX, &m_dlgParent);
|
|
m_tbOffPosY.SubclassDlgItem(IDC_TB_OFFSET_POSY, &m_dlgParent);
|
|
m_tbOffPosZ.SubclassDlgItem(IDC_TB_OFFSET_POSZ, &m_dlgParent);
|
|
m_tbOffRotH.SubclassDlgItem(IDC_TB_OFFSET_ROTH, &m_dlgParent);
|
|
m_tbOffRotP.SubclassDlgItem(IDC_TB_OFFSET_ROTP, &m_dlgParent);
|
|
m_tbOffRotB.SubclassDlgItem(IDC_TB_OFFSET_ROTB, &m_dlgParent);
|
|
m_tbMiName.SubclassDlgItem(IDC_TB_MI_NAME, &m_dlgParent);
|
|
|
|
// subclass controls in animset dialog
|
|
m_tbTreshold.SubclassDlgItem(IDC_EB_TRESHOLD ,&m_dlgAnimSet);
|
|
m_tbAnimSpeed.SubclassDlgItem(IDC_EB_SECPERFRAME,&m_dlgAnimSet);
|
|
m_tbWalkSpeed.SubclassDlgItem(IDC_TB_ZTRANSSPEED,&m_dlgAnimSet);
|
|
m_tbWalkLoopSec.SubclassDlgItem(IDC_TB_ZTRANSLOOP,&m_dlgAnimSet);
|
|
// subclass controls in colision dialog
|
|
m_tbColName.SubclassDlgItem(IDC_TB_COLNAME, &m_dlgColision);
|
|
m_tbColWidth.SubclassDlgItem(IDC_TB_COLWIDTH, &m_dlgColision);
|
|
m_tbColHeight.SubclassDlgItem(IDC_TB_COLHEIGHT,&m_dlgColision);
|
|
m_tbColLength.SubclassDlgItem(IDC_TB_COLLENGTH,&m_dlgColision);
|
|
m_tbColPosX.SubclassDlgItem(IDC_TB_COLPOSX, &m_dlgColision);
|
|
m_tbColPosY.SubclassDlgItem(IDC_TB_COLPOSY, &m_dlgColision);
|
|
m_tbColPosZ.SubclassDlgItem(IDC_TB_COLPOSZ, &m_dlgColision);
|
|
|
|
// subclass controls in colision dialog
|
|
m_tbAFBBWidth.SubclassDlgItem(IDC_TB_COLWIDTH, &m_dlgAllFrames);
|
|
m_tbAFBBHeight.SubclassDlgItem(IDC_TB_COLHEIGHT,&m_dlgAllFrames);
|
|
m_tbAFBBLength.SubclassDlgItem(IDC_TB_COLLENGTH,&m_dlgAllFrames);
|
|
m_tbAFBBPosX.SubclassDlgItem(IDC_TB_COLPOSX, &m_dlgAllFrames);
|
|
m_tbAFBBPosY.SubclassDlgItem(IDC_TB_COLPOSY, &m_dlgAllFrames);
|
|
m_tbAFBBPosZ.SubclassDlgItem(IDC_TB_COLPOSZ, &m_dlgAllFrames);
|
|
|
|
m_tbDistance.SubclassDlgItem(IDC_EB_DISTANCE, &m_dlgLod);
|
|
|
|
m_tbTextureName.SubclassDlgItem(IDC_EB_TEXTURENAME, &m_dlgTexture);
|
|
|
|
CWnd *pTexViewFrame = m_dlgTexture.GetDlgItem(IDC_TEXTURE_VIEW);
|
|
// CRect rc;
|
|
// pTexViewFrame->GetClientRect(&rc);
|
|
CRect rc = CRect(0,0,200,100);
|
|
m_tvTexView.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, rc, pTexViewFrame,IDC_TEXTURE_VIEW);
|
|
m_tvTexView.SubclassDlgItem(IDC_TEXTURE_VIEW, &m_dlgTexture);
|
|
|
|
// set width of shader combo box
|
|
((CComboBox*)m_dlgShader.GetDlgItem(IDC_CB_SHADER))->SetDroppedWidth(200);
|
|
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
pMainFrame->m_ctrlMIStretch.SetFont(m_dlgShader.GetFont(),FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
// add node from tree view to nodeinfo array
|
|
INDEX AddNode(INDEX iType,void *ni_pPtr,CModelInstance *pmi)
|
|
{
|
|
INDEX ctni = theApp.aNodeInfo.Count();
|
|
NodeInfo &ni = theApp.aNodeInfo.Push();
|
|
ni.ni_iType = iType;
|
|
ni.pmi = pmi;
|
|
ni.ni_pPtr = ni_pPtr;
|
|
ni.ni_bSelected = FALSE;
|
|
return ctni;
|
|
}
|
|
|
|
// add model instance to tree view
|
|
HTREEITEM CDlgBarTreeView::AddModelInst(CModelInstance &mi, CModelInstance *pmiParent, HTREEITEM hParent)
|
|
{
|
|
// insert model instance item
|
|
HTREEITEM hItem;
|
|
// expand only root model
|
|
if(hParent == TVI_ROOT) {
|
|
// add parent model instance
|
|
hItem = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE , L"", 0, 0, TVIS_EXPANDED, TVIS_EXPANDED, 0, hParent, 0 );
|
|
m_TreeCtrl.SetItemText(hItem,CString(mi.GetName()));
|
|
} else {
|
|
int iIcon = 0;
|
|
if(mi.mi_fnSourceFile != pmiParent->mi_fnSourceFile) iIcon = 8;
|
|
|
|
// add child model instance
|
|
hItem = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE , L"", iIcon, iIcon, TVIS_EXPANDED, TVIS_EXPANDED, 0, hParent, 0 );
|
|
// get parent bone name
|
|
CTString strParentBoneName = ska_GetStringFromTable(mi.mi_iParentBoneID);
|
|
CTString strText = mi.GetName() + " [" + strParentBoneName + "]";
|
|
m_TreeCtrl.SetItemText(hItem,CString(strText));
|
|
}
|
|
m_TreeCtrl.SetItemData(hItem,AddNode(NT_MODELINSTANCE,&mi,pmiParent));
|
|
|
|
// add its mesh instances
|
|
AddMeshInstances(mi,hItem);
|
|
// if skeleton exists
|
|
if(mi.mi_psklSkeleton != NULL) {
|
|
// add skeleton
|
|
AddSkeleton(mi,hItem);
|
|
}
|
|
// add animsets
|
|
AddAnimSet(mi,hItem);
|
|
// add colision boxes
|
|
AddColisionBoxes(mi,hItem);
|
|
// add all frames colision box
|
|
AddAllFramesBBox(mi,hItem);
|
|
// add model instance children
|
|
INDEX ctmi = mi.mi_cmiChildren.Count();
|
|
// for each child in model isntance
|
|
for(INDEX imi=0;imi<ctmi;imi++) {
|
|
// add child
|
|
AddModelInst(mi.mi_cmiChildren[imi],&mi,hItem);
|
|
}
|
|
return hItem;
|
|
}
|
|
|
|
// add skeleton to tree view
|
|
void CDlgBarTreeView::AddSkeleton(CModelInstance &mi, HTREEITEM hParent)
|
|
{
|
|
if(mi.mi_psklSkeleton == NULL) return;
|
|
CSkeleton &sk = *mi.mi_psklSkeleton;
|
|
// insert skeleton
|
|
HTREEITEM hItem = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 5, 5, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0 );
|
|
CTString strSkeletonName;
|
|
strSkeletonName.PrintF("%s [%d]",(const char*)sk.GetName().FileName(),sk.skl_aSkeletonLODs.Count());
|
|
|
|
m_TreeCtrl.SetItemText(hItem,CString(strSkeletonName));
|
|
m_TreeCtrl.SetItemData(hItem,AddNode(NT_SKELETONLODLIST,&sk,&mi));
|
|
|
|
INDEX ctslod = sk.skl_aSkeletonLODs.Count();
|
|
for(INDEX islod=0;islod<ctslod;islod++) {
|
|
SkeletonLOD &slod = sk.skl_aSkeletonLODs[islod];
|
|
// insert skeleton lod
|
|
HTREEITEM hSlod = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 5, 5, TVIS_SELECTED, TVIF_STATE, 0, hItem, 0 );
|
|
// count bones
|
|
INDEX ctb = slod.slod_aBones.Count();
|
|
|
|
CTString strText;
|
|
CTFileName fnSlodSource = sk.skl_aSkeletonLODs[islod].slod_fnSourceFile;
|
|
fnSlodSource = fnSlodSource.FileName();
|
|
strText.PrintF("%s [%g]-[%d]",(const char*)fnSlodSource.NoExt(),sk.skl_aSkeletonLODs[islod].slod_fMaxDistance,ctb);
|
|
m_TreeCtrl.SetItemText(hSlod,CString(strText));
|
|
m_TreeCtrl.SetItemData(hSlod,AddNode(NT_SKELETONLOD,&slod,&mi));
|
|
|
|
for(INDEX ib=0;ib<ctb;ib++) {
|
|
SkeletonBone &sb = sk.skl_aSkeletonLODs[islod].slod_aBones[ib];
|
|
// insert bone
|
|
HTREEITEM hBone = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 7, 7, TVIS_SELECTED, TVIF_STATE, 0, hSlod , 0 );
|
|
m_TreeCtrl.SetItemText(hBone,CString(ska_GetStringFromTable(sb.sb_iID)));
|
|
m_TreeCtrl.SetItemData(hBone,AddNode(NT_BONE,&sb,&mi));
|
|
}
|
|
}
|
|
}
|
|
|
|
// add mesh surfaces to tree view
|
|
void CDlgBarTreeView::AddSurfaces(CModelInstance &mi,MeshLOD &mlod,HTREEITEM hParent)
|
|
{
|
|
INDEX ctsrf = mlod.mlod_aSurfaces.Count();
|
|
for(INDEX isrf=0;isrf<ctsrf;isrf++) {
|
|
MeshSurface &msrf = mlod.mlod_aSurfaces[isrf];
|
|
CShader *pShader = msrf.msrf_pShader;
|
|
CTString strShaderName;
|
|
if(pShader!=NULL) strShaderName = pShader->GetName().FileName();
|
|
HTREEITEM hItem = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 11, 11, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0);
|
|
CTString strSurfName;
|
|
strSurfName.PrintF("%s [%d]-[%d]",(const char*)ska_GetStringFromTable(msrf.msrf_iSurfaceID),
|
|
msrf.msrf_ctVertices,msrf.msrf_aTriangles.Count());
|
|
m_TreeCtrl.SetItemText(hItem,CString(strSurfName));
|
|
m_TreeCtrl.SetItemData(hItem,AddNode(NT_MESHSURFACE,&msrf,&mi));
|
|
}
|
|
}
|
|
|
|
// add mesh instance to tree view
|
|
void CDlgBarTreeView::AddMeshInstances(CModelInstance &mi,HTREEITEM hParent)
|
|
{
|
|
INDEX ctmsh = mi.mi_aMeshInst.Count();
|
|
for(INDEX imsh=0;imsh<ctmsh;imsh++)
|
|
{
|
|
MeshInstance &mshi = mi.mi_aMeshInst[imsh];
|
|
HTREEITEM hItem = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 1, 1, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0);
|
|
CTString strMeshName;
|
|
strMeshName.PrintF("%s [%d]",(const char*)mshi.mi_pMesh->GetName().FileName(),mshi.mi_pMesh->msh_aMeshLODs.Count());
|
|
m_TreeCtrl.SetItemText(hItem,CString(strMeshName));
|
|
m_TreeCtrl.SetItemData(hItem,AddNode(NT_MESHLODLIST,&mshi,&mi));
|
|
|
|
// add mesh lods
|
|
INDEX ctmlod = mshi.mi_pMesh->msh_aMeshLODs.Count();
|
|
for(INDEX imlod=0;imlod<ctmlod;imlod++)
|
|
{
|
|
MeshLOD &mlod = mshi.mi_pMesh->msh_aMeshLODs[imlod];
|
|
HTREEITEM hMlod = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 3, 3, TVIS_SELECTED, TVIF_STATE, 0, hItem, 0);
|
|
|
|
CTString strMeshLod;
|
|
CTFileName fnMlodSource = mlod.mlod_fnSourceFile;
|
|
fnMlodSource = fnMlodSource.FileName();
|
|
|
|
strMeshLod.PrintF("%s [%g]-[%d]",(const char*)fnMlodSource.NoExt(),mlod.mlod_fMaxDistance,mlod.mlod_aVertices.Count());
|
|
m_TreeCtrl.SetItemText(hMlod,CString(strMeshLod));
|
|
m_TreeCtrl.SetItemData(hMlod,AddNode(NT_MESHLOD,&mlod,&mi));
|
|
AddSurfaces(mi,mlod,hMlod);
|
|
}
|
|
// add textures for this mesh
|
|
INDEX cttex = mshi.mi_tiTextures.Count();
|
|
for(INDEX itex=0;itex<cttex;itex++)
|
|
{
|
|
TextureInstance &ti = mshi.mi_tiTextures[itex];
|
|
CTString strTextName = ska_GetStringFromTable(ti.GetID());
|
|
HTREEITEM hTexture = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 4, 4, TVIS_SELECTED, TVIF_STATE, 0, hItem, 0 );
|
|
m_TreeCtrl.SetItemText(hTexture,CString(strTextName));
|
|
m_TreeCtrl.SetItemData(hTexture,AddNode(NT_TEXINSTANCE,&ti,&mi));
|
|
}
|
|
}
|
|
}
|
|
// add collision boxes to tree view
|
|
void CDlgBarTreeView::AddColisionBoxes(CModelInstance &mi,HTREEITEM hParent)
|
|
{
|
|
INDEX ctcb = mi.mi_cbAABox.Count();
|
|
// for each collision box
|
|
for(INDEX icb=0;icb<ctcb;icb++)
|
|
{
|
|
// add collision box
|
|
ColisionBox &cb = mi.mi_cbAABox[icb];
|
|
HTREEITEM hColisionBox = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 2, 2, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0);
|
|
m_TreeCtrl.SetItemText(hColisionBox,CString(cb.GetName()));
|
|
m_TreeCtrl.SetItemData(hColisionBox,AddNode(NT_COLISIONBOX,&cb,&mi));
|
|
}
|
|
}
|
|
|
|
void CDlgBarTreeView::AddAllFramesBBox(CModelInstance &mi,HTREEITEM hParent)
|
|
{
|
|
#pragma message(">> Remove AddAllFramesBBox")
|
|
// add all frames bounding box
|
|
ColisionBox &cb = mi.mi_cbAllFramesBBox;
|
|
HTREEITEM hAllFramesBBox = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 6, 6, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0);
|
|
m_TreeCtrl.SetItemText(hAllFramesBBox,L"All frames BBox");
|
|
m_TreeCtrl.SetItemData(hAllFramesBBox,AddNode(NT_ALLFRAMESBBOX,&cb,&mi));
|
|
}
|
|
|
|
// add anim set to tree view
|
|
HTREEITEM CDlgBarTreeView::AddAnimSet(CModelInstance &mi,HTREEITEM hParent)
|
|
{
|
|
INDEX ctas = mi.mi_aAnimSet.Count();
|
|
// for each animset
|
|
for(INDEX ias=0;ias<ctas;ias++)
|
|
{
|
|
CAnimSet &as = mi.mi_aAnimSet[ias];
|
|
INDEX ctan = as.as_Anims.Count();
|
|
CTString strAnimSetName;
|
|
strAnimSetName.PrintF("%s [%d]",(const char*)(as.GetName()).FileName(),ctan);
|
|
HTREEITEM hAnimSet = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 9, 9, TVIS_SELECTED, TVIF_STATE, 0, hParent, 0);
|
|
m_TreeCtrl.SetItemText(hAnimSet,CString(strAnimSetName));
|
|
m_TreeCtrl.SetItemData(hAnimSet,AddNode(NT_ANIMSET,&as,&mi));
|
|
// for each anim
|
|
for(INDEX ian=0;ian<ctan;ian++)
|
|
{
|
|
Animation &an = as.as_Anims[ian];
|
|
CTString strAnimName;
|
|
//strAnimName.PrintF("%s [%d]",(const char*)ska_GetStringFromTable(an.an_iID),an.an_iFrames);
|
|
strAnimName.PrintF("%s [%d]",(const char*)ska_GetStringFromTable(an.an_iID),an.an_iFrames);
|
|
HTREEITEM hAnim = m_TreeCtrl.InsertItem( TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 9, 9, TVIS_SELECTED, TVIF_STATE, 0, hAnimSet, 0);
|
|
m_TreeCtrl.SetItemText(hAnim,CString(strAnimName));
|
|
m_TreeCtrl.SetItemData(hAnim,AddNode(NT_ANIMATION,&an,&mi));
|
|
INDEX ctbe=an.an_abeBones.Count();
|
|
for(INDEX ibe=0;ibe<ctbe;ibe++)
|
|
{
|
|
BoneEnvelope &be = an.an_abeBones[ibe];
|
|
CTString strBoneEnvName;
|
|
CTString strBoneName = ska_GetStringFromTable(be.be_iBoneID);
|
|
|
|
INDEX ctr = be.be_arRot.Count();
|
|
if(an.an_bCompresed) ctr = be.be_arRotOpt.Count();
|
|
|
|
strBoneEnvName.PrintF("%s [%d]-[%d]",(const char*)strBoneName,ctr,be.be_apPos.Count());
|
|
HTREEITEM hBoneEnv = m_TreeCtrl.InsertItem(TVIF_IMAGE | TVIF_SELECTEDIMAGE , L"", 9, 9, TVIS_SELECTED, TVIF_STATE, 0, hAnim, 0);
|
|
m_TreeCtrl.SetItemText(hBoneEnv,CString(strBoneEnvName));
|
|
m_TreeCtrl.SetItemData(hBoneEnv,AddNode(NT_ANIM_BONEENV,&be,&mi));
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
// add all model instances to combo box
|
|
void CDlgBarTreeView::FillParentDropDown(CModelInstance *pmi)
|
|
{
|
|
if(pmi == NULL) return;
|
|
CComboBox *cbParentList = ((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTMODEL));
|
|
INDEX iItem = cbParentList->AddString(CString(pmi->GetName()));
|
|
cbParentList->SetItemDataPtr(iItem,pmi);
|
|
// add all children to combo box
|
|
INDEX ctmi = pmi->mi_cmiChildren.Count();
|
|
for(INDEX imi=0;imi<ctmi;imi++)
|
|
{
|
|
FillParentDropDown(&pmi->mi_cmiChildren[imi]);
|
|
}
|
|
}
|
|
// find out how many children from root to selected item
|
|
BOOL CDlgBarTreeView::RememberSelectedItem(HTREEITEM hParent,HTREEITEM hSelected)
|
|
{
|
|
if(hParent==NULL) return FALSE;
|
|
HTREEITEM hChild = m_TreeCtrl.GetChildItem(hParent);
|
|
INDEX ctLoops = 0;
|
|
while(hChild != NULL)
|
|
{
|
|
ctLoops++;
|
|
if(m_TreeCtrl.ItemHasChildren(hChild))
|
|
{
|
|
if(RememberSelectedItem(hChild,hSelected))
|
|
{
|
|
INDEX &iCur = _aSelectItem.Push();
|
|
iCur = ctLoops;
|
|
return TRUE;
|
|
}
|
|
}
|
|
if(hChild == hSelected)
|
|
{
|
|
INDEX &iCur = _aSelectItem.Push();
|
|
iCur = ctLoops;
|
|
return TRUE;
|
|
}
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
}
|
|
return FALSE;
|
|
}
|
|
// use previously filed array of child depth to reach selected item
|
|
BOOL CDlgBarTreeView::ReselectItem(HTREEITEM hParent)
|
|
{
|
|
INDEX ctrec=_aSelectItem.Count();
|
|
// from last to first
|
|
HTREEITEM hChild = hParent;
|
|
// if child is NULL select his parent and return
|
|
// loop filled array of recursion depth for selected item
|
|
for(INDEX irec=ctrec-1;irec>=0;irec--)
|
|
{
|
|
HTREEITEM hRet = m_TreeCtrl.GetChildItem(hChild);
|
|
if(hRet == NULL)
|
|
{
|
|
m_TreeCtrl.SelectItem(hChild);
|
|
return FALSE;
|
|
}
|
|
else hChild = hRet;
|
|
|
|
INDEX cti=_aSelectItem[irec];
|
|
for(INDEX i=0;i<cti-1;i++)
|
|
{
|
|
HTREEITEM hRet = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
if(hRet == NULL)
|
|
{
|
|
m_TreeCtrl.SelectItem(hChild);
|
|
return FALSE;
|
|
}
|
|
else hChild = hRet;
|
|
}
|
|
}
|
|
if(hChild != NULL)
|
|
{
|
|
m_TreeCtrl.SelectItem(hChild);
|
|
}
|
|
return TRUE;
|
|
}
|
|
// update tree view containing whole hierarchy of model instance
|
|
void CDlgBarTreeView::UpdateModelInstInfo(CModelInstance *pmi)
|
|
{
|
|
m_TreeCtrl.SetRedraw(FALSE);
|
|
// ShowControlGroup(-1);
|
|
HTREEITEM htSelectedItem = m_TreeCtrl.GetSelectedItem();
|
|
HTREEITEM hRoot = m_TreeCtrl.GetRootItem();
|
|
|
|
CTString strRoot;
|
|
// if root item exists
|
|
if(hRoot!=NULL) {
|
|
// remember its name
|
|
strRoot = CStringA(m_TreeCtrl.GetItemText(hRoot));
|
|
}
|
|
|
|
// clear array for selected item
|
|
_aSelectItem.PopAll();
|
|
_aiSelectedMeshSurfaces.PopAll();
|
|
// get current selected item and fill array of depths how to reach it
|
|
RememberSelectedItem(hRoot,htSelectedItem);
|
|
theApp.iSelectedBoneID = -1;
|
|
|
|
INDEX iSelIndex=0;
|
|
NodeInfo niSelected;
|
|
if(htSelectedItem != NULL)
|
|
{
|
|
iSelIndex = m_TreeCtrl.GetItemData(htSelectedItem);
|
|
niSelected = theApp.aNodeInfo[iSelIndex];
|
|
}
|
|
|
|
m_TreeCtrl.DeleteAllItems();
|
|
theApp.aNodeInfo.PopAll();
|
|
|
|
// reset combo box
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTMODEL))->ResetContent();
|
|
|
|
if(pmi == NULL) {
|
|
m_TreeCtrl.SetRedraw(TRUE);
|
|
return;
|
|
}
|
|
|
|
// fill combo with all parents
|
|
FillParentDropDown(pmi);
|
|
// fill tree ctrl with all hierarchy
|
|
HTREEITEM hParent = AddModelInst(*pmi,NULL,TVI_ROOT);
|
|
|
|
// get name of root item
|
|
CTString strNewRoot = CStringA(m_TreeCtrl.GetItemText(hParent));
|
|
// if root item name is different then old root item name clear selection
|
|
if(strRoot != strNewRoot && strRoot.Length() > 0) _aSelectItem.PopAll();
|
|
if(_aSelectItem.Count() > 0)
|
|
{
|
|
// try to select item that was selected before reloading
|
|
ReselectItem(hParent);
|
|
}
|
|
else
|
|
{
|
|
// select hParent
|
|
m_TreeCtrl.SelectItem(hParent);
|
|
}
|
|
m_TreeCtrl.SetRedraw(TRUE);
|
|
}
|
|
// check custom seconds per frame check box
|
|
void CDlgBarTreeView::CheckSecPerFrameCtrl(BOOL bCheck)
|
|
{
|
|
((CButton*)m_dlgAnimSet.GetDlgItem(IDC_CB_SECPERFRAME))->SetCheck(bCheck);
|
|
m_dlgAnimSet.GetDlgItem(IDC_EB_SECPERFRAME)->EnableWindow(bCheck);
|
|
}
|
|
// change tab in tab control
|
|
void CDlgBarTreeView::OnSelchangeModeSelectTab(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
// CTabCtrl* pTab = (CTabCtrl*)GetDlgItem(IDC_MODE_SELECT_TAB);
|
|
// ShowControlGroup(pTab->GetCurSel());
|
|
*pResult = 0;
|
|
}
|
|
// expand all model instances in tree view
|
|
void CDlgBarTreeView::ExpandAllModelInstances(HTREEITEM hItem)
|
|
{
|
|
INDEX iIndex = m_TreeCtrl.GetItemData(hItem);
|
|
NodeInfo &ni = theApp.aNodeInfo[iIndex];
|
|
// it this item is model instance
|
|
if(ni.ni_iType == NT_MODELINSTANCE)
|
|
{
|
|
// expand it
|
|
m_TreeCtrl.Expand(hItem,TVE_EXPAND);
|
|
}
|
|
|
|
// check if current item has children
|
|
if(m_TreeCtrl.ItemHasChildren(hItem))
|
|
{
|
|
HTREEITEM hChild = m_TreeCtrl.GetChildItem(hItem);
|
|
while(TRUE)
|
|
{
|
|
// expand all model instance in this child
|
|
ExpandAllModelInstances(hChild);
|
|
// get next item
|
|
hChild = m_TreeCtrl.GetNextSiblingItem(hChild);
|
|
if(hChild==NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// put all bones of selected skeleton in combo box
|
|
void CDlgBarTreeView::FillBonesToComboBox(CSkeleton *pskl,INDEX iSelectedIndex)
|
|
{
|
|
// delete all bones from combo box
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->ResetContent();
|
|
// if skeleton does not exist return
|
|
if(pskl == NULL) return;
|
|
// count skeleton lods
|
|
INDEX ctslod = pskl->skl_aSkeletonLODs.Count();
|
|
if(ctslod<1) return;
|
|
|
|
SkeletonLOD *pslod = &pskl->skl_aSkeletonLODs[0];
|
|
// if lod doesnt exist return;
|
|
if(pslod == NULL) return;
|
|
// count bones in skeleton lod
|
|
INDEX ctsb = pslod->slod_aBones.Count();
|
|
// for each bone in skeleton lod
|
|
for(INDEX isb=0;isb<ctsb;isb++)
|
|
{
|
|
SkeletonBone &sb = pslod->slod_aBones[isb];
|
|
// add bone to combo box
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->AddString(CString(ska_GetStringFromTable(sb.sb_iID)));
|
|
}
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->SetCurSel(iSelectedIndex);
|
|
}
|
|
|
|
// set text for 'custom' tab in tab control
|
|
void CDlgBarTreeView::SetCustomTabText(wchar_t *strText)
|
|
{
|
|
// fill tab control item
|
|
TCITEM tcitem;
|
|
memset(&tcitem,0,sizeof(tcitem));
|
|
tcitem.mask = TCIF_TEXT;
|
|
tcitem.cchTextMax = 256;
|
|
tcitem.pszText = strText;
|
|
((CTabCtrl*)GetDlgItem(IDC_MODE_SELECT_TAB))->SetItem(2,&tcitem);
|
|
}
|
|
// reset all controls on dialog
|
|
void CDlgBarTreeView::ResetControls()
|
|
{
|
|
m_TreeCtrl.DeleteAllItems();
|
|
m_TreeCtrl.hLastSelected = NULL;
|
|
GetDlgItem(IDC_SELECTEDMI)->SetWindowText(L"(none)");
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTBONE))->ResetContent();
|
|
((CComboBox*)m_dlgParent.GetDlgItem(IDC_CB_PARENTMODEL))->ResetContent();
|
|
((CButton*)m_dlgAnimSet.GetDlgItem(IDC_CB_COMPRESION))->SetCheck(FALSE);
|
|
CheckSecPerFrameCtrl(FALSE);
|
|
ShowControlGroup(-1);
|
|
|
|
|
|
m_tbOffPosX.SetWindowText(L"");
|
|
m_tbOffPosY.SetWindowText(L"");
|
|
m_tbOffPosZ.SetWindowText(L"");
|
|
m_tbOffRotH.SetWindowText(L"");
|
|
m_tbOffRotP.SetWindowText(L"");
|
|
m_tbOffRotB.SetWindowText(L"");
|
|
|
|
m_tbTreshold.SetWindowText(L"");
|
|
m_tbAnimSpeed.SetWindowText(L"");
|
|
|
|
m_tbColName.SetWindowText(L"");
|
|
m_tbColWidth.SetWindowText(L"");
|
|
m_tbColHeight.SetWindowText(L"");
|
|
m_tbColLength.SetWindowText(L"");
|
|
m_tbColPosX.SetWindowText(L"");
|
|
m_tbColPosY.SetWindowText(L"");
|
|
m_tbColPosZ.SetWindowText(L"");
|
|
|
|
m_tbDistance.SetWindowText(L"");
|
|
//GET_CTRL(IDC_CB_TEXNAME)->SetWindowText("");
|
|
}
|
|
|
|
void CDlgBarTreeView::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
/*
|
|
// if app has initialized
|
|
if(theApp.bAppInitialized) {
|
|
// adjust splitter
|
|
AdjustSplitter();
|
|
}
|
|
*/
|
|
CDlgTemplate::OnSize(nType, cx, cy);
|
|
}
|