123
This commit is contained in:
301
Editor/Util/AVIGenerator.cpp
Normal file
301
Editor/Util/AVIGenerator.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
// AVIGenerator.cpp: implementation of the CAVIGenerator class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "AVIGenerator.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[]=__FILE__;
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CAVIGenerator::CAVIGenerator()
|
||||
: m_sFile(_T("Untitled.avi")), m_dwRate(30),
|
||||
m_pAVIFile(NULL), m_pStream(NULL), m_pStreamCompressed(NULL)
|
||||
{
|
||||
memset(&m_bih,0,sizeof(BITMAPINFOHEADER));
|
||||
}
|
||||
|
||||
#ifdef _AVIGENERATOR_USE_MFC
|
||||
CAVIGenerator::CAVIGenerator(LPCTSTR sFileName, CView* pView, DWORD dwRate)
|
||||
: m_sFile(sFileName), m_dwRate(dwRate),
|
||||
m_pAVIFile(NULL), m_pStream(NULL), m_pStreamCompressed(NULL)
|
||||
{
|
||||
MakeExtAvi();
|
||||
SetBitmapHeader(pView);
|
||||
}
|
||||
#endif
|
||||
|
||||
CAVIGenerator::CAVIGenerator(LPCTSTR sFileName, LPBITMAPINFOHEADER lpbih, DWORD dwRate)
|
||||
: m_sFile(sFileName), m_dwRate(dwRate),
|
||||
m_pAVIFile(NULL), m_pStream(NULL), m_pStreamCompressed(NULL)
|
||||
{
|
||||
MakeExtAvi();
|
||||
SetBitmapHeader(lpbih);
|
||||
}
|
||||
|
||||
CAVIGenerator::~CAVIGenerator()
|
||||
{
|
||||
// Just checking that all allocated ressources have been released
|
||||
ASSERT(m_pStream==NULL);
|
||||
ASSERT(m_pStreamCompressed==NULL);
|
||||
ASSERT(m_pAVIFile==NULL);
|
||||
}
|
||||
|
||||
void CAVIGenerator::SetBitmapHeader(LPBITMAPINFOHEADER lpbih)
|
||||
{
|
||||
// checking that bitmap size are multiple of 4
|
||||
ASSERT(lpbih->biWidth%4==0);
|
||||
ASSERT(lpbih->biHeight%4==0);
|
||||
|
||||
// copying bitmap info structure.
|
||||
// corrected thanks to Lori Gardi
|
||||
memcpy(&m_bih,lpbih, sizeof(BITMAPINFOHEADER));
|
||||
}
|
||||
|
||||
#ifdef _AVIGENERATOR_USE_MFC
|
||||
void CAVIGenerator::SetBitmapHeader(CView *pView)
|
||||
{
|
||||
ASSERT_VALID(pView);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Getting screen dimensions
|
||||
// Get client geometry
|
||||
CRect rect;
|
||||
pView->GetClientRect(&rect);
|
||||
CSize size(rect.Width(),rect.Height());
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// changing size of image so dimension are multiple of 4
|
||||
size.cx=(size.cx/4)*4;
|
||||
size.cy=(size.cy/4)*4;
|
||||
|
||||
// initialize m_bih
|
||||
memset(&m_bih,0, sizeof(BITMAPINFOHEADER));
|
||||
// filling bitmap info structure.
|
||||
m_bih.biSize=sizeof(BITMAPINFOHEADER);
|
||||
m_bih.biWidth=size.cx;
|
||||
m_bih.biHeight=size.cy;
|
||||
m_bih.biPlanes=1;
|
||||
m_bih.biBitCount=24;
|
||||
m_bih.biSizeImage=((m_bih.biWidth*m_bih.biBitCount+31)/32 * 4)*m_bih.biHeight;
|
||||
m_bih.biCompression=BI_RGB; //BI_RGB means BRG in reality
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT CAVIGenerator::InitEngine( const char *codec )
|
||||
{
|
||||
AVISTREAMINFO strHdr; // information for a single stream
|
||||
AVICOMPRESSOPTIONS opts;
|
||||
AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
|
||||
|
||||
TCHAR szBuffer[1024];
|
||||
HRESULT hr;
|
||||
|
||||
m_sError=_T("Ok");
|
||||
|
||||
// Step 0 : Let's make sure we are running on 1.1
|
||||
DWORD wVer = HIWORD(VideoForWindowsVersion());
|
||||
if (wVer < 0x010a)
|
||||
{
|
||||
// oops, we are too old, blow out of here
|
||||
m_sError=_T("Version of Video for Windows too old. Come on, join the 21th century!");
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Step 1 : initialize AVI engine
|
||||
AVIFileInit();
|
||||
|
||||
// Step 2 : Open the movie file for writing....
|
||||
hr = AVIFileOpen(&m_pAVIFile, // Address to contain the new file interface pointer
|
||||
(LPCSTR)m_sFile, // Null-terminated string containing the name of the file to open
|
||||
OF_WRITE | OF_CREATE, // Access mode to use when opening the file.
|
||||
NULL); // use handler determined from file extension.
|
||||
// Name your file .avi -> very important
|
||||
|
||||
if (hr != AVIERR_OK)
|
||||
{
|
||||
_tprintf(szBuffer,_T("AVI Engine failed to initialize. Check filename %s."),m_sFile);
|
||||
m_sError=szBuffer;
|
||||
// Check it succeded.
|
||||
switch(hr)
|
||||
{
|
||||
case AVIERR_BADFORMAT:
|
||||
m_sError+=_T("The file couldn't be read, indicating a corrupt file or an unrecognized format.");
|
||||
break;
|
||||
case AVIERR_MEMORY:
|
||||
m_sError+=_T("The file could not be opened because of insufficient memory.");
|
||||
break;
|
||||
case AVIERR_FILEREAD:
|
||||
m_sError+=_T("A disk error occurred while reading the file.");
|
||||
break;
|
||||
case AVIERR_FILEOPEN:
|
||||
m_sError+=_T("A disk error occurred while opening the file.");
|
||||
break;
|
||||
case REGDB_E_CLASSNOTREG:
|
||||
m_sError+=_T("According to the registry, the type of file specified in AVIFileOpen does not have a handler to process it");
|
||||
break;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Fill in the header for the video stream....
|
||||
memset(&strHdr, 0, sizeof(strHdr));
|
||||
strHdr.fccType = streamtypeVIDEO; // video stream type
|
||||
strHdr.fccHandler = 0;
|
||||
strHdr.dwScale = 1; // should be one for video
|
||||
strHdr.dwRate = m_dwRate; // fps
|
||||
strHdr.dwSuggestedBufferSize = m_bih.biSizeImage; // Recommended buffer size, in bytes, for the stream.
|
||||
SetRect(&strHdr.rcFrame, 0, 0, // rectangle for stream
|
||||
(int) m_bih.biWidth,
|
||||
(int) m_bih.biHeight);
|
||||
|
||||
// Step 3 : Create the stream;
|
||||
hr = AVIFileCreateStream(m_pAVIFile, // file pointer
|
||||
&m_pStream, // returned stream pointer
|
||||
&strHdr); // stream header
|
||||
|
||||
// Check it succeded.
|
||||
if (hr != AVIERR_OK)
|
||||
{
|
||||
m_sError=_T("AVI Stream creation failed. Check Bitmap info.");
|
||||
if (hr==AVIERR_READONLY)
|
||||
{
|
||||
m_sError+=_T(" Read only file.");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (!codec || strlen(codec) < 4)
|
||||
{
|
||||
m_sError+=_T(" A suitable compressor cannot be found.");
|
||||
return AVIERR_NOCOMPRESSOR;
|
||||
}
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.fccType = streamtypeVIDEO;
|
||||
//opts.dwQuality = 100;
|
||||
opts.fccHandler = mmioFOURCC(codec[0],codec[1],codec[2],codec[3]); // Microsoft video 1
|
||||
//opts.fccHandler = getFOURCC(_compressor);
|
||||
//opts.fccHandler = 0;
|
||||
//opts.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed
|
||||
//opts.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak
|
||||
//opts.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2
|
||||
//opts.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1
|
||||
//opts.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0
|
||||
//opts.dwKeyFrameEvery = 5;
|
||||
//opts.dwQuality
|
||||
//opts.dwBytesPerSecond
|
||||
//opts.dwFlags = AVICOMPRESSF_KEYFRAMES;
|
||||
//opts.lpFormat
|
||||
//opts.cbFormat
|
||||
//opts.lpParms
|
||||
//opts.cbParms
|
||||
//opts.dwInterleaveEvery
|
||||
|
||||
// Step 5: Create a compressed stream using codec options.
|
||||
hr = AVIMakeCompressedStream(&m_pStreamCompressed,
|
||||
m_pStream,
|
||||
&opts,
|
||||
NULL);
|
||||
|
||||
if (hr != AVIERR_OK)
|
||||
{
|
||||
m_sError=_T("AVI Compressed Stream creation failed.");
|
||||
|
||||
switch(hr)
|
||||
{
|
||||
case AVIERR_NOCOMPRESSOR:
|
||||
m_sError+=_T(" A suitable compressor cannot be found.");
|
||||
break;
|
||||
case AVIERR_MEMORY:
|
||||
m_sError+=_T(" There is not enough memory to complete the operation.");
|
||||
break;
|
||||
case AVIERR_UNSUPPORTED:
|
||||
m_sError+=_T("Compression is not supported for this type of data. This error might be returned if you try to compress data that is not audio or video.");
|
||||
break;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Step 6 : sets the format of a stream at the specified position
|
||||
hr = AVIStreamSetFormat(m_pStreamCompressed,
|
||||
0, // position
|
||||
&m_bih, // stream format
|
||||
m_bih.biSize + // format size
|
||||
m_bih.biClrUsed * sizeof(RGBQUAD));
|
||||
|
||||
if (hr != AVIERR_OK)
|
||||
{
|
||||
m_sError=_T("AVI Compressed Stream format setting failed.");
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Step 6 : Initialize step counter
|
||||
m_lFrame=0;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void CAVIGenerator::ReleaseEngine()
|
||||
{
|
||||
if (m_pStream)
|
||||
{
|
||||
AVIStreamRelease(m_pStream);
|
||||
m_pStream=NULL;
|
||||
}
|
||||
|
||||
if (m_pStreamCompressed)
|
||||
{
|
||||
AVIStreamRelease(m_pStreamCompressed);
|
||||
m_pStreamCompressed=NULL;
|
||||
}
|
||||
|
||||
if (m_pAVIFile)
|
||||
{
|
||||
AVIFileRelease(m_pAVIFile);
|
||||
m_pAVIFile=NULL;
|
||||
}
|
||||
|
||||
// Close engine
|
||||
AVIFileExit();
|
||||
}
|
||||
|
||||
HRESULT CAVIGenerator::AddFrame(BYTE *bmBits)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// compress bitmap
|
||||
hr = AVIStreamWrite(m_pStreamCompressed, // stream pointer
|
||||
m_lFrame, // time of this frame
|
||||
1, // number to write
|
||||
bmBits, // image buffer
|
||||
m_bih.biSizeImage, // size of this frame
|
||||
AVIIF_KEYFRAME, // flags....
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
// updating frame counter
|
||||
m_lFrame++;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void CAVIGenerator::MakeExtAvi()
|
||||
{
|
||||
|
||||
// finding avi
|
||||
if( _tcsstr((const char*)m_sFile,_T("avi"))==NULL )
|
||||
{
|
||||
m_sFile+=_T(".avi");
|
||||
}
|
||||
}
|
||||
141
Editor/Util/AVIGenerator.h
Normal file
141
Editor/Util/AVIGenerator.h
Normal file
@@ -0,0 +1,141 @@
|
||||
// AVIGenerator.h: interface for the CAVIGenerator class.
|
||||
//
|
||||
// A class to easily create AVI
|
||||
//
|
||||
// Original code : Example code in WriteAvi.c of MSDN
|
||||
//
|
||||
// Author : Jonathan de Halleux. dehalleux@auto.ucl.ac.be
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_AVIGENERATOR_H__6BAF2E9D_3866_4779_A43B_D1B21E7E4F39__INCLUDED_)
|
||||
#define AFX_AVIGENERATOR_H__6BAF2E9D_3866_4779_A43B_D1B21E7E4F39__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
// needed headers
|
||||
#include <comdef.h>
|
||||
#include <memory.h>
|
||||
#include <tchar.h>
|
||||
#include <string.h>
|
||||
#include <vfw.h>
|
||||
|
||||
#pragma message(" _Adding library: vfw32.lib" )
|
||||
#pragma comment ( lib, "vfw32.lib")
|
||||
|
||||
// undefine this if you don't use MFC
|
||||
#define _AVIGENERATOR_USE_MFC
|
||||
|
||||
/*! \brief A simple class to create AVI video stream.
|
||||
|
||||
|
||||
\par Usage
|
||||
|
||||
Step 1 : Declare an CAVIGenerator object
|
||||
Step 2 : Set Bitmap by calling SetBitmapHeader functions + other parameters
|
||||
Step 3 : Initialize engine by calling InitEngine
|
||||
Step 4 : Send each frames to engine with function AddFrame
|
||||
Step 5 : Close engine by calling ReleaseEngine
|
||||
|
||||
\par Demo Code:
|
||||
|
||||
\code
|
||||
CAVIGenerator AviGen;
|
||||
BYTE* bmBits;
|
||||
|
||||
// set characteristics
|
||||
AviGen.SetRate(20); // set 20fps
|
||||
AviGen.SetBitmapHeader(GetActiveView()); // give info about bitmap
|
||||
|
||||
AviGen.InitEngine();
|
||||
|
||||
..... // Draw code, bmBits is the buffer containing the frame
|
||||
AviGen.AddFrame(bmBits);
|
||||
.....
|
||||
|
||||
AviGen.ReleaseEngine();
|
||||
\endcode
|
||||
|
||||
\par Update history:
|
||||
|
||||
- {\bf 22-10-2002} Minor changes in constructors.
|
||||
|
||||
\author : Jonathan de Halleux, dehalleux@auto.ucl.ac.be (2001)
|
||||
*/
|
||||
class CAVIGenerator
|
||||
{
|
||||
public:
|
||||
//! \name Constructors and destructors
|
||||
//@{
|
||||
//! Default constructor
|
||||
CAVIGenerator();
|
||||
#ifdef _AVIGENERATOR_USE_MFC
|
||||
//! Inplace constructor with CView
|
||||
CAVIGenerator(LPCTSTR sFileName, CView* pView, DWORD dwRate);
|
||||
#endif
|
||||
//! Inplace constructor with BITMAPINFOHEADER
|
||||
CAVIGenerator(LPCTSTR sFileName, LPBITMAPINFOHEADER lpbih, DWORD dwRate);
|
||||
~CAVIGenerator();
|
||||
//@}
|
||||
|
||||
//! \name AVI engine function
|
||||
//@{
|
||||
/*! \brief Initialize engine and choose codex
|
||||
|
||||
Some asserts are made to check that bitmap has been properly initialized
|
||||
*/
|
||||
HRESULT InitEngine( const char *codec );
|
||||
|
||||
/*! \brief Adds a frame to the movie.
|
||||
|
||||
The data pointed by bmBits has to be compatible with the bitmap description of the movie.
|
||||
*/
|
||||
HRESULT AddFrame(BYTE* bmBits);
|
||||
//! Release ressources allocated for movie and close file.
|
||||
void ReleaseEngine();
|
||||
//@}
|
||||
|
||||
//! \name Setters and getters
|
||||
//@{
|
||||
//! Sets bitmap info to match pView dimension.
|
||||
void SetBitmapHeader(CView* pView);
|
||||
//! Sets bitmap info as in lpbih
|
||||
void SetBitmapHeader(LPBITMAPINFOHEADER lpbih);
|
||||
//! returns a pointer to bitmap info
|
||||
LPBITMAPINFOHEADER GetBitmapHeader() { return &m_bih;};
|
||||
//! sets the name of the ouput file (should be .avi)
|
||||
void SetFileName(LPCTSTR _sFileName) { m_sFile=_sFileName; MakeExtAvi();};
|
||||
//! Sets FrameRate (should equal or greater than one)
|
||||
void SetRate(DWORD dwRate) { m_dwRate=dwRate;};
|
||||
//@}
|
||||
|
||||
//! \name Error handling
|
||||
//@{
|
||||
//! returns last error message
|
||||
LPCTSTR GetLastErrorMessage() const { return m_sError;};
|
||||
//@}
|
||||
|
||||
protected:
|
||||
//! name of output file
|
||||
_bstr_t m_sFile;
|
||||
//! Frame rate
|
||||
DWORD m_dwRate;
|
||||
//! structure contains information for a single stream
|
||||
BITMAPINFOHEADER m_bih;
|
||||
//! last error string
|
||||
_bstr_t m_sError;
|
||||
|
||||
private:
|
||||
void MakeExtAvi();
|
||||
//! frame counter
|
||||
long m_lFrame;
|
||||
//! file interface pointer
|
||||
PAVIFILE m_pAVIFile;
|
||||
//! Address of the stream interface
|
||||
PAVISTREAM m_pStream;
|
||||
//! Address of the compressed video stream
|
||||
PAVISTREAM m_pStreamCompressed;
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_AVIGENERATOR_H__6BAF2E9D_3866_4779_A43B_D1B21E7E4F39__INCLUDED_)
|
||||
80
Editor/Util/AVI_Writer.cpp
Normal file
80
Editor/Util/AVI_Writer.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: AVI_Writer.cpp
|
||||
// Version: v1.00
|
||||
// Created: 13/5/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "AVI_Writer.h"
|
||||
#include "AVIGenerator.h"
|
||||
|
||||
#include "Settings.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAVI_Writer::CAVI_Writer()
|
||||
{
|
||||
m_pAVI = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAVI_Writer::~CAVI_Writer()
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAVI_Writer::OpenFile( const char *filename,int width,int height )
|
||||
{
|
||||
m_pAVI = new CAVIGenerator;
|
||||
m_pAVI->SetFileName( filename );
|
||||
m_pAVI->SetRate(20);
|
||||
|
||||
BITMAPINFOHEADER bmi;
|
||||
ZeroStruct(bmi);
|
||||
bmi.biSize = sizeof(bmi);
|
||||
bmi.biWidth = width;
|
||||
bmi.biHeight = height;
|
||||
bmi.biPlanes = 1;
|
||||
bmi.biBitCount = 32;
|
||||
bmi.biCompression = BI_RGB;
|
||||
bmi.biSizeImage = 0;
|
||||
m_pAVI->SetBitmapHeader( &bmi );
|
||||
m_pAVI->SetRate( gSettings.aviSettings.nFrameRate );
|
||||
if (FAILED(m_pAVI->InitEngine( gSettings.aviSettings.codec )))
|
||||
{
|
||||
Warning( "AVI Engine Initialization Failed (%s)",filename );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAVI_Writer::CloseFile()
|
||||
{
|
||||
if (m_pAVI)
|
||||
{
|
||||
m_pAVI->ReleaseEngine();
|
||||
delete m_pAVI;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAVI_Writer::AddFrame( CImage &image )
|
||||
{
|
||||
if (m_pAVI)
|
||||
{
|
||||
if (!FAILED(m_pAVI->AddFrame( (BYTE*)image.GetData() )))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
37
Editor/Util/AVI_Writer.h
Normal file
37
Editor/Util/AVI_Writer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: AVI_Writer.h
|
||||
// Version: v1.00
|
||||
// Created: 13/5/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AVI_Writer_h__
|
||||
#define __AVI_Writer_h__
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Can save sequence of images to the AVI file.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CAVI_Writer
|
||||
{
|
||||
public:
|
||||
CAVI_Writer();
|
||||
~CAVI_Writer();
|
||||
|
||||
bool OpenFile( const char *filename,int width,int height );
|
||||
bool CloseFile();
|
||||
bool AddFrame( CImage &image );
|
||||
private:
|
||||
class CAVIGenerator *m_pAVI;
|
||||
};
|
||||
|
||||
#endif // __AVI_Writer_h__
|
||||
|
||||
597
Editor/Util/AffineParts.cpp
Normal file
597
Editor/Util/AffineParts.cpp
Normal file
@@ -0,0 +1,597 @@
|
||||
/**** Decompose.c ****/
|
||||
/* Ken Shoemake, 1993 */
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#pragma warning ( disable : 4244 ) // conversion from 'double' to 'float', possible loss of data.
|
||||
|
||||
/**** Decompose.h - Basic declarations ****/
|
||||
typedef struct {float x, y, z, w;} Quatern; /* Quaternernion */
|
||||
enum QuaternPart {X, Y, Z, W};
|
||||
typedef Quatern HVect; /* Homogeneous 3D vector */
|
||||
typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
|
||||
typedef struct {
|
||||
HVect t; /* Translation components */
|
||||
Quatern q; /* Essential rotation */
|
||||
Quatern u; /* Stretch rotation */
|
||||
HVect k; /* Stretch factors */
|
||||
float f; /* Sign of determinant */
|
||||
} SAffineParts;
|
||||
|
||||
|
||||
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S);
|
||||
HVect spect_decomp(HMatrix S, HMatrix U);
|
||||
Quatern snuggle(Quatern q, HVect *k);
|
||||
|
||||
/******* Matrix Preliminaries *******/
|
||||
|
||||
/** Fill out 3x3 matrix to 4x4 **/
|
||||
#define mat_pad(A) (A[W][X]=A[X][W]=A[W][Y]=A[Y][W]=A[W][Z]=A[Z][W]=0,A[W][W]=1)
|
||||
|
||||
/** Copy nxn matrix A to C using "gets" for assignment **/
|
||||
#define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
C[i][j] gets (A[i][j]);}
|
||||
|
||||
/** Copy transpose of nxn matrix A to C using "gets" for assignment **/
|
||||
#define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
AT[i][j] gets (A[j][i]);}
|
||||
|
||||
/** Assign nxn matrix C the element-wise combination of A and B using "op" **/
|
||||
#define mat_binop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
|
||||
C[i][j] gets (A[i][j]) op (B[i][j]);}
|
||||
|
||||
/** Multiply the upper left 3x3 parts of A and B to get AB **/
|
||||
static void mat_mult(HMatrix A, HMatrix B, HMatrix AB)
|
||||
{
|
||||
int i, j;
|
||||
for (i=0; i<3; i++) for (j=0; j<3; j++)
|
||||
AB[i][j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + A[i][2]*B[2][j];
|
||||
}
|
||||
|
||||
/** Return dot product of length 3 vectors va and vb **/
|
||||
static float vdot(float *va, float *vb)
|
||||
{
|
||||
return (va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2]);
|
||||
}
|
||||
|
||||
/** Set v to cross product of length 3 vectors va and vb **/
|
||||
static void vcross(float *va, float *vb, float *v)
|
||||
{
|
||||
v[0] = va[1]*vb[2] - va[2]*vb[1];
|
||||
v[1] = va[2]*vb[0] - va[0]*vb[2];
|
||||
v[2] = va[0]*vb[1] - va[1]*vb[0];
|
||||
}
|
||||
|
||||
/** Set MadjT to transpose of inverse of M times determinant of M **/
|
||||
static void adjoint_transpose(HMatrix M, HMatrix MadjT)
|
||||
{
|
||||
vcross(M[1], M[2], MadjT[0]);
|
||||
vcross(M[2], M[0], MadjT[1]);
|
||||
vcross(M[0], M[1], MadjT[2]);
|
||||
}
|
||||
|
||||
/******* Quaternernion Preliminaries *******/
|
||||
|
||||
/* Construct a (possibly non-unit) Quaternernion from real components. */
|
||||
static Quatern Qt_(float x, float y, float z, float w)
|
||||
{
|
||||
Quatern qq;
|
||||
qq.x = x; qq.y = y; qq.z = z; qq.w = w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return conjugate of Quaternernion. */
|
||||
static Quatern Qt_Conj(Quatern q)
|
||||
{
|
||||
Quatern qq;
|
||||
qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return Quaternernion product qL * qR. Note: order is important!
|
||||
* To combine rotations, use the product Mul(qSecond, qFirst),
|
||||
* which gives the effect of rotating by qFirst then qSecond. */
|
||||
static Quatern Qt_Mul(Quatern qL, Quatern qR)
|
||||
{
|
||||
Quatern qq;
|
||||
qq.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z;
|
||||
qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y;
|
||||
qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z;
|
||||
qq.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Return product of Quaternernion q by scalar w. */
|
||||
static Quatern Qt_Scale(Quatern q, float w)
|
||||
{
|
||||
Quatern qq;
|
||||
qq.w = q.w*w; qq.x = q.x*w; qq.y = q.y*w; qq.z = q.z*w;
|
||||
return (qq);
|
||||
}
|
||||
|
||||
/* Construct a unit Quaternernion from rotation matrix. Assumes matrix is
|
||||
* used to multiply column vector on the left: vnew = mat vold. Works
|
||||
* correctly for right-handed coordinate system and right-handed rotations.
|
||||
* Translation and perspective components ignored. */
|
||||
static Quatern Qt_FromMatrix(HMatrix mat)
|
||||
{
|
||||
/* This algorithm avoids near-zero divides by looking for a large component
|
||||
* - first w, then x, y, or z. When the trace is greater than zero,
|
||||
* |w| is greater than 1/2, which is as small as a largest component can be.
|
||||
* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
|
||||
* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
|
||||
Quatern qu;
|
||||
register double tr, s;
|
||||
|
||||
tr = mat[X][X] + mat[Y][Y]+ mat[Z][Z];
|
||||
if (tr >= 0.0) {
|
||||
s = sqrt(tr + mat[W][W]);
|
||||
qu.w = s*0.5;
|
||||
s = 0.5 / s;
|
||||
qu.x = (mat[Z][Y] - mat[Y][Z]) * s;
|
||||
qu.y = (mat[X][Z] - mat[Z][X]) * s;
|
||||
qu.z = (mat[Y][X] - mat[X][Y]) * s;
|
||||
} else {
|
||||
int h = X;
|
||||
if (mat[Y][Y] > mat[X][X]) h = Y;
|
||||
if (mat[Z][Z] > mat[h][h]) h = Z;
|
||||
switch (h) {
|
||||
#define caseMacro(i,j,k,I,J,K) \
|
||||
case I:\
|
||||
s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\
|
||||
qu.i = s*0.5;\
|
||||
s = 0.5 / s;\
|
||||
qu.j = (mat[I][J] + mat[J][I]) * s;\
|
||||
qu.k = (mat[K][I] + mat[I][K]) * s;\
|
||||
qu.w = (mat[K][J] - mat[J][K]) * s;\
|
||||
break
|
||||
caseMacro(x,y,z,X,Y,Z);
|
||||
caseMacro(y,z,x,Y,Z,X);
|
||||
caseMacro(z,x,y,Z,X,Y);
|
||||
}
|
||||
}
|
||||
if (mat[W][W] != 1.0) qu = Qt_Scale(qu, 1.0f/sqrt(mat[W][W]));
|
||||
return (qu);
|
||||
}
|
||||
/******* Decomp Auxiliaries *******/
|
||||
|
||||
static HMatrix mat_id = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
|
||||
|
||||
/** Compute either the 1 or infinity norm of M, depending on tpose **/
|
||||
static float mat_norm(HMatrix M, int tpose)
|
||||
{
|
||||
int i;
|
||||
float sum, max;
|
||||
max = 0.0;
|
||||
for (i=0; i<3; i++) {
|
||||
if (tpose) sum = fabs(M[0][i])+fabs(M[1][i])+fabs(M[2][i]);
|
||||
else sum = fabs(M[i][0])+fabs(M[i][1])+fabs(M[i][2]);
|
||||
if (max<sum) max = sum;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
static float norm_inf(HMatrix M) {return mat_norm(M, 0);}
|
||||
static float norm_one(HMatrix M) {return mat_norm(M, 1);}
|
||||
|
||||
/** Return index of column of M containing maximum abs entry, or -1 if M=0 **/
|
||||
static int find_max_col(HMatrix M)
|
||||
{
|
||||
float abs, max;
|
||||
int i, j, col;
|
||||
max = 0.0; col = -1;
|
||||
for (i=0; i<3; i++) for (j=0; j<3; j++) {
|
||||
abs = M[i][j]; if (abs<0.0) abs = -abs;
|
||||
if (abs>max) {max = abs; col = j;}
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
/** Setup u for Household reflection to zero all v components but first **/
|
||||
static void make_reflector(float *v, float *u)
|
||||
{
|
||||
float s = sqrt(vdot(v, v));
|
||||
u[0] = v[0]; u[1] = v[1];
|
||||
u[2] = v[2] + ((v[2]<0.0) ? -s : s);
|
||||
s = sqrt(2.0/vdot(u, u));
|
||||
u[0] = u[0]*s; u[1] = u[1]*s; u[2] = u[2]*s;
|
||||
}
|
||||
|
||||
/** Apply Householder reflection represented by u to column vectors of M **/
|
||||
static void reflect_cols(HMatrix M, float *u)
|
||||
{
|
||||
int i, j;
|
||||
for (i=0; i<3; i++) {
|
||||
float s = u[0]*M[0][i] + u[1]*M[1][i] + u[2]*M[2][i];
|
||||
for (j=0; j<3; j++) M[j][i] -= u[j]*s;
|
||||
}
|
||||
}
|
||||
/** Apply Householder reflection represented by u to row vectors of M **/
|
||||
static void reflect_rows(HMatrix M, float *u)
|
||||
{
|
||||
int i, j;
|
||||
for (i=0; i<3; i++) {
|
||||
float s = vdot(u, M[i]);
|
||||
for (j=0; j<3; j++) M[i][j] -= u[j]*s;
|
||||
}
|
||||
}
|
||||
|
||||
/** Find orthogonal factor Q of rank 1 (or less) M **/
|
||||
static void do_rank1(HMatrix M, HMatrix Q)
|
||||
{
|
||||
float v1[3], v2[3], s;
|
||||
int col;
|
||||
mat_copy(Q,=,mat_id,4);
|
||||
/* If rank(M) is 1, we should find a non-zero column in M */
|
||||
col = find_max_col(M);
|
||||
if (col<0) return; /* Rank is 0 */
|
||||
v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
|
||||
make_reflector(v1, v1); reflect_cols(M, v1);
|
||||
v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
|
||||
make_reflector(v2, v2); reflect_rows(M, v2);
|
||||
s = M[2][2];
|
||||
if (s<0.0) Q[2][2] = -1.0;
|
||||
reflect_cols(Q, v1); reflect_rows(Q, v2);
|
||||
}
|
||||
|
||||
/** Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose **/
|
||||
static void do_rank2(HMatrix M, HMatrix MadjT, HMatrix Q)
|
||||
{
|
||||
float v1[3], v2[3];
|
||||
float w, x, y, z, c, s, d;
|
||||
int col;
|
||||
/* If rank(M) is 2, we should find a non-zero column in MadjT */
|
||||
col = find_max_col(MadjT);
|
||||
if (col<0) {do_rank1(M, Q); return;} /* Rank<2 */
|
||||
v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
|
||||
make_reflector(v1, v1); reflect_cols(M, v1);
|
||||
vcross(M[0], M[1], v2);
|
||||
make_reflector(v2, v2); reflect_rows(M, v2);
|
||||
w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
|
||||
if (w*z>x*y) {
|
||||
c = z+w; s = y-x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
|
||||
Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
|
||||
} else {
|
||||
c = z-w; s = y+x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
|
||||
Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
|
||||
}
|
||||
Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
|
||||
reflect_cols(Q, v1); reflect_rows(Q, v2);
|
||||
}
|
||||
|
||||
|
||||
/******* Polar Decomposition *******/
|
||||
|
||||
/* Polar Decomposition of 3x3 matrix in 4x4,
|
||||
* M = QS. See Nicholas Higham and Robert S. Schreiber,
|
||||
* Fast Polar Decomposition of An Arbitrary Matrix,
|
||||
* Technical Report 88-942, October 1988,
|
||||
* Department of Computer Science, Cornell University.
|
||||
*/
|
||||
static float polar_decomp(HMatrix M, HMatrix Q, HMatrix S)
|
||||
{
|
||||
#define TOL 1.0e-6
|
||||
HMatrix Mk, MadjTk, Ek;
|
||||
float det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
|
||||
int i, j;
|
||||
mat_tpose(Mk,=,M,3);
|
||||
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
|
||||
do {
|
||||
adjoint_transpose(Mk, MadjTk);
|
||||
det = vdot(Mk[0], MadjTk[0]);
|
||||
if (det==0.0) {do_rank2(Mk, MadjTk, Mk); break;}
|
||||
MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk);
|
||||
gamma = sqrt(sqrt((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(det));
|
||||
g1 = gamma*0.5;
|
||||
g2 = 0.5/(gamma*det);
|
||||
mat_copy(Ek,=,Mk,3);
|
||||
mat_binop(Mk,=,g1*Mk,+,g2*MadjTk,3);
|
||||
mat_copy(Ek,-=,Mk,3);
|
||||
E_one = norm_one(Ek);
|
||||
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
|
||||
} while (E_one>(M_one*TOL));
|
||||
mat_tpose(Q,=,Mk,3); mat_pad(Q);
|
||||
mat_mult(Mk, M, S); mat_pad(S);
|
||||
for (i=0; i<3; i++) for (j=i; j<3; j++)
|
||||
S[i][j] = S[j][i] = 0.5*(S[i][j]+S[j][i]);
|
||||
return (det);
|
||||
}
|
||||
|
||||
|
||||
/******* Spectral Decomposition *******/
|
||||
|
||||
/* Compute the spectral decomposition of symmetric positive semi-definite S.
|
||||
* Returns rotation in U and scale factors in result, so that if K is a diagonal
|
||||
* matrix of the scale factors, then S = U K (U transpose). Uses Jacobi method.
|
||||
* See Gene H. Golub and Charles F. Van Loan. Matrix Computations. Hopkins 1983.
|
||||
*/
|
||||
static HVect spect_decomp(HMatrix S, HMatrix U)
|
||||
{
|
||||
HVect kv;
|
||||
double Diag[3],OffD[3]; /* OffD is off-diag (by omitted index) */
|
||||
double g,h,fabsh,fabsOffDi,t,theta,c,s,tau,ta,OffDq,a,b;
|
||||
static char nxt[] = {Y,Z,X};
|
||||
int sweep, i, j;
|
||||
mat_copy(U,=,mat_id,4);
|
||||
Diag[X] = S[X][X]; Diag[Y] = S[Y][Y]; Diag[Z] = S[Z][Z];
|
||||
OffD[X] = S[Y][Z]; OffD[Y] = S[Z][X]; OffD[Z] = S[X][Y];
|
||||
for (sweep=20; sweep>0; sweep--) {
|
||||
float sm = fabs(OffD[X])+fabs(OffD[Y])+fabs(OffD[Z]);
|
||||
if (sm==0.0) break;
|
||||
for (i=Z; i>=X; i--) {
|
||||
int p = nxt[i]; int q = nxt[p];
|
||||
fabsOffDi = fabs(OffD[i]);
|
||||
g = 100.0*fabsOffDi;
|
||||
if (fabsOffDi>0.0) {
|
||||
h = Diag[q] - Diag[p];
|
||||
fabsh = fabs(h);
|
||||
if (fabsh+g==fabsh) {
|
||||
t = OffD[i]/h;
|
||||
} else {
|
||||
theta = 0.5*h/OffD[i];
|
||||
t = 1.0/(fabs(theta)+sqrt(theta*theta+1.0));
|
||||
if (theta<0.0) t = -t;
|
||||
}
|
||||
c = 1.0/sqrt(t*t+1.0); s = t*c;
|
||||
tau = s/(c+1.0);
|
||||
ta = t*OffD[i]; OffD[i] = 0.0;
|
||||
Diag[p] -= ta; Diag[q] += ta;
|
||||
OffDq = OffD[q];
|
||||
OffD[q] -= s*(OffD[p] + tau*OffD[q]);
|
||||
OffD[p] += s*(OffDq - tau*OffD[p]);
|
||||
for (j=Z; j>=X; j--) {
|
||||
a = U[j][p]; b = U[j][q];
|
||||
U[j][p] -= s*(b + tau*a);
|
||||
U[j][q] += s*(a - tau*b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
kv.x = Diag[X]; kv.y = Diag[Y]; kv.z = Diag[Z]; kv.w = 1.0;
|
||||
return (kv);
|
||||
}
|
||||
|
||||
/******* Spectral Axis Adjustment *******/
|
||||
|
||||
/* Given a unit Quaternernion, q, and a scale vector, k, find a unit Quaternernion, p,
|
||||
* which permutes the axes and turns freely in the plane of duplicate scale
|
||||
* factors, such that q p has the largest possible w component, i.e. the
|
||||
* smallest possible angle. Permutes k's components to go with q p instead of q.
|
||||
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
|
||||
* Proceedings of Graphics Interface 1992. Details on p. 262-263.
|
||||
*/
|
||||
static Quatern snuggle(Quatern q, HVect *k)
|
||||
{
|
||||
#define SQRTHALF (0.7071067811865475244f)
|
||||
#define sgn(n,v) ((n)?-(v):(v))
|
||||
#define swap(a,i,j) {a[3]=a[i]; a[i]=a[j]; a[j]=a[3];}
|
||||
#define cycle(a,p) if (p) {a[3]=a[0]; a[0]=a[1]; a[1]=a[2]; a[2]=a[3];}\
|
||||
else {a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; a[0]=a[3];}
|
||||
Quatern p;
|
||||
float ka[4];
|
||||
int i, turn = -1;
|
||||
ka[X] = k->x; ka[Y] = k->y; ka[Z] = k->z;
|
||||
if (ka[X]==ka[Y]) {if (ka[X]==ka[Z]) turn = W; else turn = Z;}
|
||||
else {if (ka[X]==ka[Z]) turn = Y; else if (ka[Y]==ka[Z]) turn = X;}
|
||||
if (turn>=0) {
|
||||
Quatern qtoz, qp;
|
||||
unsigned neg[3], win;
|
||||
double mag[3], t;
|
||||
static Quatern qxtoz = {0,SQRTHALF,0,SQRTHALF};
|
||||
static Quatern qytoz = {SQRTHALF,0,0,SQRTHALF};
|
||||
static Quatern qppmm = { 0.5, 0.5,-0.5,-0.5};
|
||||
static Quatern qpppp = { 0.5, 0.5, 0.5, 0.5};
|
||||
static Quatern qmpmm = {-0.5, 0.5,-0.5,-0.5};
|
||||
static Quatern qpppm = { 0.5, 0.5, 0.5,-0.5};
|
||||
static Quatern q0001 = { 0.0, 0.0, 0.0, 1.0};
|
||||
static Quatern q1000 = { 1.0, 0.0, 0.0, 0.0};
|
||||
switch (turn) {
|
||||
default: return (Qt_Conj(q));
|
||||
case X: q = Qt_Mul(q, qtoz = qxtoz); swap(ka,X,Z); break;
|
||||
case Y: q = Qt_Mul(q, qtoz = qytoz); swap(ka,Y,Z); break;
|
||||
case Z: qtoz = q0001; break;
|
||||
}
|
||||
q = Qt_Conj(q);
|
||||
mag[0] = (double)q.z*q.z+(double)q.w*q.w-0.5;
|
||||
mag[1] = (double)q.x*q.z-(double)q.y*q.w;
|
||||
mag[2] = (double)q.y*q.z+(double)q.x*q.w;
|
||||
for (i=0; i<3; i++) if (neg[i] = (mag[i]<0.0)) mag[i] = -mag[i];
|
||||
if (mag[0]>mag[1]) {if (mag[0]>mag[2]) win = 0; else win = 2;}
|
||||
else {if (mag[1]>mag[2]) win = 1; else win = 2;}
|
||||
switch (win) {
|
||||
case 0: if (neg[0]) p = q1000; else p = q0001; break;
|
||||
case 1: if (neg[1]) p = qppmm; else p = qpppp; cycle(ka,0); break;
|
||||
case 2: if (neg[2]) p = qmpmm; else p = qpppm; cycle(ka,1); break;
|
||||
}
|
||||
qp = Qt_Mul(q, p);
|
||||
t = sqrt(mag[win]+0.5);
|
||||
p = Qt_Mul(p, Qt_(0.0,0.0,-qp.z/t,qp.w/t));
|
||||
p = Qt_Mul(qtoz, Qt_Conj(p));
|
||||
} else {
|
||||
float qa[4], pa[4];
|
||||
unsigned lo, hi, neg[4], par = 0;
|
||||
double all, big, two;
|
||||
qa[0] = q.x; qa[1] = q.y; qa[2] = q.z; qa[3] = q.w;
|
||||
for (i=0; i<4; i++) {
|
||||
pa[i] = 0.0;
|
||||
if (neg[i] = (qa[i]<0.0)) qa[i] = -qa[i];
|
||||
par ^= neg[i];
|
||||
}
|
||||
/* Find two largest components, indices in hi and lo */
|
||||
if (qa[0]>qa[1]) lo = 0; else lo = 1;
|
||||
if (qa[2]>qa[3]) hi = 2; else hi = 3;
|
||||
if (qa[lo]>qa[hi]) {
|
||||
if (qa[lo^1]>qa[hi]) {hi = lo; lo ^= 1;}
|
||||
else {hi ^= lo; lo ^= hi; hi ^= lo;}
|
||||
} else {if (qa[hi^1]>qa[lo]) lo = hi^1;}
|
||||
all = (qa[0]+qa[1]+qa[2]+qa[3])*0.5;
|
||||
two = (qa[hi]+qa[lo])*SQRTHALF;
|
||||
big = qa[hi];
|
||||
if (all>two) {
|
||||
if (all>big) {/*all*/
|
||||
{int i; for (i=0; i<4; i++) pa[i] = sgn(neg[i], 0.5);}
|
||||
cycle(ka,par)
|
||||
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
|
||||
} else {
|
||||
if (two>big) {/*two*/
|
||||
pa[hi] = sgn(neg[hi],SQRTHALF); pa[lo] = sgn(neg[lo], SQRTHALF);
|
||||
if (lo>hi) {hi ^= lo; lo ^= hi; hi ^= lo;}
|
||||
if (hi==W) {hi = "\001\002\000"[lo]; lo = 3-hi-lo;}
|
||||
swap(ka,hi,lo)
|
||||
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
|
||||
}
|
||||
p.x = -pa[0]; p.y = -pa[1]; p.z = -pa[2]; p.w = pa[3];
|
||||
}
|
||||
k->x = ka[X]; k->y = ka[Y]; k->z = ka[Z];
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
||||
/******* Decompose Affine Matrix *******/
|
||||
|
||||
/* Decompose 4x4 affine matrix A as TFRUK(U transpose), where t contains the
|
||||
* translation components, q contains the rotation R, u contains U, k contains
|
||||
* scale factors, and f contains the sign of the determinant.
|
||||
* Assumes A transforms column vectors in right-handed coordinates.
|
||||
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
|
||||
* Proceedings of Graphics Interface 1992.
|
||||
*/
|
||||
static void decomp_affine(HMatrix A, SAffineParts *parts)
|
||||
{
|
||||
HMatrix Q, S, U;
|
||||
Quatern p;
|
||||
float det;
|
||||
parts->t = Qt_(A[X][W], A[Y][W], A[Z][W], 0);
|
||||
det = polar_decomp(A, Q, S);
|
||||
if (det<0.0) {
|
||||
mat_copy(Q,=,-Q,3);
|
||||
parts->f = -1;
|
||||
} else parts->f = 1;
|
||||
parts->q = Qt_FromMatrix(Q);
|
||||
parts->k = spect_decomp(S, U);
|
||||
parts->u = Qt_FromMatrix(U);
|
||||
p = snuggle(parts->u, &parts->k);
|
||||
parts->u = Qt_Mul(parts->u, p);
|
||||
}
|
||||
|
||||
static void spectral_decomp_affine(HMatrix A, SAffineParts *parts)
|
||||
{
|
||||
HMatrix Q, S, U;
|
||||
float det;
|
||||
|
||||
parts->t = Qt_(A[X][W], A[Y][W], A[Z][W], 0);
|
||||
det = polar_decomp(A, Q, S);
|
||||
if (det<0.0) {
|
||||
mat_copy(Q,=,-Q,3);
|
||||
parts->f = -1;
|
||||
} else parts->f = 1;
|
||||
parts->q = Qt_FromMatrix(Q);
|
||||
parts->k = spect_decomp(S, U);
|
||||
parts->u = Qt_FromMatrix(U);
|
||||
}
|
||||
|
||||
/******* Invert Affine Decomposition *******/
|
||||
|
||||
/* Compute inverse of affine decomposition.
|
||||
*/
|
||||
static void invert_affine(SAffineParts *parts, SAffineParts *inverse)
|
||||
{
|
||||
Quatern t, p;
|
||||
inverse->f = parts->f;
|
||||
inverse->q = Qt_Conj(parts->q);
|
||||
inverse->u = Qt_Mul(parts->q, parts->u);
|
||||
inverse->k.x = (parts->k.x==0.0) ? 0.0 : 1.0/parts->k.x;
|
||||
inverse->k.y = (parts->k.y==0.0) ? 0.0 : 1.0/parts->k.y;
|
||||
inverse->k.z = (parts->k.z==0.0) ? 0.0 : 1.0/parts->k.z;
|
||||
inverse->k.w = parts->k.w;
|
||||
t = Qt_(-parts->t.x, -parts->t.y, -parts->t.z, 0);
|
||||
t = Qt_Mul(Qt_Conj(inverse->u), Qt_Mul(t, inverse->u));
|
||||
t = Qt_(inverse->k.x*t.x, inverse->k.y*t.y, inverse->k.z*t.z, 0);
|
||||
p = Qt_Mul(inverse->q, inverse->u);
|
||||
t = Qt_Mul(p, Qt_Mul(t, Qt_Conj(p)));
|
||||
inverse->t = (inverse->f>0.0) ? t : Qt_(-t.x, -t.y, -t.z, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
void AffineParts::invert() {
|
||||
SAffineParts parts,inverse;
|
||||
|
||||
parts.q.w = q.w; parts.q.x = q.x; parts.q.y = q.y; parts.q.z = q.z;
|
||||
//parts.u.w = u.w; parts.u.x = u.x; parts.u.y = u.y; parts.u.z = u.z;
|
||||
parts.u.w = 0; parts.u.x = 1; parts.u.y = 0; parts.u.z = 0;
|
||||
parts.t.x = t.x; parts.t.y = t.y; parts.t.z = t.z;
|
||||
parts.k.x = k.x; parts.k.y = k.y; parts.k.z = k.z;
|
||||
//parts.f = f;
|
||||
parts.f = 1;
|
||||
|
||||
invert_affine( &parts,&inverse );
|
||||
|
||||
q.set( inverse.q.w,inverse.q.x,inverse.q.y,inverse.q.z );
|
||||
// u.set( inverse.u.w,inverse.u.x,inverse.u.y,inverse.u.z );
|
||||
t.set( inverse.t.x,inverse.t.y,inverse.t.z );
|
||||
k.set( inverse.k.x,inverse.k.y,inverse.k.z );
|
||||
// f = inverse.f;
|
||||
}
|
||||
*/
|
||||
|
||||
// Decompose matrix to affine parts.
|
||||
void AffineParts::Decompose( const Matrix44 &tm )
|
||||
{
|
||||
SAffineParts parts;
|
||||
HMatrix H;
|
||||
|
||||
H[X][X] = tm[0][0];
|
||||
H[X][Y] = tm[1][0];
|
||||
H[X][Z] = tm[2][0];
|
||||
|
||||
H[Y][X] = tm[0][1];
|
||||
H[Y][Y] = tm[1][1];
|
||||
H[Y][Z] = tm[2][1];
|
||||
|
||||
H[Z][X] = tm[0][2];
|
||||
H[Z][Y] = tm[1][2];
|
||||
H[Z][Z] = tm[2][2];
|
||||
|
||||
H[X][W] = tm[3][0];
|
||||
H[Y][W] = tm[3][1];
|
||||
H[Z][W] = tm[3][2];
|
||||
|
||||
decomp_affine( H,&parts );
|
||||
|
||||
rot = Quat( parts.q.w,parts.q.x,parts.q.y,parts.q.z );
|
||||
rotScale = Quat( parts.u.w,parts.u.x,parts.u.y,parts.u.z );
|
||||
pos = Vec3( parts.t.x,parts.t.y,parts.t.z );
|
||||
scale = Vec3( parts.k.x,parts.k.y,parts.k.z );
|
||||
fDet = parts.f;
|
||||
}
|
||||
|
||||
// Spectral matrix decompostion to affine parts.
|
||||
void AffineParts::SpectralDecompose( const Matrix44 &tm )
|
||||
{
|
||||
SAffineParts parts;
|
||||
HMatrix H;
|
||||
|
||||
H[X][X] = tm[0][0];
|
||||
H[X][Y] = tm[1][0];
|
||||
H[X][Z] = tm[2][0];
|
||||
|
||||
H[Y][X] = tm[0][1];
|
||||
H[Y][Y] = tm[1][1];
|
||||
H[Y][Z] = tm[2][1];
|
||||
|
||||
H[Z][X] = tm[0][2];
|
||||
H[Z][Y] = tm[1][2];
|
||||
H[Z][Z] = tm[2][2];
|
||||
|
||||
H[X][W] = tm[3][0];
|
||||
H[Y][W] = tm[3][1];
|
||||
H[Z][W] = tm[3][2];
|
||||
|
||||
spectral_decomp_affine( H,&parts );
|
||||
|
||||
rot = Quat( parts.q.w,parts.q.x,parts.q.y,parts.q.z );
|
||||
rotScale = Quat( parts.u.w,parts.u.x,parts.u.y,parts.u.z );
|
||||
pos = Vec3( parts.t.x,parts.t.y,parts.t.z );
|
||||
scale = Vec3( parts.k.x,parts.k.y,parts.k.z );
|
||||
fDet = parts.f;
|
||||
}
|
||||
41
Editor/Util/AffineParts.h
Normal file
41
Editor/Util/AffineParts.h
Normal file
@@ -0,0 +1,41 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: affineparts.h
|
||||
// Version: v1.00
|
||||
// Created: 19/8/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __affineparts_h__
|
||||
#define __affineparts_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
struct AffineParts
|
||||
{
|
||||
Vec3 pos; //!< Translation components
|
||||
Quat rot; //!< Essential rotation.
|
||||
Quat rotScale; //!< Stretch rotation.
|
||||
Vec3 scale; //!< Stretch factors.
|
||||
float fDet; //!< Sign of determinant.
|
||||
|
||||
/** Decompose matrix to its affnie parts.
|
||||
*/
|
||||
void Decompose( const Matrix44 &mat );
|
||||
|
||||
/** Decompose matrix to its affnie parts.
|
||||
Assume there`s no stretch rotation.
|
||||
*/
|
||||
void SpectralDecompose( const Matrix44 &mat );
|
||||
};
|
||||
|
||||
#endif // __affineparts_h__
|
||||
156
Editor/Util/BBox.cpp
Normal file
156
Editor/Util/BBox.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bbox.cpp
|
||||
// Version: v1.00
|
||||
// Created: 2/7/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "BBox.h"
|
||||
|
||||
typedef unsigned int udword;
|
||||
|
||||
// Integer representation of a floating-Vec3 value.
|
||||
#define IR(x) ((udword&)x)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* A method to compute a ray-AABB intersection.
|
||||
* Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
|
||||
* Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
|
||||
* Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
|
||||
*
|
||||
* Hence this version is faster as well as more robust than the original one.
|
||||
*
|
||||
* Should work provided:
|
||||
* 1) the integer representation of 0.0f is 0x00000000
|
||||
* 2) the sign bit of the float is the most significant one
|
||||
*
|
||||
* Report bugs: p.terdiman@codercorner.com
|
||||
*
|
||||
* \param aabb [in] the axis-aligned bounding box
|
||||
* \param origin [in] ray origin
|
||||
* \param dir [in] ray direction
|
||||
* \param coord [out] impact coordinates
|
||||
* \return true if ray intersects AABB
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define RAYAABB_EPSILON 0.00001f
|
||||
bool BBox::IsIntersectRay( const Vec3& vOrigin, const Vec3& vDir, Vec3& pntContact )
|
||||
{
|
||||
BOOL Inside = TRUE;
|
||||
float MinB[3] = { min.x,min.y,min.z };
|
||||
float MaxB[3] = { max.x,max.y,max.z };
|
||||
float MaxT[3];
|
||||
MaxT[0]=MaxT[1]=MaxT[2]=-1.0f;
|
||||
float coord[3] = { 0,0,0 };
|
||||
|
||||
float origin[3] = { vOrigin.x,vOrigin.y,vOrigin.z };
|
||||
float dir[3] = { vDir.x,vDir.y,vDir.z };
|
||||
|
||||
// Find candidate planes.
|
||||
for(udword i=0;i<3;i++)
|
||||
{
|
||||
if(origin[i] < MinB[i])
|
||||
{
|
||||
coord[i] = MinB[i];
|
||||
Inside = FALSE;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if(IR(dir[i])) MaxT[i] = (MinB[i] - origin[i]) / dir[i];
|
||||
}
|
||||
else if(origin[i] > MaxB[i])
|
||||
{
|
||||
coord[i] = MaxB[i];
|
||||
Inside = FALSE;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if(IR(dir[i])) MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Ray origin inside bounding box
|
||||
if(Inside)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Timur: for editor this need to be treated as intersection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
pntContact(origin[0],origin[1],origin[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get largest of the maxT's for final choice of intersection
|
||||
udword WhichPlane = 0;
|
||||
if(MaxT[1] > MaxT[WhichPlane]) WhichPlane = 1;
|
||||
if(MaxT[2] > MaxT[WhichPlane]) WhichPlane = 2;
|
||||
|
||||
// Check final candidate actually inside box
|
||||
if(IR(MaxT[WhichPlane])&0x80000000) return false;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
if(i!=WhichPlane)
|
||||
{
|
||||
coord[i] = origin[i] + MaxT[WhichPlane] * dir[i];
|
||||
#ifdef RAYAABB_EPSILON
|
||||
if(coord[i] < MinB[i] - RAYAABB_EPSILON || coord[i] > MaxB[i] + RAYAABB_EPSILON) return false;
|
||||
#else
|
||||
if(coord[i] < MinB[i] || coord[i] > MaxB[i]) return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
pntContact(coord[0],coord[1],coord[2]);
|
||||
return true; // ray hits box
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BBox::RayEdgeIntersection( const Vec3 &raySrc,const Vec3 &rayDir,float epsilonDist,float &dist,Vec3 &intPnt )
|
||||
{
|
||||
// Check 6 group lines.
|
||||
Vec3 rayTrg = raySrc + rayDir*10000.0f;
|
||||
Vec3 pnt[12];
|
||||
|
||||
float d[12];
|
||||
|
||||
// Near
|
||||
d[0] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,max.z),Vec3(max.x,min.y,max.z),pnt[0] );
|
||||
d[1] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,max.z),Vec3(max.x,max.y,max.z),pnt[1] );
|
||||
d[2] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,max.z),Vec3(min.x,max.y,max.z),pnt[2] );
|
||||
d[3] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,max.z),Vec3(max.x,max.y,max.z),pnt[3] );
|
||||
|
||||
// Far
|
||||
d[4] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(max.x,min.y,min.z),pnt[4] );
|
||||
d[5] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,min.z),Vec3(max.x,max.y,min.z),pnt[5] );
|
||||
d[6] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(min.x,max.y,min.z),pnt[6] );
|
||||
d[7] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,min.z),Vec3(max.x,max.y,min.z),pnt[7] );
|
||||
|
||||
// Sides.
|
||||
d[8] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(min.x,min.y,max.z),pnt[8] );
|
||||
d[9] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,min.z),Vec3(max.x,min.y,max.z),pnt[9] );
|
||||
d[10] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,min.z),Vec3(min.x,max.y,max.z),pnt[10] );
|
||||
d[11] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,max.y,min.z),Vec3(max.x,max.y,max.z),pnt[11] );
|
||||
|
||||
dist = FLT_MAX;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (d[i] < dist)
|
||||
{
|
||||
dist = d[i];
|
||||
intPnt = pnt[i];
|
||||
}
|
||||
}
|
||||
if (dist < epsilonDist)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
122
Editor/Util/BBox.h
Normal file
122
Editor/Util/BBox.h
Normal file
@@ -0,0 +1,122 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bbox.h
|
||||
// Version: v1.00
|
||||
// Created: 2/7/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __bbox_h__
|
||||
#define __bbox_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* BBox is a bounding box structure.
|
||||
*/
|
||||
struct BBox
|
||||
{
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
|
||||
BBox() {}
|
||||
BBox( const Vec3 &vMin,const Vec3 &vMax ) { min = vMin; max = vMax; }
|
||||
void Reset()
|
||||
{
|
||||
min = Vec3d( 100000,100000,100000 );
|
||||
max = Vec3d( -100000,-100000,-100000 );
|
||||
}
|
||||
void Add( const Vec3 &v )
|
||||
{
|
||||
min.x = __min( min.x,v.x );
|
||||
min.y = __min( min.y,v.y );
|
||||
min.z = __min( min.z,v.z );
|
||||
|
||||
max.x = __max( max.x,v.x );
|
||||
max.y = __max( max.y,v.y );
|
||||
max.z = __max( max.z,v.z );
|
||||
}
|
||||
|
||||
bool IsOverlapSphereBounds( const Vec3 &pos,float radius ) const
|
||||
{
|
||||
if (pos.x > min.x && pos.x < max.x &&
|
||||
pos.y > min.y && pos.y < max.y &&
|
||||
pos.z > min.z && pos.z < max.z)
|
||||
return true;
|
||||
|
||||
if (pos.x+radius < min.x) return false;
|
||||
if (pos.y+radius < min.y) return false;
|
||||
if (pos.z+radius < min.z) return false;
|
||||
if (pos.x-radius > max.x) return false;
|
||||
if (pos.y-radius > max.y) return false;
|
||||
if (pos.z-radius > max.z) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsContainSphere( const Vec3 &pos,float radius ) const
|
||||
{
|
||||
if (pos.x-radius < min.x) return false;
|
||||
if (pos.y-radius < min.y) return false;
|
||||
if (pos.z-radius < min.z) return false;
|
||||
if (pos.x+radius > max.x) return false;
|
||||
if (pos.y+radius > max.y) return false;
|
||||
if (pos.z+radius > max.z) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return IsEquivalent(min,max,VEC_EPSILON); }
|
||||
|
||||
// Check two ortogonal bounding boxes for intersection.
|
||||
inline bool IsIntersectBox( const BBox &b ) const
|
||||
{
|
||||
// Check for intersection on X axis.
|
||||
if ((min.x > b.max.x)||(b.min.x > max.x)) return false;
|
||||
// Check for intersection on Y axis.
|
||||
if ((min.y > b.max.y)||(b.min.y > max.y)) return false;
|
||||
// Check for intersection on Z axis.
|
||||
if ((min.z > b.max.z)||(b.min.z > max.z)) return false;
|
||||
|
||||
// Boxes intersect in all 3 axises.
|
||||
return true;
|
||||
}
|
||||
|
||||
void Transform( const Matrix44 &tm )
|
||||
{
|
||||
Vec3 m = tm.TransformPointOLD( min );
|
||||
Vec3 vx = Vec3(tm[0][0],tm[0][1],tm[0][2])*(max.x-min.x);
|
||||
Vec3 vy = Vec3(tm[1][0],tm[1][1],tm[1][2])*(max.y-min.y);
|
||||
Vec3 vz = Vec3(tm[2][0],tm[2][1],tm[2][2])*(max.z-min.z);
|
||||
min = m;
|
||||
max = m;
|
||||
if (vx.x < 0) min.x += vx.x; else max.x += vx.x;
|
||||
if (vx.y < 0) min.y += vx.y; else max.y += vx.y;
|
||||
if (vx.z < 0) min.z += vx.z; else max.z += vx.z;
|
||||
|
||||
if (vy.x < 0) min.x += vy.x; else max.x += vy.x;
|
||||
if (vy.y < 0) min.y += vy.y; else max.y += vy.y;
|
||||
if (vy.z < 0) min.z += vy.z; else max.z += vy.z;
|
||||
|
||||
if (vz.x < 0) min.x += vz.x; else max.x += vz.x;
|
||||
if (vz.y < 0) min.y += vz.y; else max.y += vz.y;
|
||||
if (vz.z < 0) min.z += vz.z; else max.z += vz.z;
|
||||
}
|
||||
|
||||
bool IsIntersectRay( const Vec3 &origin,const Vec3 &dir,Vec3 &pntContact );
|
||||
|
||||
//! Check if ray intersect edge of bounding box.
|
||||
//! @param epsilonDist if distance between ray and egde is less then this epsilon then edge was intersected.
|
||||
//! @param dist Distance between ray and edge.
|
||||
//! @param intPnt intersection point.
|
||||
bool RayEdgeIntersection( const Vec3 &raySrc,const Vec3 &rayDir,float epsilonDist,float &dist,Vec3 &intPnt );
|
||||
};
|
||||
|
||||
#endif // __bbox_h__
|
||||
130
Editor/Util/ChunkFile.cpp
Normal file
130
Editor/Util/ChunkFile.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: chunkfile.cpp
|
||||
// Version: v1.00
|
||||
// Created: 15/12/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#include "CryHeaders.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CChunkFile implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CChunkFile::CChunkFile()
|
||||
{
|
||||
m_fileHeader.FileType = FileType_Geom;
|
||||
m_fileHeader.ChunkTableOffset = -1;
|
||||
m_fileHeader.Version = GeomFileVersion;
|
||||
|
||||
strcpy(m_fileHeader.Signature,FILE_SIGNATURE);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CChunkFile::~CChunkFile()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CChunkFile::Write( const char *filename )
|
||||
{
|
||||
FILE *file = fopen( filename,"wb" );
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
unsigned i;
|
||||
|
||||
fseek( file,sizeof(m_fileHeader),SEEK_SET );
|
||||
|
||||
for(i=0;i<m_chunks.size();i++)
|
||||
{
|
||||
int ofs = ftell(file);
|
||||
// write header.
|
||||
ChunkDesc &ch = m_chunks[i];
|
||||
ch.hdr.FileOffset = ofs;
|
||||
memcpy( ch.data->GetBuffer(),&ch.hdr,sizeof(ch.hdr) );
|
||||
// write data.
|
||||
fwrite( ch.data->GetBuffer(),ch.data->GetSize(),1,file );
|
||||
}
|
||||
|
||||
int chunkTableOffset = ftell(file);
|
||||
|
||||
//=======================
|
||||
//Write # of Chunks
|
||||
//=======================
|
||||
unsigned nch = m_chunks.size();
|
||||
if (fwrite(&nch,sizeof(nch),1,file) !=1)
|
||||
return false;
|
||||
|
||||
//=======================
|
||||
//Write Chunk List
|
||||
//=======================
|
||||
for(i=0;i<nch;i++)
|
||||
{
|
||||
CHUNK_HEADER &hdr = m_chunks[i].hdr;
|
||||
if (fwrite(&hdr,sizeof(hdr),1,file)!=1)
|
||||
return false;
|
||||
}
|
||||
|
||||
//update Header for chunk list offset
|
||||
m_fileHeader.ChunkTableOffset = chunkTableOffset;
|
||||
fseek(file,0,SEEK_SET);
|
||||
if (fwrite(&m_fileHeader,sizeof(m_fileHeader),1,file) != 1)
|
||||
return false;
|
||||
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CChunkFile::ChunkDesc* CChunkFile::FindChunkByType( int type )
|
||||
{
|
||||
for(unsigned i=0; i<m_chunks.size();i++)
|
||||
{
|
||||
if (m_chunks[i].hdr.ChunkType == type)
|
||||
{
|
||||
return &m_chunks[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CChunkFile::ChunkDesc* CChunkFile::FindChunkById( int id )
|
||||
{
|
||||
for(unsigned i=0; i<m_chunks.size();i++)
|
||||
{
|
||||
if (m_chunks[i].hdr.ChunkID == id)
|
||||
{
|
||||
return &m_chunks[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CChunkFile::AddChunk( const CHUNK_HEADER &hdr,void *chunkData,int chunkSize )
|
||||
{
|
||||
ChunkDesc chunk;
|
||||
chunk.hdr = hdr;
|
||||
chunk.data = new CMemoryBlock;
|
||||
chunk.data->Allocate( chunkSize );
|
||||
chunk.data->Copy( chunkData,chunkSize );
|
||||
|
||||
int chunkID = m_chunks.size() + 1;
|
||||
chunk.hdr.ChunkID = chunkID;
|
||||
m_chunks.push_back( chunk );
|
||||
return chunkID;
|
||||
}
|
||||
|
||||
64
Editor/Util/ChunkFile.h
Normal file
64
Editor/Util/ChunkFile.h
Normal file
@@ -0,0 +1,64 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: chunkfile.h
|
||||
// Version: v1.00
|
||||
// Created: 15/12/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __chunkfile_h__
|
||||
#define __chunkfile_h__
|
||||
#pragma once
|
||||
|
||||
#include "CryHeaders.h"
|
||||
#include "MemoryBlock.h"
|
||||
|
||||
/** Chunk files used to save .cgf models.
|
||||
*/
|
||||
class CChunkFile
|
||||
{
|
||||
public:
|
||||
struct ChunkDesc
|
||||
{
|
||||
CHUNK_HEADER hdr;
|
||||
TSmartPtr<CMemoryBlock> data;
|
||||
|
||||
ChunkDesc() {}
|
||||
ChunkDesc( const ChunkDesc& d ) { *this = d; }
|
||||
ChunkDesc& operator=( const ChunkDesc &d )
|
||||
{
|
||||
hdr = d.hdr;
|
||||
data = d.data;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
CChunkFile();
|
||||
~CChunkFile();
|
||||
|
||||
bool Write( const char *filename );
|
||||
|
||||
//! Add chunk to file.
|
||||
//! @retun ChunkID of added chunk.
|
||||
int AddChunk( const CHUNK_HEADER &hdr,void *chunkData,int chunkSize );
|
||||
|
||||
private:
|
||||
ChunkDesc* FindChunkByType( int type );
|
||||
ChunkDesc* FindChunkById( int id );
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// variables.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
FILE_HEADER m_fileHeader;
|
||||
std::vector<ChunkDesc> m_chunks;
|
||||
};
|
||||
|
||||
#endif // __chunkfile_h__
|
||||
138
Editor/Util/DynamicArray2D.cpp
Normal file
138
Editor/Util/DynamicArray2D.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
// DynamicArray2D.cpp: Implementation of the class CDynamicArray.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DynamicArray2D.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction / destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CDynamicArray2D::CDynamicArray2D(unsigned int iDimension1, unsigned int iDimension2)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Declare a 2D array on the free store
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Save the position of the array dimensions
|
||||
m_Dimension1 = iDimension1;
|
||||
m_Dimension2 = iDimension2;
|
||||
|
||||
// First dimension
|
||||
m_Array = new float * [m_Dimension1];
|
||||
VERIFY(m_Array);
|
||||
|
||||
// Second dimension
|
||||
for (i=0; i<m_Dimension1; ++i)
|
||||
{
|
||||
m_Array[i] = new float[m_Dimension2];
|
||||
|
||||
// Init all fields with 0
|
||||
memset(&m_Array[i][0], 0, m_Dimension2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
CDynamicArray2D::~CDynamicArray2D()
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Remove the 2D array and all its sub arrays from the free store
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<m_Dimension1; ++i)
|
||||
delete [] m_Array[i];
|
||||
|
||||
delete [] m_Array;
|
||||
m_Array = 0;
|
||||
}
|
||||
|
||||
void CDynamicArray2D::ScaleImage(CDynamicArray2D *pDestination)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Scale an image stored (in an array class) to a new size
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i, j, iOldWidth;
|
||||
int iXSrcFl, iXSrcCe, iYSrcFl, iYSrcCe;
|
||||
float fXSrc, fYSrc;
|
||||
float fHeight[4];
|
||||
float fHeightWeight[4];
|
||||
float fHeightBottom;
|
||||
float fHeightTop;
|
||||
|
||||
assert(pDestination);
|
||||
assert(pDestination->m_Dimension1 > 1);
|
||||
|
||||
// Width has to be zero based, not a count
|
||||
iOldWidth = m_Dimension1 - 1;
|
||||
|
||||
// Loop trough each field of the new image and interpolate the value
|
||||
// from the source heightmap
|
||||
for (i=0; i<pDestination->m_Dimension1; i++)
|
||||
{
|
||||
// Calculate the average source array position
|
||||
fXSrc = i / (float) pDestination->m_Dimension1 * iOldWidth;
|
||||
assert(fXSrc >= 0.0f && fXSrc <= iOldWidth);
|
||||
|
||||
// Precalculate floor and ceiling values. Use fast asm integer floor and
|
||||
// fast asm float / integer conversion
|
||||
iXSrcFl = ifloor(fXSrc);
|
||||
iXSrcCe = FloatToIntRet((float) ceil(fXSrc));
|
||||
|
||||
// Distribution between left and right height values
|
||||
fHeightWeight[0] = (float) iXSrcCe - fXSrc;
|
||||
fHeightWeight[1] = fXSrc - (float) iXSrcFl;
|
||||
|
||||
// Avoid error when floor() and ceil() return the same value
|
||||
if (fHeightWeight[0] == 0.0f && fHeightWeight[1] == 0.0f)
|
||||
{
|
||||
fHeightWeight[0] = 0.5f;
|
||||
fHeightWeight[1] = 0.5f;
|
||||
}
|
||||
|
||||
for (j=0; j<pDestination->m_Dimension1; j++)
|
||||
{
|
||||
// Calculate the average source array position
|
||||
fYSrc = j / (float) pDestination->m_Dimension1 * iOldWidth;
|
||||
assert(fYSrc >= 0.0f && fYSrc <= iOldWidth);
|
||||
|
||||
// Precalculate floor and ceiling values. Use fast asm integer floor and
|
||||
// fast asm float / integer conversion
|
||||
iYSrcFl = ifloor(fYSrc);
|
||||
iYSrcCe = FloatToIntRet((float) ceil(fYSrc));
|
||||
|
||||
// Get the four nearest height values
|
||||
fHeight[0] = m_Array[iXSrcFl][iYSrcFl];
|
||||
fHeight[1] = m_Array[iXSrcCe][iYSrcFl];
|
||||
fHeight[2] = m_Array[iXSrcFl][iYSrcCe];
|
||||
fHeight[3] = m_Array[iXSrcCe][iYSrcCe];
|
||||
|
||||
// Calculate how much weight each height value has
|
||||
|
||||
// Distribution between top and bottom height values
|
||||
fHeightWeight[2] = (float) iYSrcCe - fYSrc;
|
||||
fHeightWeight[3] = fYSrc - (float) iYSrcFl;
|
||||
|
||||
// Avoid error when floor() and ceil() return the same value
|
||||
if (fHeightWeight[2] == 0.0f && fHeightWeight[3] == 0.0f)
|
||||
{
|
||||
fHeightWeight[2] = 0.5f;
|
||||
fHeightWeight[3] = 0.5f;
|
||||
}
|
||||
|
||||
// Interpolate between the four nearest height values
|
||||
|
||||
// Get the height for the given X position trough interpolation between
|
||||
// the left and the right height
|
||||
fHeightBottom = (fHeight[0] * fHeightWeight[0] + fHeight[1] * fHeightWeight[1]);
|
||||
fHeightTop = (fHeight[2] * fHeightWeight[0] + fHeight[3] * fHeightWeight[1]);
|
||||
|
||||
// Set the new value in the destination heightmap
|
||||
pDestination->m_Array[i][j] = fHeightBottom * fHeightWeight[2] + fHeightTop * fHeightWeight[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Editor/Util/DynamicArray2D.h
Normal file
25
Editor/Util/DynamicArray2D.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// DynamicArray2D.h: Interface of the class CDynamicArray.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_DYNAMICARRAY_H__3B36BCC2_AB88_11D1_8F4C_D0B67CC10B05__INCLUDED_)
|
||||
#define AFX_DYNAMICARRAY_H__3B36BCC2_AB88_11D1_8F4C_D0B67CC10B05__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class CDynamicArray2D
|
||||
{
|
||||
public:
|
||||
CDynamicArray2D(unsigned int iDimension1, unsigned int iDimension2);
|
||||
void ScaleImage(CDynamicArray2D *pDestination);
|
||||
virtual ~CDynamicArray2D();
|
||||
float **m_Array;
|
||||
|
||||
private:
|
||||
unsigned int m_Dimension1;
|
||||
unsigned int m_Dimension2;
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_DYNAMICARRAY_H__3B36BCC2_AB88_11D1_8F4C_D0B67CC10B05__INCLUDED_)
|
||||
68
Editor/Util/EditorUtils.cpp
Normal file
68
Editor/Util/EditorUtils.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: EditorUtils.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "EditorUtils.h"
|
||||
#include <malloc.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void HeapCheck::Check( const char *file,int line )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
/* Check heap status */
|
||||
int heapstatus = _heapchk();
|
||||
switch( heapstatus )
|
||||
{
|
||||
case _HEAPOK:
|
||||
break;
|
||||
case _HEAPEMPTY:
|
||||
break;
|
||||
case _HEAPBADBEGIN:
|
||||
{
|
||||
CString str;
|
||||
str.Format( "Bad Start of Heap, at file %s line:%d",file,line );
|
||||
MessageBox( NULL,str,"Heap Check",MB_OK );
|
||||
}
|
||||
break;
|
||||
case _HEAPBADNODE:
|
||||
{
|
||||
CString str;
|
||||
str.Format( "Bad Node in Heap, at file %s line:%d",file,line );
|
||||
MessageBox( NULL,str,"Heap Check",MB_OK );
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BOOL CMFCUtils::LoadTrueColorImageList( CImageList &imageList,UINT nIDResource,int nIconWidth,COLORREF colMaskColor )
|
||||
{
|
||||
CBitmap bitmap;
|
||||
BITMAP bmBitmap;
|
||||
if (!bitmap.Attach(LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nIDResource),IMAGE_BITMAP, 0, 0,LR_DEFAULTSIZE|LR_CREATEDIBSECTION)))
|
||||
return FALSE;
|
||||
if (!bitmap.GetBitmap(&bmBitmap))
|
||||
return FALSE;
|
||||
CSize cSize(bmBitmap.bmWidth, bmBitmap.bmHeight);
|
||||
RGBTRIPLE* rgb = (RGBTRIPLE*)(bmBitmap.bmBits);
|
||||
int nCount = cSize.cx/nIconWidth;
|
||||
if (!imageList.Create(nIconWidth, cSize.cy, ILC_COLOR24|ILC_MASK, nCount, 0))
|
||||
return FALSE;
|
||||
|
||||
if (imageList.Add(&bitmap,colMaskColor) == -1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
276
Editor/Util/EditorUtils.h
Normal file
276
Editor/Util/EditorUtils.h
Normal file
@@ -0,0 +1,276 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: EditorUtils.h
|
||||
// Version: v1.00
|
||||
// Created: 10/10/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Utility classes used by Editor.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __EditorUtils_h__
|
||||
#define __EditorUtils_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//! Typedef for vector.
|
||||
typedef Vec3d Vec3;
|
||||
|
||||
//! Typedef for quaternion.
|
||||
//typedef CryQuat Quat;
|
||||
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#define LINE_EPS (0.00001f)
|
||||
|
||||
template <class T> inline void ZeroStruct( T &t ) { memset( &t,0,sizeof(t) ); }
|
||||
|
||||
//! Checks heap for errors.
|
||||
struct HeapCheck
|
||||
{
|
||||
//! Runs consistency checks on the heap.
|
||||
static void Check( const char *file,int line );
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define HEAP_CHECK HeapCheck::Check( __FILE__,__LINE__ );
|
||||
#else
|
||||
#define HEAP_CHECK
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
* StdMap Wraps std::map to provide easier to use interface.
|
||||
*/
|
||||
template <class Key,class Value>
|
||||
struct StdMap
|
||||
{
|
||||
private:
|
||||
typedef std::map<Key,Value> Map;
|
||||
Map m;
|
||||
|
||||
public:
|
||||
typedef typename Map::iterator Iterator;
|
||||
typedef typename Map::const_iterator ConstIterator;
|
||||
|
||||
void Insert( const Key& key,const Value &value ) { m[key] = value; }
|
||||
int GetCount() const { return m.size(); };
|
||||
bool IsEmpty() const { return m.empty(); };
|
||||
void Clear() { m.clear(); }
|
||||
int Erase( const Key &key ) { return m.erase(key); };
|
||||
Value& operator[]( const Key &key ) { return m[key]; };
|
||||
bool Find( const Key& key,Value &value ) const
|
||||
{
|
||||
Map::const_iterator it = m.find(key);
|
||||
if (it == m.end())
|
||||
return false;
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
Iterator Find( const Key& key ) { return m.find(key); }
|
||||
ConstIterator Find( const Key& key ) const { return m.find(key); }
|
||||
|
||||
bool FindKeyByValue( const Value &value,Key& key ) const
|
||||
{
|
||||
for (Map::const_iterator it = m.begin(); it != m.end(); ++it)
|
||||
{
|
||||
if (it->second == value)
|
||||
{
|
||||
key = it->first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator Begin() { return m.begin(); };
|
||||
Iterator End() { return m.end(); };
|
||||
ConstIterator Begin() const { return m.begin(); };
|
||||
ConstIterator End() const { return m.end(); };
|
||||
|
||||
void GetAsVector( std::vector<Value> &array ) const
|
||||
{
|
||||
array.resize( m.size() );
|
||||
int i = 0;
|
||||
for (Map::const_iterator it = m.begin(); it != m.end(); ++it)
|
||||
array[i++] = it->second;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** This class keeps file version information.
|
||||
*/
|
||||
struct Version
|
||||
{
|
||||
int v[4];
|
||||
|
||||
Version() {
|
||||
v[0] = v[1] = v[2] = v[3] = 0;
|
||||
}
|
||||
Version( const int vers[] ) {
|
||||
v[0] = vers[0];
|
||||
v[1] = vers[1];
|
||||
v[2] = vers[2];
|
||||
v[3] = 1;
|
||||
}
|
||||
|
||||
explicit Version( const char* s )
|
||||
{
|
||||
v[0] = v[1] = v[2] = v[3] = 0;
|
||||
|
||||
char t[50]; char* p;
|
||||
strcpy(t,s);
|
||||
|
||||
if(!(p = strtok(t,"."))) return;
|
||||
v[3] = atoi(p);
|
||||
if(!(p = strtok(NULL,"."))) return;
|
||||
v[2] = atoi(p);
|
||||
if(!(p = strtok(NULL,"."))) return;
|
||||
v[1] = atoi(p);
|
||||
if(!(p = strtok(NULL,"."))) return;
|
||||
v[0] = atoi(p);
|
||||
}
|
||||
|
||||
bool operator <( const Version &v2 ) const {
|
||||
if (v[3] < v2.v[3]) return true;
|
||||
if (v[3] > v2.v[3]) return false;
|
||||
|
||||
if (v[2] < v2.v[2]) return true;
|
||||
if (v[2] > v2.v[2]) return false;
|
||||
|
||||
if (v[1] < v2.v[1]) return true;
|
||||
if (v[1] > v2.v[1]) return false;
|
||||
|
||||
if (v[0] < v2.v[0]) return true;
|
||||
if (v[0] > v2.v[0]) return false;
|
||||
return false;
|
||||
}
|
||||
bool operator ==( const Version &v1 ) const {
|
||||
if (v[0] == v1.v[0] && v[1] == v1.v[1] &&
|
||||
v[2] == v1.v[2] && v[3] == v1.v[3]) return true;
|
||||
return false;
|
||||
}
|
||||
bool operator >( const Version &v1) const {
|
||||
return !(*this < v1);
|
||||
}
|
||||
bool operator >=( const Version &v1) const {
|
||||
return (*this == v1) || (*this > v1);
|
||||
}
|
||||
bool operator <=( const Version &v1) const {
|
||||
return (*this == v1) || (*this < v1);
|
||||
}
|
||||
|
||||
int& operator[](int i) { return v[i];}
|
||||
int operator[](int i) const { return v[i];}
|
||||
|
||||
CString ToString() const {
|
||||
char s[1024];
|
||||
sprintf( s,"%d.%d.%d",v[2],v[1],v[0] );
|
||||
return s;
|
||||
}
|
||||
|
||||
CString ToFullString() const {
|
||||
char s[1024];
|
||||
sprintf( s,"%d.%d.%d.%d",v[3],v[2],v[1],v[0] );
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Convert String representation of color to RGB integer value.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline COLORREF String2Color( const CString &val )
|
||||
{
|
||||
unsigned int r=0,g=0,b=0;
|
||||
int res = 0;
|
||||
res = sscanf( val,"R:%d,G:%d,B:%d",&r,&g,&b );
|
||||
if (res != 3)
|
||||
res = sscanf( val,"R:%d G:%d B:%d",&r,&g,&b );
|
||||
if (res != 3)
|
||||
res = sscanf( val,"%d,%d,%d",&r,&g,&b );
|
||||
if (res != 3)
|
||||
res = sscanf( val,"%d %d %d",&r,&g,&b );
|
||||
if (res != 3)
|
||||
{
|
||||
sscanf( val,"%x",&r );
|
||||
return r;
|
||||
}
|
||||
|
||||
return RGB(r,g,b);
|
||||
}
|
||||
|
||||
// Converts COLORREF to Vector.
|
||||
inline Vec3 Rgb2Vec( COLORREF color )
|
||||
{
|
||||
return Vec3( GetRValue(color)/255.0f,GetGValue(color)/255.0f,GetBValue(color)/255.0f );
|
||||
}
|
||||
|
||||
// Converts COLORREF to Vector.
|
||||
inline COLORREF Vec2Rgb( const Vec3 &color )
|
||||
{
|
||||
return RGB( color.x*255,color.y*255,color.z*255 );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Tokenize string.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline CString TokenizeString( const CString &str,LPCSTR pszTokens, int& iStart )
|
||||
{
|
||||
assert( iStart >= 0 );
|
||||
|
||||
if( pszTokens == NULL )
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
LPCSTR pszPlace = (LPCSTR)str + iStart;
|
||||
LPCSTR pszEnd = (LPCSTR)str + str.GetLength();
|
||||
if( pszPlace < pszEnd )
|
||||
{
|
||||
int nIncluding = (int)strspn( pszPlace,pszTokens );;
|
||||
|
||||
if( (pszPlace+nIncluding) < pszEnd )
|
||||
{
|
||||
pszPlace += nIncluding;
|
||||
int nExcluding = (int)strcspn( pszPlace, pszTokens );
|
||||
|
||||
int iFrom = iStart+nIncluding;
|
||||
int nUntil = nExcluding;
|
||||
iStart = iFrom+nUntil+1;
|
||||
|
||||
return (str.Mid( iFrom, nUntil ) );
|
||||
}
|
||||
}
|
||||
|
||||
// return empty string, done tokenizing
|
||||
iStart = -1;
|
||||
return "";
|
||||
}
|
||||
|
||||
/*! Collection of Utility MFC functions.
|
||||
*/
|
||||
struct CMFCUtils
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Load true color image into image list.
|
||||
static BOOL LoadTrueColorImageList( CImageList &imageList,UINT nIDResource,int nIconWidth,COLORREF colMaskColor );
|
||||
};
|
||||
|
||||
#endif // __EditorUtils_h__
|
||||
|
||||
299
Editor/Util/FileChangeMonitor.cpp
Normal file
299
Editor/Util/FileChangeMonitor.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: filechangemonitor.cpp
|
||||
// Version: v1.00
|
||||
// Created: 15/11/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FileChangeMonitor.h"
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Util\FileUtil.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Directory monitoring thread.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct CFileChangeMonitorThread : public CThread
|
||||
{
|
||||
public:
|
||||
std::vector<HANDLE> m_handles;
|
||||
std::vector<CString> m_dirs;
|
||||
MTQueue<CString> m_files;
|
||||
HANDLE m_killEvent;
|
||||
DWORD m_mainThreadId;
|
||||
|
||||
|
||||
CFileChangeMonitorThread()
|
||||
{
|
||||
m_mainThreadId = GetCurrentThreadId();
|
||||
m_killEvent = ::CreateEvent( NULL,TRUE,FALSE,NULL );
|
||||
// First event in list is KillEvent.
|
||||
m_handles.push_back(m_killEvent);
|
||||
m_dirs.push_back("");
|
||||
}
|
||||
|
||||
~CFileChangeMonitorThread()
|
||||
{
|
||||
::CloseHandle( m_killEvent );
|
||||
m_killEvent = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
void FindChangedFiles( const CString &dir );
|
||||
|
||||
void Run()
|
||||
{
|
||||
DWORD dwWaitStatus;
|
||||
|
||||
int numHandles = m_handles.size();
|
||||
|
||||
// If First handle triggers, its quit.
|
||||
// Waiting thread.
|
||||
while (TRUE)
|
||||
{
|
||||
// Wait for notification.
|
||||
dwWaitStatus = WaitForMultipleObjects( numHandles,&m_handles[0],FALSE,INFINITE );
|
||||
|
||||
if (dwWaitStatus >= WAIT_OBJECT_0 && dwWaitStatus < WAIT_OBJECT_0+numHandles)
|
||||
{
|
||||
if (dwWaitStatus == WAIT_OBJECT_0)
|
||||
{
|
||||
// This is Thread Kill event.
|
||||
break;
|
||||
}
|
||||
// One of objects got triggered, find out which.
|
||||
int id = dwWaitStatus - WAIT_OBJECT_0;
|
||||
CString dir = m_dirs[id];
|
||||
|
||||
FindChangedFiles(dir);
|
||||
|
||||
// Now the intesting part.. we need to find which file have been changed.
|
||||
// The fastest way, is scan directoryto take current time
|
||||
|
||||
if (FindNextChangeNotification(m_handles[id]) == FALSE)
|
||||
{
|
||||
// Error!!!.
|
||||
//ExitProcess(GetLastError());
|
||||
}
|
||||
// Notify main thread that something have changed.
|
||||
PostThreadMessage( m_mainThreadId,WM_FILEMONITORCHANGE,0,0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Close all change notification handles.
|
||||
for (int i = 1; i < m_handles.size(); i++)
|
||||
{
|
||||
FindCloseChangeNotification(m_handles[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline void UnixTimeToFileTime(time_t t, LPFILETIME pft)
|
||||
{
|
||||
// Note that LONGLONG is a 64-bit value
|
||||
LONGLONG ll;
|
||||
|
||||
ll = Int32x32To64(t, 10000000) + 116444736000000000;
|
||||
pft->dwLowDateTime = (DWORD)ll;
|
||||
pft->dwHighDateTime = ll >> 32;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool ScanDirectoryFiles( const CString &root,const CString &path,const CString &fileSpec,std::vector<CFileChangeMonitor::SFileEnumInfo> &files )
|
||||
{
|
||||
bool anyFound = false;
|
||||
CString dir = Path::AddBackslash(root + path);
|
||||
|
||||
CString findFilter = Path::Make(dir,fileSpec);
|
||||
ICryPak *pIPak = GetIEditor()->GetSystem()->GetIPak();
|
||||
|
||||
// Add all directories.
|
||||
CFileFind finder;
|
||||
BOOL bWorking = finder.FindFile( Path::Make(dir,fileSpec) );
|
||||
while (bWorking)
|
||||
{
|
||||
bWorking = finder.FindNextFile();
|
||||
|
||||
if (finder.IsDots())
|
||||
continue;
|
||||
|
||||
if (!finder.IsDirectory())
|
||||
{
|
||||
anyFound = true;
|
||||
|
||||
CFileChangeMonitor::SFileEnumInfo fd;
|
||||
fd.filename = dir + finder.GetFileName();
|
||||
//fd.nFileSize = finder.GetLength();
|
||||
|
||||
//finder.GetCreationTime( &fd.ftCreationTime );
|
||||
//finder.GetLastAccessTime( &fd.ftLastAccessTime );
|
||||
finder.GetLastWriteTime( &fd.ftLastWriteTime );
|
||||
|
||||
files.push_back(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get directory contents.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool ScanDirectoryRecursive( const CString &root,const CString &path,const CString &fileSpec,std::vector<CFileChangeMonitor::SFileEnumInfo> &files, bool recursive )
|
||||
{
|
||||
bool anyFound = false;
|
||||
CString dir = Path::AddBackslash(root + path);
|
||||
|
||||
if (ScanDirectoryFiles( root,path,fileSpec,files ))
|
||||
anyFound = true;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
CFileFind finder;
|
||||
BOOL bWorking = finder.FindFile( Path::Make(dir,"*.*") );
|
||||
while (bWorking)
|
||||
{
|
||||
bWorking = finder.FindNextFile();
|
||||
|
||||
if (finder.IsDots())
|
||||
continue;
|
||||
|
||||
if (finder.IsDirectory())
|
||||
{
|
||||
// Scan directory.
|
||||
if (ScanDirectoryRecursive( root,Path::AddBackslash(path+finder.GetFileName()),fileSpec,files,recursive ))
|
||||
anyFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileChangeMonitorThread::FindChangedFiles( const CString &dir )
|
||||
{
|
||||
//CLogFile::WriteLine( "** Searching file" );
|
||||
// Get current file time.
|
||||
SYSTEMTIME curSysTime;
|
||||
FILETIME curFileTime;
|
||||
GetSystemTime( &curSysTime );
|
||||
SystemTimeToFileTime( &curSysTime,&curFileTime );
|
||||
|
||||
std::vector<CFileChangeMonitor::SFileEnumInfo> files;
|
||||
files.reserve( 1000 );
|
||||
ScanDirectoryRecursive( dir,"","*.*",files,true );
|
||||
|
||||
INT64 curftime = *(INT64*)&curFileTime;
|
||||
|
||||
SYSTEMTIME s1,s2;
|
||||
FILETIME ft1,ft2;
|
||||
ZeroStruct(ft1);
|
||||
FileTimeToSystemTime(&ft1,&s1);
|
||||
FileTimeToSystemTime(&ft1,&s2);
|
||||
|
||||
s2.wSecond = 5; // 5 second.
|
||||
|
||||
SystemTimeToFileTime(&s1,&ft1);
|
||||
SystemTimeToFileTime(&s2,&ft2);
|
||||
int deltaT = (*(INT64*)&ft2) - (*(INT64*)&ft1) ; // 1 second.
|
||||
|
||||
for (int i = 0; i < files.size(); i++)
|
||||
{
|
||||
// now compare time stamps.
|
||||
INT64 ftime = *(INT64*)&(files[i].ftLastWriteTime);
|
||||
|
||||
INT64 dt = curftime-ftime;
|
||||
if (dt < 0)
|
||||
{
|
||||
dt = ftime - curftime;
|
||||
}
|
||||
|
||||
if (dt < deltaT)
|
||||
{
|
||||
// This file was written within deltaT time from now, consider it as modified.
|
||||
CString filename = files[i].filename;
|
||||
m_files.push( filename );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CFileChangeMonitor::CFileChangeMonitor()
|
||||
{
|
||||
m_thread = new CFileChangeMonitorThread;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CFileChangeMonitor::~CFileChangeMonitor()
|
||||
{
|
||||
// Send to thread a kill event.
|
||||
StopMonitor();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileChangeMonitor::IsDirectory(const char* sFileName)
|
||||
{
|
||||
struct __stat64 my_stat;
|
||||
if (_stat64(sFileName, &my_stat) != 0) return false;
|
||||
return ((my_stat.st_mode & S_IFDIR) != 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileChangeMonitor::MonitorDirectories( const std::vector<CString> &dirs )
|
||||
{
|
||||
// Watch the C:\WINDOWS directory for file creation and
|
||||
// deletion.
|
||||
for (int i = 0; i < dirs.size(); i++)
|
||||
{
|
||||
if (!IsDirectory( Path::RemoveBackslash(dirs[i]) ))
|
||||
continue;
|
||||
|
||||
m_thread->m_dirs.push_back(dirs[i]);
|
||||
|
||||
// Create Notification Event.
|
||||
HANDLE dwHandle = FindFirstChangeNotification( dirs[i],TRUE,FILE_NOTIFY_CHANGE_LAST_WRITE); // watch file name changes
|
||||
m_thread->m_handles.push_back(dwHandle);
|
||||
}
|
||||
|
||||
// Start monitoring thread.
|
||||
m_thread->Start();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileChangeMonitor::StopMonitor()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
::SetEvent(m_thread->m_killEvent);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileChangeMonitor::HaveModifiedFiles() const
|
||||
{
|
||||
return !m_thread->m_files.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CString CFileChangeMonitor::GetModifiedFile()
|
||||
{
|
||||
CString file;
|
||||
if (!m_thread->m_files.empty())
|
||||
{
|
||||
file = m_thread->m_files.top();
|
||||
m_thread->m_files.pop();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
54
Editor/Util/FileChangeMonitor.h
Normal file
54
Editor/Util/FileChangeMonitor.h
Normal file
@@ -0,0 +1,54 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: filechangemonitor.h
|
||||
// Version: v1.00
|
||||
// Created: 15/11/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __filechangemonitor_h__
|
||||
#define __filechangemonitor_h__
|
||||
#pragma once
|
||||
|
||||
//! This message sent to main application window when file change detected.
|
||||
#define WM_FILEMONITORCHANGE WM_APP + 10
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Monitors directory for any changed files.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CFileChangeMonitor
|
||||
{
|
||||
public:
|
||||
CFileChangeMonitor();
|
||||
~CFileChangeMonitor();
|
||||
|
||||
void MonitorDirectories( const std::vector<CString> &dirs );
|
||||
void StopMonitor();
|
||||
|
||||
//! Check if any files where modified.
|
||||
//! This is a polling function, call it every frame or so.
|
||||
bool HaveModifiedFiles() const;
|
||||
//! Get next modified file, this file will be delete from list after calling this function.
|
||||
//! Call it until HaveModifiedFiles return true.
|
||||
CString GetModifiedFile();
|
||||
|
||||
struct SFileEnumInfo
|
||||
{
|
||||
CString filename;
|
||||
FILETIME ftLastWriteTime;
|
||||
};
|
||||
private:
|
||||
bool IsDirectory(const char* sFileName);
|
||||
|
||||
//! Pointer to implementation class.
|
||||
struct CFileChangeMonitorThread *m_thread;
|
||||
};
|
||||
|
||||
#endif // __filechangemonitor_h__
|
||||
141
Editor/Util/FileEnum.cpp
Normal file
141
Editor/Util/FileEnum.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
// FileEnum.cpp: Implementation of the class CFileEnum.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "FileEnum.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <ISound.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construcktion / destrucktion
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CFileEnum::CFileEnum()
|
||||
{
|
||||
m_hEnumFile = 0;
|
||||
}
|
||||
|
||||
CFileEnum::~CFileEnum()
|
||||
{
|
||||
// End the enumeration
|
||||
if (m_hEnumFile)
|
||||
{
|
||||
_findclose(m_hEnumFile);
|
||||
m_hEnumFile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CFileEnum::StartEnumeration( const char* szEnumPath, char szEnumPattern[], __finddata64_t *pFile)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Take path and search pattern as separate arguments
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
char szPath[_MAX_PATH];
|
||||
|
||||
// Build enumeration path
|
||||
strcpy(szPath, szEnumPath);
|
||||
if (szPath[strlen(szPath)] != '\\' &&
|
||||
szPath[strlen(szPath)] != '/')
|
||||
{
|
||||
strcat(szPath, "\\");
|
||||
}
|
||||
strcat(szPath, szEnumPattern);
|
||||
|
||||
return StartEnumeration(szPath, pFile);
|
||||
}
|
||||
|
||||
bool CFileEnum::StartEnumeration( const char *szEnumPathAndPattern, __finddata64_t *pFile)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Start a new file enumeration
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// End any previous enumeration
|
||||
if (m_hEnumFile)
|
||||
{
|
||||
_findclose(m_hEnumFile);
|
||||
m_hEnumFile = 0;
|
||||
}
|
||||
|
||||
// Start the enumeration
|
||||
if ((m_hEnumFile = _findfirst64(szEnumPathAndPattern, pFile)) == -1L)
|
||||
{
|
||||
// No files found
|
||||
_findclose(m_hEnumFile);
|
||||
m_hEnumFile = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFileEnum::GetNextFile(__finddata64_t *pFile)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Start a new file enumeration
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Fill file strcuture
|
||||
if (_findnext64(m_hEnumFile, pFile) == -1)
|
||||
{
|
||||
// No more files left
|
||||
_findclose(m_hEnumFile);
|
||||
m_hEnumFile = 0;
|
||||
return false;
|
||||
};
|
||||
|
||||
// At least one file left
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Get directory contents.
|
||||
inline bool ScanDirectoryRecursive( const CString &root,const CString &path,const CString &file,std::vector<CString> &files, bool recursive )
|
||||
{
|
||||
struct __finddata64_t c_file;
|
||||
intptr_t hFile;
|
||||
|
||||
bool anyFound = false;
|
||||
|
||||
CString fullPath = root + path + file;
|
||||
if( (hFile = _findfirst64( fullPath, &c_file )) != -1L )
|
||||
{
|
||||
// Find the rest of the files.
|
||||
do {
|
||||
anyFound = true;
|
||||
files.push_back( path + c_file.name );
|
||||
} while (_findnext64( hFile, &c_file ) == 0);
|
||||
_findclose( hFile );
|
||||
}
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
fullPath = root + path + "*.*";
|
||||
if( (hFile = _findfirst64( fullPath, &c_file )) != -1L )
|
||||
{
|
||||
// Find directories.
|
||||
do {
|
||||
if (c_file.attrib & _A_SUBDIR)
|
||||
{
|
||||
// If recursive.
|
||||
if (c_file.name[0] != '.')
|
||||
{
|
||||
if (ScanDirectoryRecursive( root,path + c_file.name + "\\",file,files,recursive ))
|
||||
anyFound = true;
|
||||
}
|
||||
}
|
||||
} while (_findnext64( hFile, &c_file ) == 0);
|
||||
_findclose( hFile );
|
||||
}
|
||||
}
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
bool CFileEnum::ScanDirectory( const CString &path,const CString &file,std::vector<CString> &files, bool recursive )
|
||||
{
|
||||
return ScanDirectoryRecursive(path,"",file,files,recursive );
|
||||
}
|
||||
26
Editor/Util/FileEnum.h
Normal file
26
Editor/Util/FileEnum.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// FileEnum.h: Interface of the class CFileEnum.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_FILEENUM_H__9A4EB661_8991_11D4_8100_D1626940A160__INCLUDED_)
|
||||
#define AFX_FILEENUM_H__9A4EB661_8991_11D4_8100_D1626940A160__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class CFileEnum
|
||||
{
|
||||
public:
|
||||
static bool ScanDirectory( const CString &path,const CString &file,std::vector<CString> &files, bool recursive=true );
|
||||
|
||||
bool GetNextFile(struct __finddata64_t *pFile);
|
||||
bool StartEnumeration( const char *szEnumPathAndPattern, __finddata64_t *pFile);
|
||||
bool StartEnumeration( const char *szEnumPath, char szEnumPattern[], __finddata64_t *pFile);
|
||||
CFileEnum();
|
||||
virtual ~CFileEnum();
|
||||
protected:
|
||||
intptr_t m_hEnumFile;
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_FILEENUM_H__9A4EB661_8991_11D4_8100_D1626940A160__INCLUDED_)
|
||||
649
Editor/Util/FileUtil.cpp
Normal file
649
Editor/Util/FileUtil.cpp
Normal file
@@ -0,0 +1,649 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: fileutil.cpp
|
||||
// Version: v1.00
|
||||
// Created: 13/9/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Settings.h"
|
||||
#include "CheckOutDialog.h"
|
||||
#include "SrcSafeSettingsDialog.h"
|
||||
|
||||
#include "CustomFileDialog.h"
|
||||
#include <CryFile.h>
|
||||
#include <io.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::CompileLuaFile( const char *luaFilename )
|
||||
{
|
||||
// Check if this file is in Archive.
|
||||
{
|
||||
CCryFile file;
|
||||
if (file.Open( luaFilename,"rb" ))
|
||||
{
|
||||
// Check if in pack.
|
||||
if (file.IsInPak())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// First try compiling script and see if it have any errors.
|
||||
CString LuaCompiler;
|
||||
CString CompilerOutput;
|
||||
|
||||
// Create the filepath of the lua compiler
|
||||
char szExeFileName[_MAX_PATH];
|
||||
// Get the path of the executable
|
||||
GetModuleFileName( GetModuleHandle(NULL), szExeFileName, sizeof(szExeFileName));
|
||||
CString exePath = Path::GetPath( szExeFileName );
|
||||
|
||||
LuaCompiler = Path::AddBackslash(exePath) + "LuaCompiler.exe ";
|
||||
|
||||
CString luaFile = luaFilename;
|
||||
luaFile.Replace( '/','\\' );
|
||||
|
||||
// Add the name of the Lua file
|
||||
CString cmdLine = LuaCompiler + luaFile;
|
||||
|
||||
// Execute the compiler and capture the output
|
||||
if (!GetIEditor()->ExecuteConsoleApp( cmdLine,CompilerOutput ))
|
||||
{
|
||||
AfxMessageBox("Error while executing 'LuaCompiler.exe', make sure the file is in" \
|
||||
" your Master CD folder !");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check return string
|
||||
if (strlen(CompilerOutput) > 0)
|
||||
{
|
||||
// Errors while compiling file.
|
||||
|
||||
// Show output from Lua compiler
|
||||
if (MessageBox( NULL,(CString("Error output from Lua compiler:\r\n") + CompilerOutput +
|
||||
CString("\r\nDo you want to edit the file ?")),"Lua Compiler", MB_ICONERROR | MB_YESNO) == IDYES)
|
||||
{
|
||||
int line = 0;
|
||||
CString cmdLine = luaFile;
|
||||
int index = CompilerOutput.Find( "at line" );
|
||||
if (index >= 0)
|
||||
{
|
||||
const char *str = CompilerOutput;
|
||||
sscanf( &str[index],"at line %d",&line );
|
||||
}
|
||||
// Open the Lua file for editing
|
||||
EditTextFile( luaFile,line );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileUtil::EditTextFile( const char *txtFile,int line,ETextFileType fileType )
|
||||
{
|
||||
CString file = txtFile;
|
||||
file.Replace( '/','\\' );
|
||||
|
||||
CString cmd;
|
||||
if (line != 0)
|
||||
{
|
||||
cmd.Format( "%s/%d/0",(const char*)file,line );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = file;
|
||||
}
|
||||
|
||||
// Check if this file is in Archive.
|
||||
{
|
||||
CCryFile cryfile;
|
||||
if (cryfile.Open( file,"rb" ))
|
||||
{
|
||||
// Check if in pack.
|
||||
if (cryfile.IsInPak())
|
||||
{
|
||||
const char *sPakName = cryfile.GetPakPath();
|
||||
// Cannot edit file in pack, suggest to extract it for editing.
|
||||
CString msg;
|
||||
msg.Format( _T("File %s is inside Pak file %s\r\nDo you want it to be extracted for Editing?"),(const char*)file,sPakName );
|
||||
if (AfxMessageBox( msg,MB_YESNO|MB_ICONEXCLAMATION) == IDNO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CFileUtil::CreateDirectory( Path::GetPath(file) );
|
||||
// Extract it from Pak file.
|
||||
CFile diskFile;
|
||||
if (diskFile.Open( file,CFile::modeCreate|CFile::modeWrite))
|
||||
{
|
||||
// Copy data from packed file to disk file.
|
||||
char *data = new char[cryfile.GetLength()];
|
||||
cryfile.Read( data,cryfile.GetLength() );
|
||||
diskFile.Write( data,cryfile.GetLength() );
|
||||
delete []data;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Failed to create file %s on disk",(const char*)file );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CString TextEditor = gSettings.textEditorForScript;
|
||||
if (fileType == FILE_TYPE_SHADER)
|
||||
{
|
||||
TextEditor = gSettings.textEditorForShaders;
|
||||
}
|
||||
|
||||
HINSTANCE hInst = ShellExecute( NULL, "open", TextEditor, cmd, NULL, SW_SHOWNORMAL );
|
||||
if ((DWORD_PTR)hInst < 32)
|
||||
{
|
||||
// Failed.
|
||||
file = file.SpanExcluding( "/" );
|
||||
// Try standart open.
|
||||
ShellExecute( NULL, "open", file, NULL, NULL, SW_SHOWNORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::SelectFile( const CString &fileSpec,const CString &searchFolder,CString &fullFileName )
|
||||
{
|
||||
CString filter;
|
||||
filter.Format( "%s|%s||",(const char*)fileSpec,(const char*)fileSpec );
|
||||
|
||||
CFileDialog dlg(TRUE, NULL,NULL, OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR, filter );
|
||||
dlg.m_ofn.lpstrInitialDir = searchFolder;
|
||||
|
||||
if (dlg.DoModal() == IDOK)
|
||||
{
|
||||
fullFileName = dlg.GetPathName();
|
||||
return true;
|
||||
/*
|
||||
if (!fileName.IsEmpty())
|
||||
{
|
||||
relativeFileName = GetIEditor()->GetRelativePath( fileName );
|
||||
if (!relativeFileName.IsEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "You must select files from %s folder",(const char*)GetIEditor()->GetMasterCDFolder(); );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// CSelectFileDlg cDialog;
|
||||
// bool res = cDialog.SelectFileName( &fileName,&relativeFileName,fileSpec,searchFolder );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFileUtil::SelectFiles( const CString &fileSpec,const CString &searchFolder,std::vector<CString> &files )
|
||||
{
|
||||
CString filter;
|
||||
filter.Format( "%s|%s||",(const char*)fileSpec,(const char*)fileSpec );
|
||||
|
||||
char filesStr[16768];
|
||||
memset( filesStr,0,sizeof(filesStr) );
|
||||
|
||||
CFileDialog dlg(TRUE, NULL,NULL, OFN_ALLOWMULTISELECT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR, filter );
|
||||
dlg.m_ofn.lpstrInitialDir = searchFolder;
|
||||
dlg.m_ofn.lpstrFile = filesStr;
|
||||
dlg.m_ofn.nMaxFile = sizeof(filesStr);
|
||||
|
||||
files.clear();
|
||||
if (dlg.DoModal())
|
||||
{
|
||||
POSITION pos = dlg.GetStartPosition();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CString fileName = dlg.GetNextPathName(pos);
|
||||
if (fileName.IsEmpty())
|
||||
continue;
|
||||
files.push_back( fileName );
|
||||
}
|
||||
}
|
||||
|
||||
if (!files.empty())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::SelectSaveFile( const CString &fileFilter,const CString &defaulExtension,const CString &startFolder,CString &fileName )
|
||||
{
|
||||
CFileDialog dlg(FALSE, defaulExtension,NULL, OFN_ENABLESIZING|OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT, fileFilter );
|
||||
dlg.m_ofn.lpstrInitialDir = startFolder;
|
||||
|
||||
if (dlg.DoModal() == IDOK)
|
||||
{
|
||||
fileName = dlg.GetPathName();
|
||||
if (!fileName.IsEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::SelectSingleFile( ECustomFileType fileType,CString &outputFile,const CString &filter,const CString &initialDir )
|
||||
{
|
||||
CCustomFileDialog::OpenParams op;
|
||||
op.bMultiSelection = false;
|
||||
op.filetype = fileType;
|
||||
op.filter = filter;
|
||||
op.initialDir = initialDir;
|
||||
op.initialFile = outputFile;
|
||||
CCustomFileDialog dlg( op );
|
||||
|
||||
if (dlg.DoModal() == IDOK)
|
||||
{
|
||||
outputFile = dlg.GetFilePath();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Display OpenFile dialog and allow to select multiple files.
|
||||
bool CFileUtil::SelectMultipleFiles( ECustomFileType fileType,std::vector<CString> &files,const CString &filter,const CString &initialDir )
|
||||
{
|
||||
CCustomFileDialog::OpenParams op;
|
||||
op.bMultiSelection = true;
|
||||
op.filetype = fileType;
|
||||
op.filter = filter;
|
||||
op.initialDir = initialDir;
|
||||
CCustomFileDialog dlg( op );
|
||||
|
||||
files.clear();
|
||||
if (dlg.DoModal() == IDOK)
|
||||
{
|
||||
for (int i = 0; i < dlg.GetSelectedCount(); i++)
|
||||
{
|
||||
files.push_back( dlg.GetSelectedFile(i) );
|
||||
}
|
||||
}
|
||||
return !files.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get directory contents.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool ScanDirectoryFiles( const CString &root,const CString &path,const CString &fileSpec,std::vector<CFileUtil::FileDesc> &files )
|
||||
{
|
||||
bool anyFound = false;
|
||||
CString dir = Path::AddBackslash(root + path);
|
||||
|
||||
CString findFilter = Path::Make(dir,fileSpec);
|
||||
ICryPak *pIPak = GetIEditor()->GetSystem()->GetIPak();
|
||||
|
||||
// Add all directories.
|
||||
_finddata_t fd;
|
||||
intptr_t fhandle;
|
||||
|
||||
fhandle = pIPak->FindFirst( findFilter,&fd );
|
||||
if (fhandle != -1)
|
||||
{
|
||||
do {
|
||||
// Skip back folders.
|
||||
if (fd.name[0] == '.')
|
||||
continue;
|
||||
if (fd.attrib & _A_SUBDIR) // skip sub directories.
|
||||
continue;
|
||||
|
||||
anyFound = true;
|
||||
|
||||
CFileUtil::FileDesc file;
|
||||
file.filename = path + fd.name;
|
||||
file.attrib = fd.attrib;
|
||||
file.size = fd.size;
|
||||
file.time_access = fd.time_access;
|
||||
file.time_create = fd.time_create;
|
||||
file.time_write = fd.time_write;
|
||||
|
||||
files.push_back( file );
|
||||
} while (pIPak->FindNext( fhandle,&fd ) == 0);
|
||||
pIPak->FindClose(fhandle);
|
||||
}
|
||||
|
||||
/*
|
||||
CFileFind finder;
|
||||
BOOL bWorking = finder.FindFile( Path::Make(dir,fileSpec) );
|
||||
while (bWorking)
|
||||
{
|
||||
bWorking = finder.FindNextFile();
|
||||
|
||||
if (finder.IsDots())
|
||||
continue;
|
||||
|
||||
if (!finder.IsDirectory())
|
||||
{
|
||||
anyFound = true;
|
||||
|
||||
CFileUtil::FileDesc fd;
|
||||
fd.filename = dir + finder.GetFileName();
|
||||
fd.nFileSize = finder.GetLength();
|
||||
|
||||
finder.GetCreationTime( &fd.ftCreationTime );
|
||||
finder.GetLastAccessTime( &fd.ftLastAccessTime );
|
||||
finder.GetLastWriteTime( &fd.ftLastWriteTime );
|
||||
|
||||
fd.dwFileAttributes = 0;
|
||||
if (finder.IsArchived())
|
||||
fd.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
if (finder.IsCompressed())
|
||||
fd.dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
|
||||
if (finder.IsNormal())
|
||||
fd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
if (finder.IsHidden())
|
||||
fd.dwFileAttributes = FILE_ATTRIBUTE_HIDDEN;
|
||||
if (finder.IsReadOnly())
|
||||
fd.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
|
||||
if (finder.IsSystem())
|
||||
fd.dwFileAttributes = FILE_ATTRIBUTE_SYSTEM;
|
||||
if (finder.IsTemporary())
|
||||
fd.dwFileAttributes = FILE_ATTRIBUTE_TEMPORARY;
|
||||
|
||||
files.push_back(fd);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get directory contents.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool ScanDirectoryRecursive( const CString &root,const CString &path,const CString &fileSpec,std::vector<CFileUtil::FileDesc> &files, bool recursive )
|
||||
{
|
||||
bool anyFound = false;
|
||||
CString dir = Path::AddBackslash(root + path);
|
||||
|
||||
if (ScanDirectoryFiles( root,Path::AddBackslash(path),fileSpec,files ))
|
||||
anyFound = true;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
/*
|
||||
CFileFind finder;
|
||||
BOOL bWorking = finder.FindFile( Path::Make(dir,"*.*") );
|
||||
while (bWorking)
|
||||
{
|
||||
bWorking = finder.FindNextFile();
|
||||
|
||||
if (finder.IsDots())
|
||||
continue;
|
||||
|
||||
if (finder.IsDirectory())
|
||||
{
|
||||
// Scan directory.
|
||||
if (ScanDirectoryRecursive( root,Path::AddBackslash(path+finder.GetFileName()),fileSpec,files,recursive ))
|
||||
anyFound = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
ICryPak *pIPak = GetIEditor()->GetSystem()->GetIPak();
|
||||
|
||||
// Add all directories.
|
||||
_finddata_t fd;
|
||||
intptr_t fhandle;
|
||||
|
||||
fhandle = pIPak->FindFirst( Path::Make(dir,"*.*"),&fd );
|
||||
if (fhandle != -1)
|
||||
{
|
||||
do {
|
||||
// Skip back folders.
|
||||
if (fd.name[0] == '.')
|
||||
continue;
|
||||
if (!(fd.attrib & _A_SUBDIR)) // skip not directories.
|
||||
continue;
|
||||
|
||||
// Scan directory.
|
||||
if (ScanDirectoryRecursive( root,Path::AddBackslash(path + fd.name),fileSpec,files,recursive ))
|
||||
anyFound = true;
|
||||
|
||||
} while (pIPak->FindNext( fhandle,&fd ) == 0);
|
||||
pIPak->FindClose(fhandle);
|
||||
}
|
||||
}
|
||||
|
||||
return anyFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::ScanDirectory( const CString &path,const CString &file,std::vector<FileDesc> &files, bool recursive )
|
||||
{
|
||||
return ScanDirectoryRecursive(Path::AddBackslash(path),"",file,files,recursive );
|
||||
}
|
||||
|
||||
/*
|
||||
bool CFileUtil::ScanDirectory( const CString &startDirectory,const CString &searchPath,const CString &fileSpec,FileArray &files, bool recursive=true )
|
||||
{
|
||||
return ScanDirectoryRecursive(startDirectory,SearchPath,file,files,recursive );
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::OverwriteFile( const char *filename )
|
||||
{
|
||||
// check if file exist.
|
||||
FILE *file = fopen( filename,"rb" );
|
||||
if (!file)
|
||||
return true;
|
||||
fclose(file);
|
||||
|
||||
int res = (GetFileAttributes(filename)&FILE_ATTRIBUTE_READONLY);
|
||||
if (res == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
Warning( "Cannot Save File %s",filename );
|
||||
return false;
|
||||
}
|
||||
if (res != 0)
|
||||
{
|
||||
CCheckOutDialog dlg( filename,AfxGetMainWnd() );
|
||||
if (dlg.DoModal() == IDCANCEL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (dlg.GetResult() == CCheckOutDialog::CHECKOUT)
|
||||
{
|
||||
return CheckoutFile( filename );
|
||||
}
|
||||
SetFileAttributes( filename,FILE_ATTRIBUTE_NORMAL );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
static bool CheckOutFile( const char *filename )
|
||||
{
|
||||
CString ssafeExe = "C:\\Program Files\\Microsoft Visual Studio\\VSS\\win32\\ss.exe";
|
||||
SetEnvironmentVariable( "ssuser","timur" );
|
||||
SetEnvironmentVariable( "ssdir","\\\\Server2\\XISLE\\ArtworkVss" );
|
||||
//CString SSafeArtwork = "\\\\Server2\\XISLE\\ArtworkVss\\win32\\ss.exe";
|
||||
//CString SSafeArtworkProject = "$/MASTERCD";
|
||||
|
||||
CString cmd = ssafeExe + " " + " checkout cg.dll";
|
||||
|
||||
char currDirectory[MAX_PATH];
|
||||
GetCurrentDirectory( sizeof(currDirectory),currDirectory );
|
||||
char cmdLine[MAX_PATH];
|
||||
strcpy( cmdLine,cmd );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
memset( &si,0,sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
memset( &pi,0,sizeof(pi) );
|
||||
if (CreateProcess( NULL,cmdLine,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,currDirectory,&si,&pi ))
|
||||
{
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::CheckoutFile( const char *filename )
|
||||
{
|
||||
if (gSettings.ssafeParams.user.IsEmpty())
|
||||
{
|
||||
AfxMessageBox( _T("Source Safe login user name must be configured."),MB_OK|MB_ICONEXCLAMATION );
|
||||
|
||||
// Source safe not configured.
|
||||
CSrcSafeSettingsDialog dlg;
|
||||
if (dlg.DoModal() != IDOK)
|
||||
{
|
||||
AfxMessageBox( _T("Checkout canceled"),MB_OK|MB_ICONEXCLAMATION );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SetEnvironmentVariable( "ssuser",gSettings.ssafeParams.user );
|
||||
SetEnvironmentVariable( "ssdir",gSettings.ssafeParams.databasePath );
|
||||
|
||||
CString relFile = GetIEditor()->GetRelativePath(filename);
|
||||
if (relFile.IsEmpty())
|
||||
relFile = filename;
|
||||
|
||||
CString cmd = gSettings.ssafeParams.exeFile + " checkout " + relFile;
|
||||
|
||||
char currDirectory[MAX_PATH];
|
||||
GetCurrentDirectory( sizeof(currDirectory),currDirectory );
|
||||
char cmdLine[MAX_PATH];
|
||||
strcpy( cmdLine,cmd );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
memset( &si,0,sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
memset( &pi,0,sizeof(pi) );
|
||||
if (CreateProcess( NULL,cmdLine,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,currDirectory,&si,&pi ))
|
||||
{
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::CheckinFile( const char *filename )
|
||||
{
|
||||
SetEnvironmentVariable( "ssuser",gSettings.ssafeParams.user );
|
||||
SetEnvironmentVariable( "ssdir",gSettings.ssafeParams.databasePath );
|
||||
|
||||
CString relFile = GetIEditor()->GetRelativePath(filename);
|
||||
if (relFile.IsEmpty())
|
||||
relFile = filename;
|
||||
|
||||
CString cmd = gSettings.ssafeParams.exeFile + " checkout " + relFile;
|
||||
|
||||
char currDirectory[MAX_PATH];
|
||||
GetCurrentDirectory( sizeof(currDirectory),currDirectory );
|
||||
char cmdLine[MAX_PATH];
|
||||
strcpy( cmdLine,cmd );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
memset( &si,0,sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
memset( &pi,0,sizeof(pi) );
|
||||
if (CreateProcess( NULL,cmdLine,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,currDirectory,&si,&pi ))
|
||||
{
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create new directory, check if directory already exist.
|
||||
static bool CheckAndCreateDirectory( const char *path )
|
||||
{
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
|
||||
HANDLE hFind = FindFirstFile( path,&FindFileData );
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
return ::CreateDirectory( path,NULL ) == TRUE;
|
||||
} else {
|
||||
DWORD attr = FindFileData.dwFileAttributes;
|
||||
FindClose(hFind);
|
||||
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileUtil::CreateDirectory( const char *directory )
|
||||
{
|
||||
CString path = directory;
|
||||
CString dir;
|
||||
bool res = CheckAndCreateDirectory( path );
|
||||
if (!res)
|
||||
{
|
||||
int iStart = 0;
|
||||
CString token = TokenizeString(path,"\\/",iStart );
|
||||
dir = token;
|
||||
while (token != "")
|
||||
{
|
||||
CheckAndCreateDirectory( dir );
|
||||
token = TokenizeString(path,"\\/",iStart );
|
||||
dir += CString("\\") + token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CFileUtil::BackupFile( const char *filename )
|
||||
{
|
||||
// Make a backup of previous file.
|
||||
bool makeBackup = true;
|
||||
|
||||
CString bakFilename = Path::ReplaceExtension( filename,"bak" );
|
||||
|
||||
{
|
||||
// Check if backup needed.
|
||||
CFile bak;
|
||||
if (bak.Open( filename,CFile::modeRead ))
|
||||
{
|
||||
if (bak.GetLength() <= 0)
|
||||
makeBackup = false;
|
||||
}
|
||||
else
|
||||
makeBackup = false;
|
||||
}
|
||||
if (makeBackup)
|
||||
{
|
||||
SetFileAttributes( filename,FILE_ATTRIBUTE_NORMAL );
|
||||
MoveFileEx( filename,bakFilename,MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH );
|
||||
}
|
||||
}
|
||||
99
Editor/Util/FileUtil.h
Normal file
99
Editor/Util/FileUtil.h
Normal file
@@ -0,0 +1,99 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: fileutil.h
|
||||
// Version: v1.00
|
||||
// Created: 13/9/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __fileutil_h__
|
||||
#define __fileutil_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* File types used for File Open dialogs.
|
||||
*
|
||||
*/
|
||||
enum ECustomFileType
|
||||
{
|
||||
EFILE_TYPE_ANY,
|
||||
EFILE_TYPE_GEOMETRY,
|
||||
EFILE_TYPE_TEXTURE,
|
||||
EFILE_TYPE_SOUND,
|
||||
EFILE_TYPE_LAST,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class SANDBOX_API CFileUtil
|
||||
{
|
||||
public:
|
||||
struct FileDesc
|
||||
{
|
||||
CString filename;
|
||||
unsigned int attrib;
|
||||
time_t time_create; //! -1 for FAT file systems
|
||||
time_t time_access; //! -1 for FAT file systems
|
||||
time_t time_write;
|
||||
int64 size;
|
||||
};
|
||||
enum ETextFileType
|
||||
{
|
||||
FILE_TYPE_SCRIPT,
|
||||
FILE_TYPE_SHADER
|
||||
};
|
||||
|
||||
typedef std::vector<FileDesc> FileArray;
|
||||
|
||||
static bool ScanDirectory( const CString &path,const CString &fileSpec,FileArray &files, bool recursive=true );
|
||||
//static bool ScanDirectory( const CString &startDirectory,const CString &searchPath,const CString &fileSpecZ,FileArray &files, bool recursive=true );
|
||||
|
||||
static bool CompileLuaFile( const char *luaFilename );
|
||||
static void EditTextFile( const char *txtFile,int line=0,ETextFileType fileType=FILE_TYPE_SCRIPT );
|
||||
|
||||
//! Open file selection dialog.
|
||||
static bool SelectFile( const CString &fileSpec,const CString &searchFolder,CString &fullFileName );
|
||||
//! Open file selection dialog.
|
||||
static bool SelectFiles( const CString &fileSpec,const CString &searchFolder,std::vector<CString> &files );
|
||||
|
||||
//! Display OpenFile dialog and allow to select multiple files.
|
||||
//! @return true if selected, false if canceled.
|
||||
//! @outputFile Inputs and Outputs filename.
|
||||
static bool SelectSingleFile( ECustomFileType fileType,CString &outputFile,const CString &filter="",const CString &initialDir="" );
|
||||
|
||||
//! Display OpenFile dialog and allow to select multiple files.
|
||||
//! @return true if selected, false if canceled.
|
||||
static bool SelectMultipleFiles( ECustomFileType fileType,std::vector<CString> &files,const CString &filter="",const CString &initialDir="" );
|
||||
|
||||
static bool SelectSaveFile( const CString &fileFilter,const CString &defaulExtension,const CString &startFolder,CString &fileName );
|
||||
|
||||
//! If file is read-only ask user if he wants to overwrite it.
|
||||
//! If yes file is deleted.
|
||||
//! @return True if file was deleted.
|
||||
static bool OverwriteFile( const char *filename );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Interface to Source safe.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Checks out the file from source safe.
|
||||
static bool CheckoutFile( const char *filename );
|
||||
|
||||
//! Checks in the file to source safe.
|
||||
static bool CheckinFile( const char *filename );
|
||||
|
||||
//! Creates this directory.
|
||||
static void CreateDirectory( const char *dir );
|
||||
|
||||
//! Makes a backup file.
|
||||
static void BackupFile( const char *filename );
|
||||
};
|
||||
|
||||
#endif // __fileutil_h__
|
||||
55
Editor/Util/FunctorMulticaster.h
Normal file
55
Editor/Util/FunctorMulticaster.h
Normal file
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: FunctorMulticaster.h
|
||||
// Version: v1.00
|
||||
// Created: 30/1/2002 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Multicast multiple functors.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __FunctorMulticaster_h__
|
||||
#define __FunctorMulticaster_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class _event>
|
||||
class FunctorMulticaster
|
||||
{
|
||||
public:
|
||||
typedef Functor1<_event> callback;
|
||||
|
||||
FunctorMulticaster() {}
|
||||
virtual ~FunctorMulticaster() {}
|
||||
|
||||
void AddListener( const callback &func )
|
||||
{
|
||||
m_listeners.push_back( func );
|
||||
}
|
||||
|
||||
void RemoveListener( const callback &func )
|
||||
{
|
||||
m_listeners.remove( func );
|
||||
}
|
||||
|
||||
void Call( _event evt )
|
||||
{
|
||||
std::list<callback>::iterator iter;
|
||||
for (iter = m_listeners.begin(); iter != m_listeners.end(); ++iter) {
|
||||
(*iter)( evt );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<callback> m_listeners;
|
||||
};
|
||||
|
||||
#endif // __FunctorMulticaster_h__
|
||||
20
Editor/Util/GuidUtil.cpp
Normal file
20
Editor/Util/GuidUtil.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: guidutil.cpp
|
||||
// Version: v1.00
|
||||
// Created: 25/4/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "GuidUtil.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const GUID GuidUtil::NullGuid = { 0, 0, 0, { 0,0,0,0,0,0,0,0 } };
|
||||
83
Editor/Util/GuidUtil.h
Normal file
83
Editor/Util/GuidUtil.h
Normal file
@@ -0,0 +1,83 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: guidutil.h
|
||||
// Version: v1.00
|
||||
// Created: 20/1/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Utility functions to work with GUIDs.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __guidutil_h__
|
||||
#define __guidutil_h__
|
||||
#pragma once
|
||||
|
||||
struct GuidUtil
|
||||
{
|
||||
//! Convert GUID to string in the valid format.
|
||||
//! The valid format for a GUID is {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} where X is a hex digit.
|
||||
static const char* ToString( REFGUID guid );
|
||||
//! Convert from guid string in valid format to GUID class.
|
||||
static GUID FromString( const char* guidString );
|
||||
static bool IsEmpty( REFGUID guid );
|
||||
|
||||
static const GUID NullGuid;
|
||||
};
|
||||
|
||||
/** Used to compare GUID keys.
|
||||
*/
|
||||
struct guid_less_predicate
|
||||
{
|
||||
bool operator()( REFGUID guid1,REFGUID guid2 ) const
|
||||
{
|
||||
return memcmp(&guid1,&guid2,sizeof(GUID)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline bool GuidUtil::IsEmpty( REFGUID guid )
|
||||
{
|
||||
return guid == NullGuid;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline const char* GuidUtil::ToString( REFGUID guid )
|
||||
{
|
||||
static char guidString[64];
|
||||
//unsigned short Data4 = *((unsigned short*)guid.Data4);
|
||||
//unsigned long Data5 = *((unsigned long*)&guid.Data4[2]);
|
||||
//unsigned short Data6 = *((unsigned short*)&guid.Data4[6]);
|
||||
sprintf( guidString,"{%.8X-%.4X-%.4X-%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X%}",guid.Data1,guid.Data2,guid.Data3, guid.Data4[0],guid.Data4[1],
|
||||
guid.Data4[2],guid.Data4[3],guid.Data4[4],guid.Data4[5],guid.Data4[6],guid.Data4[7] );
|
||||
return guidString;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline GUID GuidUtil::FromString( const char *guidString )
|
||||
{
|
||||
GUID guid;
|
||||
unsigned int d[8];
|
||||
memset( &d,0,sizeof(guid) );
|
||||
guid.Data1 = 0;
|
||||
guid.Data2 = 0;
|
||||
guid.Data3 = 0;
|
||||
sscanf( guidString,"{%8X-%4hX-%4hX-%2X%2X-%2X%2X%2X%2X%2X%2X%}",
|
||||
&guid.Data1,&guid.Data2,&guid.Data3, &d[0],&d[1],&d[2],&d[3],&d[4],&d[5],&d[6],&d[7] );
|
||||
guid.Data4[0] = d[0];
|
||||
guid.Data4[1] = d[1];
|
||||
guid.Data4[2] = d[2];
|
||||
guid.Data4[3] = d[3];
|
||||
guid.Data4[4] = d[4];
|
||||
guid.Data4[5] = d[5];
|
||||
guid.Data4[6] = d[6];
|
||||
guid.Data4[7] = d[7];
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif // __guidutil_h__
|
||||
1513
Editor/Util/IJL.H
Normal file
1513
Editor/Util/IJL.H
Normal file
File diff suppressed because it is too large
Load Diff
85
Editor/Util/Image.cpp
Normal file
85
Editor/Util/Image.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: Image.cpp
|
||||
// Version: v1.00
|
||||
// Created: 26/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Image implementation,
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Image.h"
|
||||
//#include "libtiff\tiffio.h"
|
||||
|
||||
//#pragma comment( lib,"libtiff/tiff.lib" )
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImage::LoadGrayscale16Tiff( const CString &fileName )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImage::SaveGrayscale16Tiff( const CString &fileName )
|
||||
{
|
||||
/*
|
||||
TIFF * tif;
|
||||
int Width, Height,Bpp;
|
||||
tdata_t buf;
|
||||
|
||||
tif = TIFFOpen(fileName, "rb");
|
||||
if (tif == 0)
|
||||
{
|
||||
MessageBox( NULL,"Not a Tiff file","Warning",MB_OK|MB_ICONEXCLAMATION );
|
||||
return false;
|
||||
}
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &Width);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &Height);
|
||||
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &Bpp);
|
||||
|
||||
int bytes = Bpp/8;
|
||||
int mask = Bpp-1;
|
||||
|
||||
Allocate(Width, Height);
|
||||
*/
|
||||
/*
|
||||
buf = _TIFFmalloc(TIFFScanlineSize(tif));
|
||||
for (int row = 0; row < Height; row++)
|
||||
{
|
||||
TIFFReadScanline(tif, buf, row);
|
||||
unsigned char *pBuf = (unsigned char*)buf;
|
||||
for (int x = 0; x < Width*bytes; x += bytes)
|
||||
{
|
||||
ValueAt( x,row ) = (*(uint*)buf) & mask;
|
||||
pBuf += bytes;
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
*/
|
||||
|
||||
//TIFFClose(tif);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CImage::SwapRedAndBlue()
|
||||
{
|
||||
if (!IsValid())
|
||||
return;
|
||||
// Set the loop pointers
|
||||
uint *pPixData = GetData();
|
||||
uint *pPixDataEnd = pPixData + GetWidth()*GetHeight();
|
||||
// Switch R and B
|
||||
while (pPixData != pPixDataEnd)
|
||||
{
|
||||
// Extract the bits, shift them, put them back and advance to the next pixel
|
||||
*pPixData++ = ((* pPixData & 0x00FF0000) >> 16) |
|
||||
(* pPixData & 0x0000FF00) | ((* pPixData & 0x000000FF) << 16);
|
||||
}
|
||||
}
|
||||
250
Editor/Util/Image.h
Normal file
250
Editor/Util/Image.h
Normal file
@@ -0,0 +1,250 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: Image.h
|
||||
// Version: v1.00
|
||||
// Created: 14/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: General Image
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __Image_h__
|
||||
#define __Image_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class CXmlArchive;
|
||||
|
||||
/*!
|
||||
* Templated image class.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class TImage
|
||||
{
|
||||
public:
|
||||
TImage()
|
||||
{
|
||||
m_data = 0;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
virtual ~TImage() {}
|
||||
|
||||
T& ValueAt( int x,int y ) { return m_data[x+y*m_width]; };
|
||||
const T& ValueAt( int x,int y ) const { return m_data[x+y*m_width]; };
|
||||
|
||||
T* GetData() const { return m_data; };
|
||||
int GetWidth() const { return m_width; };
|
||||
int GetHeight() const { return m_height; };
|
||||
int GetSize() const { return m_width*m_height*sizeof(T); };
|
||||
|
||||
bool IsValid() const { return m_data != 0; };
|
||||
|
||||
void Attach( T* data,int width,int height )
|
||||
{
|
||||
assert( data );
|
||||
m_memory = new CMemoryBlock;
|
||||
m_memory->Attach( data,width*height*sizeof(T) );
|
||||
m_data = data;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
void Attach( const TImage<T> &img )
|
||||
{
|
||||
assert( img.IsValid() );
|
||||
m_memory = img.m_memory;
|
||||
m_data = (T*)m_memory->GetBuffer();
|
||||
m_width = img.m_width;
|
||||
m_height = img.m_height;
|
||||
}
|
||||
void Detach()
|
||||
{
|
||||
m_memory = 0;
|
||||
m_data = 0;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
bool Allocate( int width,int height )
|
||||
{
|
||||
// New memory block.
|
||||
m_memory = new CMemoryBlock;
|
||||
m_memory->Allocate( width*height*sizeof(T) ); // +width for crash safety.
|
||||
m_data = (T*)m_memory->GetBuffer();
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
if (!m_data)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
m_memory = 0;
|
||||
m_data = 0;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
// Copy operator.
|
||||
void Copy( const TImage<T> &img )
|
||||
{
|
||||
if (!img.IsValid())
|
||||
return;
|
||||
if (m_width != img.GetWidth() || m_height != img.GetHeight())
|
||||
Allocate( img.GetWidth(),img.GetHeight() );
|
||||
*m_memory = *img.m_memory;
|
||||
m_data = (T*)m_memory->GetBuffer();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Clear()
|
||||
{
|
||||
Fill(0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Fill( unsigned char c )
|
||||
{
|
||||
if (IsValid())
|
||||
memset( GetData(),c,GetSize() );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void GetSubImage( int x1,int y1,int width,int height,TImage<T> &img )
|
||||
{
|
||||
int size = width*height;
|
||||
img.Allocate( width,height );
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
img.ValueAt(x,y) = ValueAt(x1+x,y1+y);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetSubImage( int x1,int y1,const TImage<T> &subImage )
|
||||
{
|
||||
int width = subImage.GetWidth();
|
||||
int height = subImage.GetHeight();
|
||||
if (x1 < 0)
|
||||
{
|
||||
width = width + x1;
|
||||
x1 = 0;
|
||||
}
|
||||
if (y1 < 0)
|
||||
{
|
||||
height = height + y1;
|
||||
y1 = 0;
|
||||
}
|
||||
if (x1+width > m_width)
|
||||
width = m_width - x1;
|
||||
if (y1+height > m_height)
|
||||
height = m_height - y1;
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
ValueAt(x1+x,y1+y) = subImage.ValueAt(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Compress image to memory block.
|
||||
void Compress( CMemoryBlock &mem ) const
|
||||
{
|
||||
assert( IsValid() );
|
||||
m_memory->Compress(mem);
|
||||
}
|
||||
|
||||
//! Uncompress image from memory block.
|
||||
bool Uncompress( const CMemoryBlock &mem )
|
||||
{
|
||||
assert( IsValid() );
|
||||
// New memory block.
|
||||
TSmartPtr<CMemoryBlock> temp = new CMemoryBlock;
|
||||
mem.Uncompress( *temp );
|
||||
bool bValid = (GetSize() == m_memory->GetSize())
|
||||
|| ((GetSize()+m_width*sizeof(T)) == m_memory->GetSize());
|
||||
if (bValid)
|
||||
{
|
||||
m_memory = temp;
|
||||
m_data = (T*)m_memory->GetBuffer();
|
||||
}
|
||||
return bValid;
|
||||
//assert( GetSize() == m_memory.GetSize() );
|
||||
}
|
||||
|
||||
void Serialize( CXmlArchive &ar );
|
||||
|
||||
private:
|
||||
// Restrict use of copy constructor.
|
||||
TImage( const TImage<T> &img ) {};
|
||||
TImage<T>& operator=( const TImage<T> &img ) {};
|
||||
|
||||
|
||||
//! Memory holding image data.
|
||||
TSmartPtr<CMemoryBlock> m_memory;
|
||||
|
||||
T* m_data;
|
||||
int m_width;
|
||||
int m_height;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void TImage<T>::Serialize( CXmlArchive &ar )
|
||||
{
|
||||
if (ar.bLoading)
|
||||
{
|
||||
// Loading
|
||||
ar.root->getAttr( "ImageWidth",m_width );
|
||||
ar.root->getAttr( "ImageHeight",m_height );
|
||||
m_data = Allocate( m_width,m_height );
|
||||
void *pData = 0;
|
||||
int nDataSize = 0
|
||||
bool bHaveBlock = ar.pNamedData->GetDataBlock( ar.root->getTag(),pData,nDataSize );
|
||||
if (bHaveBlock && nDataSize == GetSize())
|
||||
{
|
||||
m_data = (T*)pData;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
ar.root->setAttr( "ImageWidth",m_width );
|
||||
ar.root->setAttr( "ImageHeight",m_height );
|
||||
|
||||
ar.pNamedData->AddDataBlock( ar.root->getTag(),(void*)m_data,GetSize() );
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CImage : public TImage<unsigned int>
|
||||
{
|
||||
public:
|
||||
bool LoadGrayscale16Tiff( const CString &file );
|
||||
bool SaveGrayscale16Tiff( const CString &file );
|
||||
|
||||
void SwapRedAndBlue();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Define types of most commonly used images.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef TImage<bool> CBoolImage;
|
||||
typedef TImage<float> CFloatImage;
|
||||
typedef TImage<unsigned char> CByteImage;
|
||||
typedef TImage<unsigned short> CWordImage;
|
||||
typedef TImage<unsigned int> CIntImage;
|
||||
|
||||
#endif // __Image_h__
|
||||
473
Editor/Util/ImageGif.cpp
Normal file
473
Editor/Util/ImageGif.cpp
Normal file
@@ -0,0 +1,473 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: imagegif.cpp
|
||||
// Version: v1.00
|
||||
// Created: 15/3/2002 by Timur.
|
||||
// Compilers: Visual C++ 7.0
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ImageGif.h"
|
||||
#include "CryFile.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define NEXTBYTE (*ptr++)
|
||||
#define IMAGESEP 0x2c
|
||||
#define GRAPHIC_EXT 0xf9
|
||||
#define PLAINTEXT_EXT 0x01
|
||||
#define APPLICATION_EXT 0xff
|
||||
#define COMMENT_EXT 0xfe
|
||||
#define START_EXTENSION 0x21
|
||||
#define INTERLACEMASK 0x40
|
||||
#define COLORMAPMASK 0x80
|
||||
#define CHK(x) x
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct SRGBcolor
|
||||
{
|
||||
uchar red, green, blue;
|
||||
};
|
||||
struct SRGBPixel
|
||||
{
|
||||
uchar red, green, blue, alpha;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static int BitOffset = 0, /* Bit Offset of next code */
|
||||
XC = 0, YC = 0, /* Output X and Y coords of current pixel */
|
||||
Pass = 0, /* Used by output routine if interlaced pic */
|
||||
OutCount = 0, /* Decompressor output 'stack count' */
|
||||
RWidth, RHeight, /* screen dimensions */
|
||||
Width, Height, /* image dimensions */
|
||||
LeftOfs, TopOfs, /* image offset */
|
||||
BitsPerPixel, /* Bits per pixel, read from GIF header */
|
||||
BytesPerScanline, /* bytes per scanline in output raster */
|
||||
ColorMapSize, /* number of colors */
|
||||
Background, /* background color */
|
||||
CodeSize, /* Code size, read from GIF header */
|
||||
InitCodeSize, /* Starting code size, used during Clear */
|
||||
Code, /* Value returned by ReadCode */
|
||||
MaxCode, /* limiting value for current code size */
|
||||
ClearCode, /* GIF clear code */
|
||||
EOFCode, /* GIF end-of-information code */
|
||||
CurCode, OldCode, InCode, /* Decompressor variables */
|
||||
FirstFree, /* First free code, generated per GIF spec */
|
||||
FreeCode, /* Decompressor, next free slot in hash table*/
|
||||
FinChar, /* Decompressor variable */
|
||||
BitMask, /* AND mask for data size */
|
||||
ReadMask; /* Code AND mask for current code size */
|
||||
|
||||
static bool Interlace, HasColormap;
|
||||
|
||||
static SRGBPixel *Image; /* The result array */
|
||||
static SRGBcolor* Palette; /* The palette that is used */
|
||||
static uchar* IndexImage;
|
||||
|
||||
static uchar *Raster; /* The raster data stream, unblocked */
|
||||
|
||||
static uchar used[256];
|
||||
static int numused;
|
||||
|
||||
const char *id87 = "GIF87a";
|
||||
const char *id89 = "GIF89a";
|
||||
|
||||
static int log2 (int);
|
||||
|
||||
/* Fetch the next code from the raster data stream. The codes can be
|
||||
* any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
|
||||
* maintain our location in the Raster array as a BIT Offset. We compute
|
||||
* the uchar Offset into the raster array by dividing this by 8, pick up
|
||||
* three bytes, compute the bit Offset into our 24-bit chunk, shift to
|
||||
* bring the desired code to the bottom, then mask it off and return it.
|
||||
*/
|
||||
inline int ReadCode (void)
|
||||
{
|
||||
int RawCode, ByteOffset;
|
||||
|
||||
ByteOffset = BitOffset / 8;
|
||||
RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
|
||||
|
||||
if (CodeSize >= 8)
|
||||
RawCode += (0x10000 * Raster[ByteOffset + 2]);
|
||||
|
||||
RawCode >>= (BitOffset % 8);
|
||||
BitOffset += CodeSize;
|
||||
|
||||
return RawCode & ReadMask;
|
||||
}
|
||||
|
||||
inline void AddToPixel (uchar Index)
|
||||
{
|
||||
if (YC<Height)
|
||||
{
|
||||
SRGBPixel* p = Image + YC * BytesPerScanline + XC;
|
||||
p->red = Palette[Index].red;
|
||||
p->green = Palette[Index].green;
|
||||
p->blue = Palette[Index].blue;
|
||||
p->alpha = 0;
|
||||
IndexImage[YC * BytesPerScanline + XC] = Index;
|
||||
}
|
||||
|
||||
if (!used[Index]) { used[Index]=1; numused++; }
|
||||
|
||||
/* Update the X-coordinate, and if it overflows, update the Y-coordinate */
|
||||
|
||||
if (++XC == Width)
|
||||
{
|
||||
|
||||
/* If a non-interlaced picture, just increment YC to the next scan line.
|
||||
* If it's interlaced, deal with the interlace as described in the GIF
|
||||
* spec. Put the decoded scan line out to the screen if we haven't gone
|
||||
* past the bottom of it
|
||||
*/
|
||||
|
||||
XC = 0;
|
||||
if (!Interlace) YC++;
|
||||
else
|
||||
{
|
||||
switch (Pass)
|
||||
{
|
||||
case 0:
|
||||
YC += 8;
|
||||
if (YC >= Height)
|
||||
{
|
||||
Pass++;
|
||||
YC = 4;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
YC += 8;
|
||||
if (YC >= Height)
|
||||
{
|
||||
Pass++;
|
||||
YC = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
YC += 4;
|
||||
if (YC >= Height)
|
||||
{
|
||||
Pass++;
|
||||
YC = 1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
YC += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CImageGif::Load( const CString &fileName,CImage &outImage )
|
||||
{
|
||||
std::vector<uchar> data;
|
||||
CCryFile file;
|
||||
if (!file.Open( fileName,"rb" ))
|
||||
{
|
||||
CLogFile::FormatLine( "File not found %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
long filesize = file.GetLength();
|
||||
|
||||
data.resize(filesize);
|
||||
uchar* ptr = &data[0];
|
||||
|
||||
file.Read( ptr,filesize );
|
||||
|
||||
/* Detect if this is a GIF file */
|
||||
if (strncmp ((char*)ptr, "GIF87a", 6) && strncmp ((char*)ptr, "GIF89a", 6))
|
||||
{
|
||||
CLogFile::FormatLine( "Bad GIF file format %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
int numcols;
|
||||
register unsigned char ch, ch1;
|
||||
register uchar *ptr1;
|
||||
register int i;
|
||||
short transparency = -1;
|
||||
|
||||
/* The hash table used by the decompressor */
|
||||
int* Prefix;
|
||||
int* Suffix;
|
||||
|
||||
/* An output array used by the decompressor */
|
||||
int* OutCode;
|
||||
|
||||
CHK (Prefix = new int [4096]);
|
||||
CHK (Suffix = new int [4096]);
|
||||
CHK (OutCode = new int [1025]);
|
||||
|
||||
BitOffset = 0;
|
||||
XC = YC = 0;
|
||||
Pass = 0;
|
||||
OutCount = 0;
|
||||
|
||||
Palette = NULL;
|
||||
CHK (Raster = new uchar [filesize]);
|
||||
|
||||
if (strncmp((char *) ptr, id87, 6))
|
||||
if (strncmp((char *) ptr, id89, 6))
|
||||
{
|
||||
CLogFile::FormatLine( "Bad GIF file format %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr += 6;
|
||||
|
||||
/* Get variables from the GIF screen descriptor */
|
||||
|
||||
ch = NEXTBYTE;
|
||||
RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */
|
||||
ch = NEXTBYTE;
|
||||
RHeight = ch + 0x100 * NEXTBYTE;
|
||||
|
||||
ch = NEXTBYTE;
|
||||
HasColormap = ((ch & COLORMAPMASK) ? true : false);
|
||||
|
||||
BitsPerPixel = (ch & 7) + 1;
|
||||
numcols = ColorMapSize = 1 << BitsPerPixel;
|
||||
BitMask = ColorMapSize - 1;
|
||||
|
||||
Background = NEXTBYTE; /* background color... not used. */
|
||||
|
||||
if (NEXTBYTE) /* supposed to be NULL */
|
||||
{
|
||||
CLogFile::FormatLine( "Bad GIF file format %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Read in global colormap. */
|
||||
SRGBcolor mspPal[1024];
|
||||
|
||||
if (HasColormap)
|
||||
{
|
||||
for (i = 0; i < ColorMapSize; i++)
|
||||
{
|
||||
mspPal[i].red = NEXTBYTE;
|
||||
mspPal[i].green = NEXTBYTE;
|
||||
mspPal[i].blue = NEXTBYTE;
|
||||
used[i] = 0;
|
||||
}
|
||||
Palette = mspPal;
|
||||
|
||||
numused = 0;
|
||||
} /* else no colormap in GIF file */
|
||||
|
||||
/* look for image separator */
|
||||
|
||||
for (ch = NEXTBYTE ; ch != IMAGESEP ; ch = NEXTBYTE)
|
||||
{
|
||||
i = ch;
|
||||
if (ch != START_EXTENSION)
|
||||
{
|
||||
CLogFile::FormatLine( "Bad GIF file format %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* handle image extensions */
|
||||
switch (ch = NEXTBYTE)
|
||||
{
|
||||
case GRAPHIC_EXT:
|
||||
ch = NEXTBYTE;
|
||||
if (ptr[0] & 0x1)
|
||||
transparency = ptr[3]; /* transparent color index */
|
||||
ptr += ch;
|
||||
break;
|
||||
case PLAINTEXT_EXT:
|
||||
break;
|
||||
case APPLICATION_EXT:
|
||||
break;
|
||||
case COMMENT_EXT:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
CLogFile::FormatLine( "Invalid GIF89 extension %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while ((ch = NEXTBYTE)) ptr += ch;
|
||||
}
|
||||
|
||||
//if (transparency >= 0)
|
||||
//mfSet_transparency(transparency);
|
||||
|
||||
/* Now read in values from the image descriptor */
|
||||
|
||||
ch = NEXTBYTE;
|
||||
LeftOfs = ch + 0x100 * NEXTBYTE;
|
||||
ch = NEXTBYTE;
|
||||
TopOfs = ch + 0x100 * NEXTBYTE;
|
||||
ch = NEXTBYTE;
|
||||
Width = ch + 0x100 * NEXTBYTE;
|
||||
ch = NEXTBYTE;
|
||||
Height = ch + 0x100 * NEXTBYTE;
|
||||
Interlace = ((NEXTBYTE & INTERLACEMASK) ? true : false);
|
||||
|
||||
TImage<uchar> outImageIndex;
|
||||
// Set the dimensions which will also allocate the image data
|
||||
// buffer.
|
||||
outImage.Allocate(Width,Height);
|
||||
//mfSet_dimensions (Width, Height);
|
||||
Image = (SRGBPixel*)outImage.GetData();
|
||||
outImageIndex.Allocate(Width,Height);
|
||||
IndexImage = outImageIndex.GetData();
|
||||
|
||||
/* Note that I ignore the possible existence of a local color map.
|
||||
* I'm told there aren't many files around that use them, and the spec
|
||||
* says it's defined for future use. This could lead to an error
|
||||
* reading some files.
|
||||
*/
|
||||
|
||||
/* Start reading the raster data. First we get the intial code size
|
||||
* and compute decompressor constant values, based on this code size.
|
||||
*/
|
||||
|
||||
CodeSize = NEXTBYTE;
|
||||
ClearCode = (1 << CodeSize);
|
||||
EOFCode = ClearCode + 1;
|
||||
FreeCode = FirstFree = ClearCode + 2;
|
||||
|
||||
/* The GIF spec has it that the code size is the code size used to
|
||||
* compute the above values is the code size given in the file, but the
|
||||
* code size used in compression/decompression is the code size given in
|
||||
* the file plus one. (thus the ++).
|
||||
*/
|
||||
|
||||
CodeSize++;
|
||||
InitCodeSize = CodeSize;
|
||||
MaxCode = (1 << CodeSize);
|
||||
ReadMask = MaxCode - 1;
|
||||
|
||||
/* Read the raster data. Here we just transpose it from the GIF array
|
||||
* to the Raster array, turning it from a series of blocks into one long
|
||||
* data stream, which makes life much easier for ReadCode().
|
||||
*/
|
||||
|
||||
ptr1 = Raster;
|
||||
do
|
||||
{
|
||||
ch = ch1 = NEXTBYTE;
|
||||
while (ch--) *ptr1++ = NEXTBYTE;
|
||||
if ((ptr1 - Raster) > filesize)
|
||||
{
|
||||
CLogFile::FormatLine( "Corrupted GIF file (unblock) %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (ch1);
|
||||
|
||||
BytesPerScanline = Width;
|
||||
|
||||
|
||||
/* Decompress the file, continuing until you see the GIF EOF code.
|
||||
* One obvious enhancement is to add checking for corrupt files here.
|
||||
*/
|
||||
|
||||
Code = ReadCode ();
|
||||
while (Code != EOFCode)
|
||||
{
|
||||
|
||||
/* Clear code sets everything back to its initial value, then reads the
|
||||
* immediately subsequent code as uncompressed data.
|
||||
*/
|
||||
|
||||
if (Code == ClearCode)
|
||||
{
|
||||
CodeSize = InitCodeSize;
|
||||
MaxCode = (1 << CodeSize);
|
||||
ReadMask = MaxCode - 1;
|
||||
FreeCode = FirstFree;
|
||||
CurCode = OldCode = Code = ReadCode();
|
||||
FinChar = CurCode & BitMask;
|
||||
AddToPixel (FinChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If not a clear code, then must be data: save same as CurCode and InCode */
|
||||
CurCode = InCode = Code;
|
||||
|
||||
/* If greater or equal to FreeCode, not in the hash table yet;
|
||||
* repeat the last character decoded
|
||||
*/
|
||||
|
||||
if (CurCode >= FreeCode)
|
||||
{
|
||||
CurCode = OldCode;
|
||||
OutCode[OutCount++] = FinChar;
|
||||
}
|
||||
|
||||
/* Unless this code is raw data, pursue the chain pointed to by CurCode
|
||||
* through the hash table to its end; each code in the chain puts its
|
||||
* associated output code on the output queue.
|
||||
*/
|
||||
|
||||
while (CurCode > BitMask)
|
||||
{
|
||||
if (OutCount > 1024)
|
||||
{
|
||||
CLogFile::FormatLine( "Corrupted GIF file (OutCount) %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
OutCode[OutCount++] = Suffix[CurCode];
|
||||
CurCode = Prefix[CurCode];
|
||||
}
|
||||
|
||||
/* The last code in the chain is treated as raw data. */
|
||||
|
||||
FinChar = CurCode & BitMask;
|
||||
OutCode[OutCount++] = FinChar;
|
||||
|
||||
/* Now we put the data out to the Output routine.
|
||||
* It's been stacked LIFO, so deal with it that way...
|
||||
*/
|
||||
|
||||
for (i = OutCount - 1; i >= 0; i--)
|
||||
AddToPixel (OutCode[i]);
|
||||
OutCount = 0;
|
||||
|
||||
/* Build the hash table on-the-fly. No table is stored in the file. */
|
||||
|
||||
Prefix[FreeCode] = OldCode;
|
||||
Suffix[FreeCode] = FinChar;
|
||||
OldCode = InCode;
|
||||
|
||||
/* Point to the next slot in the table. If we exceed the current
|
||||
* MaxCode value, increment the code size unless it's already 12. If it
|
||||
* is, do nothing: the next code decompressed better be CLEAR
|
||||
*/
|
||||
|
||||
FreeCode++;
|
||||
if (FreeCode >= MaxCode)
|
||||
{
|
||||
if (CodeSize < 12)
|
||||
{
|
||||
CodeSize++;
|
||||
MaxCode *= 2;
|
||||
ReadMask = (1 << CodeSize) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Code = ReadCode ();
|
||||
}
|
||||
|
||||
//cleanup:
|
||||
if (Raster) { CHK (delete [] Raster); }
|
||||
if (Prefix) { CHK (delete [] Prefix); }
|
||||
if (Suffix) { CHK (delete [] Suffix); }
|
||||
if (OutCode) { CHK (delete [] OutCode); }
|
||||
|
||||
return true;
|
||||
}
|
||||
30
Editor/Util/ImageGif.h
Normal file
30
Editor/Util/ImageGif.h
Normal file
@@ -0,0 +1,30 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: imagegif.h
|
||||
// Version: v1.00
|
||||
// Created: 15/3/2002 by Timur.
|
||||
// Compilers: Visual C++ 7.0
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __imagegif_h__
|
||||
#define __imagegif_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class CImageGif
|
||||
{
|
||||
public:
|
||||
bool Load( const CString &fileName,CImage &outImage );
|
||||
};
|
||||
|
||||
|
||||
#endif // __imagegif_h__
|
||||
155
Editor/Util/ImagePainter.cpp
Normal file
155
Editor/Util/ImagePainter.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: imagepainter.cpp
|
||||
// Version: v1.00
|
||||
// Created: 11/10/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ImagePainter.h"
|
||||
#include "Image.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CImagePainter::CImagePainter()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CImagePainter::~CImagePainter()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CImagePainter::PaintBrush( TImage<unsigned char> &image,int px,int py,SPaintBrush &brush )
|
||||
{
|
||||
if (brush.type == SMOOTH_BRUSH)
|
||||
{
|
||||
SmoothBrush( image,px,py,brush );
|
||||
return;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Draw an attenuated spot on the map
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
int i, j;
|
||||
int iPosX, iPosY;
|
||||
float fMaxDist, fAttenuation, fYSquared;
|
||||
float fHardness = brush.hardness;
|
||||
|
||||
unsigned int pos;
|
||||
|
||||
unsigned char *src = image.GetData();
|
||||
|
||||
int value = brush.color;
|
||||
|
||||
// Calculate the maximum distance
|
||||
fMaxDist = brush.radius;
|
||||
|
||||
int width = image.GetWidth();
|
||||
int height = image.GetHeight();
|
||||
|
||||
for (j = -brush.radius; j < brush.radius; j++)
|
||||
{
|
||||
// Precalculate
|
||||
iPosY = py + j;
|
||||
fYSquared = (float)(j*j);
|
||||
|
||||
for (i = -brush.radius; i < brush.radius; i++)
|
||||
{
|
||||
// Calculate the position
|
||||
iPosX = px + i;
|
||||
|
||||
// Skip invalid locations
|
||||
if (iPosX < 0 || iPosY < 0 || iPosX > width - 1 || iPosY > height - 1)
|
||||
continue;
|
||||
|
||||
// Only circle.
|
||||
float dist = sqrtf(fYSquared + i*i);
|
||||
if (dist > fMaxDist)
|
||||
continue;
|
||||
|
||||
// Calculate the array index
|
||||
pos = iPosX + iPosY * width;
|
||||
|
||||
// Calculate attenuation factor
|
||||
fAttenuation = 1.0f - __min(1.0f, dist/fMaxDist);
|
||||
|
||||
int h = src[pos];
|
||||
int dh = value - h;
|
||||
float fh = (fAttenuation)*dh*fHardness + h;
|
||||
|
||||
src[pos] = ftoi(fh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CImagePainter::SmoothBrush( CByteImage &image,int px,int py,SPaintBrush &brush )
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Draw an attenuated spot on the map
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
int i, j;
|
||||
int iPosX, iPosY;
|
||||
float fMaxDist, fYSquared;
|
||||
float fHardness = brush.hardness;
|
||||
|
||||
unsigned int pos;
|
||||
|
||||
unsigned char *src = image.GetData();
|
||||
|
||||
int value = brush.color;
|
||||
|
||||
// Calculate the maximum distance
|
||||
fMaxDist = brush.radius;
|
||||
|
||||
int width = image.GetWidth();
|
||||
int height = image.GetHeight();
|
||||
int maxsize = width*height;
|
||||
|
||||
for (j = -brush.radius; j < brush.radius; j++)
|
||||
{
|
||||
// Precalculate
|
||||
iPosY = py + j;
|
||||
fYSquared = (float)(j*j);
|
||||
|
||||
for (i = -brush.radius; i < brush.radius; i++)
|
||||
{
|
||||
// Calculate the position
|
||||
iPosX = px + i;
|
||||
|
||||
// Skip invalid locations
|
||||
if (iPosX < 1 || iPosY < 1 || iPosX > width - 2 || iPosY > height - 2)
|
||||
continue;
|
||||
|
||||
// Only circle.
|
||||
float dist = sqrtf(fYSquared + i*i);
|
||||
if (dist > fMaxDist)
|
||||
continue;
|
||||
|
||||
// Calculate the array index
|
||||
pos = iPosX + iPosY * width;
|
||||
|
||||
// Calculate attenuation factor
|
||||
float currH = src[pos];
|
||||
float h =
|
||||
((uint)currH +
|
||||
src[pos+1] +
|
||||
src[pos-1] +
|
||||
src[pos+width] +
|
||||
src[pos-width] +
|
||||
src[pos+1+width] +
|
||||
src[pos+1-width] +
|
||||
src[pos-1+width] +
|
||||
src[pos-1-width]
|
||||
) / 9.0f;
|
||||
|
||||
src[pos] = FloatToIntRet(currH + (h-currH)*fHardness);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Editor/Util/ImagePainter.h
Normal file
55
Editor/Util/ImagePainter.h
Normal file
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: imagepainter.h
|
||||
// Version: v1.00
|
||||
// Created: 11/10/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __imagepainter_h__
|
||||
#define __imagepainter_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/** Contains image painting functions.
|
||||
*/
|
||||
class CImagePainter
|
||||
{
|
||||
public:
|
||||
CImagePainter();
|
||||
~CImagePainter();
|
||||
|
||||
enum EBrushType
|
||||
{
|
||||
PAINT_BRUSH,
|
||||
SMOOTH_BRUSH,
|
||||
};
|
||||
|
||||
// Brush structure used for painting.
|
||||
struct SPaintBrush
|
||||
{
|
||||
EBrushType type;
|
||||
unsigned char color; //!< Painting color.
|
||||
int radius; //!< Inner radius.
|
||||
float hardness; //!< 0-1 hardness of brush.
|
||||
};
|
||||
|
||||
//! Paint spot on image at position px,py with specified paint brush parameters.
|
||||
void PaintBrush( CByteImage &image,int px,int py,SPaintBrush &brush );
|
||||
//void PaintBrush( int iX, int iY, int radius, float fHeigh,float fHardness=1.0f,bool bAddNoise = false,float noiseFreq=1,float noiseScale=1 );
|
||||
|
||||
private:
|
||||
void SmoothBrush( CByteImage &image,int px,int py,SPaintBrush &brush );
|
||||
};
|
||||
|
||||
|
||||
#endif // __imagepainter_h__
|
||||
874
Editor/Util/ImageUtil.cpp
Normal file
874
Editor/Util/ImageUtil.cpp
Normal file
@@ -0,0 +1,874 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: ImageUtil.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/1/2002 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Image utilities implementation.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ImageUtil.h"
|
||||
#include "ImageGif.h"
|
||||
#include "Image_DXTC.h"
|
||||
#include "CryFile.h"
|
||||
|
||||
#ifndef WIN64
|
||||
// Required linking with (Intels Jpeg Library) IJL15.LIB
|
||||
#include "ijl.h"
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::SaveBitmap( const CString &szFileName, CImage &inImage,bool inverseY )
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Simple DIB save code
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HANDLE hfile;
|
||||
DWORD dwBytes;
|
||||
unsigned int i;
|
||||
DWORD *pLine1 = NULL;
|
||||
DWORD *pLine2 = NULL;
|
||||
DWORD *pTemp = NULL;
|
||||
BITMAPFILEHEADER bitmapfileheader;
|
||||
BITMAPINFOHEADER bitmapinfoheader;
|
||||
|
||||
CLogFile::FormatLine("Saving data to bitmap... %s", (const char*)szFileName);
|
||||
|
||||
int dwWidth = inImage.GetWidth();
|
||||
int dwHeight = inImage.GetHeight();
|
||||
DWORD *pData = (DWORD*)inImage.GetData();
|
||||
|
||||
uchar *pImage = new uchar[dwWidth*dwHeight*3];
|
||||
|
||||
i = 0;
|
||||
for (int y = 0; y < dwHeight; y++)
|
||||
{
|
||||
int src_y=y;
|
||||
|
||||
if(inverseY)
|
||||
src_y=(dwHeight-1)-y;
|
||||
|
||||
for (int x = 0; x < dwWidth; x++)
|
||||
{
|
||||
DWORD c = pData[x+src_y*dwWidth];
|
||||
pImage[i] = GetBValue(c);
|
||||
pImage[i+1] = GetGValue(c);
|
||||
pImage[i+2] = GetRValue(c);
|
||||
i+=3;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in bitmap structures
|
||||
bitmapfileheader.bfType = 0x4D42;
|
||||
bitmapfileheader.bfSize = (dwWidth * dwHeight * 3) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
bitmapfileheader.bfReserved1 = 0;
|
||||
bitmapfileheader.bfReserved2 = 0;
|
||||
bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
|
||||
sizeof(BITMAPINFOHEADER) + (0 * sizeof(RGBQUAD));
|
||||
bitmapinfoheader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapinfoheader.biWidth = dwWidth;
|
||||
bitmapinfoheader.biHeight = dwHeight;
|
||||
bitmapinfoheader.biPlanes = 1;
|
||||
bitmapinfoheader.biBitCount = (WORD) 24;
|
||||
bitmapinfoheader.biCompression = BI_RGB;
|
||||
bitmapinfoheader.biSizeImage = 0;
|
||||
bitmapinfoheader.biXPelsPerMeter = 0;
|
||||
bitmapinfoheader.biYPelsPerMeter = 0;
|
||||
bitmapinfoheader.biClrUsed = 0;
|
||||
bitmapinfoheader.biClrImportant = 0;
|
||||
|
||||
// Write bitmap to disk
|
||||
hfile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hfile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
delete []pImage;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the headers to the file
|
||||
WriteFile(hfile, &bitmapfileheader, sizeof(BITMAPFILEHEADER), &dwBytes, NULL);
|
||||
WriteFile(hfile, &bitmapinfoheader, sizeof(BITMAPINFOHEADER), &dwBytes, NULL);
|
||||
|
||||
// Write the data
|
||||
DWORD written;
|
||||
WriteFile(hfile, pImage, (dwWidth * dwHeight * 3), &written, NULL);
|
||||
|
||||
CloseHandle(hfile);
|
||||
|
||||
delete []pImage;
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::SaveJPEG( const CString &strFileName,CImage &inImage )
|
||||
{
|
||||
#ifdef WIN64
|
||||
return false;
|
||||
#else //WIN64
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Save an array as a JPEG
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool bSuccess = true;
|
||||
JPEG_CORE_PROPERTIES Image;
|
||||
unsigned char *pImageData = NULL;
|
||||
unsigned char *pImageDataStart = NULL;
|
||||
|
||||
CLogFile::FormatLine("Saving data to JPEG... %s", (const char*)strFileName);
|
||||
|
||||
|
||||
int dwWidth = inImage.GetWidth();
|
||||
int dwHeight = inImage.GetHeight();
|
||||
DWORD *pData = (DWORD*)inImage.GetData();
|
||||
|
||||
// Convert from RGBA to RGB
|
||||
// Allocate memory for the converted image
|
||||
pImageData = new unsigned char[dwWidth * dwHeight * 3];
|
||||
|
||||
// Set the loop pointer
|
||||
pImageDataStart = pImageData;
|
||||
DWORD *pDataEnd = &pData[dwWidth * dwHeight];
|
||||
|
||||
// Convert
|
||||
while (pData != pDataEnd)
|
||||
{
|
||||
// Extract the color channels and copy them into the indivdual
|
||||
// bytes of the converted image
|
||||
*pImageData++ = GetRValue(*pData);
|
||||
*pImageData++ = GetGValue(*pData);
|
||||
*pImageData++ = GetBValue(*pData);
|
||||
|
||||
// Advance to the next source pixel
|
||||
pData++;
|
||||
}
|
||||
|
||||
// Restore the pointer
|
||||
pImageData = pImageDataStart;
|
||||
|
||||
// Init the JPEG structure
|
||||
memset(&Image, 0, sizeof(JPEG_CORE_PROPERTIES));
|
||||
|
||||
bool failed = false;
|
||||
|
||||
// Initialize
|
||||
if (ijlInit(&Image) != IJL_OK)
|
||||
{
|
||||
Warning("Can't initialize Intel(R) JPEG library !");
|
||||
return failed;
|
||||
}
|
||||
|
||||
// Setup DIB
|
||||
Image.DIBWidth = dwWidth;
|
||||
Image.DIBHeight = dwHeight;
|
||||
Image.DIBBytes = pImageData;
|
||||
Image.DIBPadBytes = IJL_DIB_PAD_BYTES(Image.DIBWidth, 3);
|
||||
|
||||
// Setup JPEG
|
||||
Image.JPGFile = const_cast<char *> ((const char*)strFileName);
|
||||
Image.JPGWidth = dwWidth;
|
||||
Image.JPGHeight = dwHeight;
|
||||
|
||||
Image.jquality = 100;
|
||||
|
||||
Image.DIBColor = IJL_RGB;
|
||||
|
||||
// Remove the read-only attribute so the JPEG library can overwrite the file.
|
||||
SetFileAttributes(strFileName, FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
// Write the image
|
||||
if (ijlWrite( &Image, IJL_JFILE_WRITEWHOLEIMAGE ) != IJL_OK)
|
||||
{
|
||||
Warning("Can't JPEG write image !");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
if (ijlFree(&Image) != IJL_OK)
|
||||
{
|
||||
Warning("Can't free Intel(R) JPEG library !");
|
||||
}
|
||||
|
||||
// Free the temporary memory
|
||||
delete [] pImageData;
|
||||
pImageData = 0;
|
||||
|
||||
return bSuccess;
|
||||
|
||||
#endif //WIN64
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::LoadJPEG( const CString &strFileName,CImage &outImage )
|
||||
{
|
||||
#ifdef WIN64
|
||||
return false;
|
||||
#else //WIN64
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Loads a JPEG file and stores image dimension data in the passed
|
||||
// pointers. Memory for the image itself is allocated and passed
|
||||
// and the passed pointer is set
|
||||
//
|
||||
// TODO: Verify that this functions works
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
JPEG_CORE_PROPERTIES Image;
|
||||
ASSERT(!strFileName.IsEmpty());
|
||||
BYTE *pImageData = NULL;
|
||||
|
||||
CLogFile::FormatLine("Loading JPEG %s...", (const char*)strFileName );
|
||||
|
||||
ZeroMemory(&Image, sizeof(JPEG_CORE_PROPERTIES));
|
||||
|
||||
// Initialize the JPEG library
|
||||
if (ijlInit(&Image) != IJL_OK)
|
||||
{
|
||||
Warning("Can't initialize Intel(R) JPEG library !");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the filename
|
||||
Image.JPGFile = strFileName;
|
||||
|
||||
// Read the JPEG header
|
||||
if (ijlRead(&Image, IJL_JFILE_READPARAMS) != IJL_OK)
|
||||
{
|
||||
Warning("Error while reading JPEG file (Header) !");
|
||||
|
||||
return false;
|
||||
}
|
||||
if (Image.JPGChannels != 3)
|
||||
{
|
||||
CLogFile::FormatLine( "JPG File %s is not 3 channels jpeg format.",(const char*)strFileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate memory for the image
|
||||
pImageData = new BYTE[Image.JPGWidth * Image.JPGHeight * Image.JPGChannels];
|
||||
ASSERT(pImageData);
|
||||
|
||||
// Fill in the DIB header
|
||||
Image.DIBBytes = pImageData;
|
||||
Image.DIBColor = (Image.JPGChannels == 3) ? IJL_RGB : IJL_G;
|
||||
Image.DIBWidth = Image.JPGWidth;
|
||||
Image.DIBHeight = Image.JPGHeight;
|
||||
Image.DIBChannels = Image.JPGChannels;
|
||||
|
||||
// Read the JPEG image
|
||||
if (ijlRead(&Image, IJL_JFILE_READWHOLEIMAGE) != IJL_OK)
|
||||
{
|
||||
Warning("Error while reading JPEG file (Whole Image) !");
|
||||
|
||||
ijlFree(&Image);
|
||||
delete []pImageData;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free the image
|
||||
if (ijlFree(&Image) != IJL_OK)
|
||||
{
|
||||
Warning("Can't free Intel(R) JPEG library !");
|
||||
|
||||
delete []pImageData;
|
||||
return false;
|
||||
}
|
||||
|
||||
int memSize = Image.JPGWidth*Image.JPGHeight*4;
|
||||
outImage.Allocate( Image.JPGWidth,Image.JPGHeight );
|
||||
uint *trg = outImage.GetData();
|
||||
if (!trg)
|
||||
{
|
||||
Warning( "CImageUtil::LoadJPEG Memory allocation faild\r\nFailed to allocate %dMb of RAM for Jpg %s",
|
||||
memSize/(1024*1024),(const char*)strFileName );
|
||||
return false;
|
||||
}
|
||||
unsigned char *src = pImageData;
|
||||
if (src && trg)
|
||||
{
|
||||
for (int i = 0; i < Image.JPGHeight*Image.JPGWidth; i++)
|
||||
{
|
||||
*trg++ = RGB(src[0],src[1],src[2]) | 0xFF000000;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
delete []pImageData;
|
||||
|
||||
return true;
|
||||
|
||||
#endif //WIN64
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::SavePGM( const CString &fileName, uint dwWidth, uint dwHeight, uint *pData)
|
||||
{
|
||||
FILE *file = fopen( fileName,"wt" );
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
char s[65536];
|
||||
|
||||
fprintf( file, "P2\n", s );
|
||||
fprintf( file, "%d %d\n", dwWidth,dwHeight );
|
||||
fprintf( file, "65535\n" );
|
||||
for (int y = 0; y < dwHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < dwWidth; x++)
|
||||
{
|
||||
fprintf( file, "%d ",(uint)pData[x+y*dwWidth] );
|
||||
}
|
||||
fprintf( file, "\n" );
|
||||
}
|
||||
|
||||
fclose( file );
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::LoadPGM( const CString &fileName, uint *pWidthOut, uint *pHeightOut, uint **pImageDataOut)
|
||||
{
|
||||
FILE *file = fopen( fileName,"rt" );
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
const char seps[] = " \n\t";
|
||||
char *token;
|
||||
|
||||
|
||||
int width=0;
|
||||
int height=0;
|
||||
int numColors = 1;
|
||||
|
||||
|
||||
fseek( file,0,SEEK_END );
|
||||
int fileSize = ftell(file);
|
||||
fseek( file,0,SEEK_SET );
|
||||
|
||||
char *str = new char[fileSize];
|
||||
fread( str,fileSize,1,file );
|
||||
|
||||
token = strtok( str,seps );
|
||||
|
||||
while (token != NULL && token[0] == '#')
|
||||
{
|
||||
if (token != NULL && token[0] == '#')
|
||||
strtok( NULL, "\n" );
|
||||
token = strtok( NULL, seps );
|
||||
}
|
||||
if (stricmp(token,"P2") != 0)
|
||||
{
|
||||
// Bad file. not supported pgm.
|
||||
delete []str;
|
||||
fclose( file );
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
token = strtok( NULL, seps );
|
||||
if (token != NULL && token[0] == '#') {
|
||||
strtok( NULL, "\n" );
|
||||
}
|
||||
} while (token != NULL && token[0] == '#');
|
||||
width = atoi(token);
|
||||
|
||||
do {
|
||||
token = strtok( NULL, seps );
|
||||
if (token != NULL && token[0] == '#')
|
||||
strtok( NULL, "\n" );
|
||||
} while (token != NULL && token[0] == '#');
|
||||
height = atoi(token);
|
||||
|
||||
do {
|
||||
token = strtok( NULL, seps );
|
||||
if (token != NULL && token[0] == '#')
|
||||
strtok( NULL, "\n" );
|
||||
} while (token != NULL && token[0] == '#');
|
||||
numColors = atoi(token);
|
||||
|
||||
*pWidthOut = width;
|
||||
*pHeightOut = height;
|
||||
|
||||
uint *pImage = new uint[width*height];
|
||||
*pImageDataOut = pImage;
|
||||
|
||||
uint *p = pImage;
|
||||
int size = width*height;
|
||||
int i = 0;
|
||||
while (token != NULL && i < size)
|
||||
{
|
||||
do { token = strtok( NULL,seps ); } while (token != NULL && token[0] == '#');
|
||||
*p++ = atoi(token);
|
||||
i++;
|
||||
}
|
||||
|
||||
delete []str;
|
||||
|
||||
fclose( file );
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static inline ushort us_endian (const byte* ptr)
|
||||
{
|
||||
short n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline unsigned long ul_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline long l_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
#define BFTYPE(x) us_endian((x) + 0)
|
||||
#define BFSIZE(x) ul_endian((x) + 2)
|
||||
#define BFOFFBITS(x) ul_endian((x) + 10)
|
||||
#define BISIZE(x) ul_endian((x) + 14)
|
||||
#define BIWIDTH(x) l_endian ((x) + 18)
|
||||
#define BIHEIGHT(x) l_endian ((x) + 22)
|
||||
#define BITCOUNT(x) us_endian((x) + 28)
|
||||
#define BICOMP(x) ul_endian((x) + 30)
|
||||
#define IMAGESIZE(x) ul_endian((x) + 34)
|
||||
#define BICLRUSED(x) ul_endian((x) + 46)
|
||||
#define BICLRIMP(x) ul_endian((x) + 50)
|
||||
#define BIPALETTE(x) ((x) + 54)
|
||||
|
||||
// Type ID
|
||||
#define BM "BM" // Windows 3.1x, 95, NT, ...
|
||||
#define BA "BA" // OS/2 Bitmap Array
|
||||
#define CI "CI" // OS/2 Color Icon
|
||||
#define CP "CP" // OS/2 Color Pointer
|
||||
#define IC "IC" // OS/2 Icon
|
||||
#define PT "PT" // OS/2 Pointer
|
||||
|
||||
// Possible values for the header size
|
||||
#define WinHSize 0x28
|
||||
#define OS21xHSize 0x0C
|
||||
#define OS22xHSize 0xF0
|
||||
|
||||
// Possible values for the BPP setting
|
||||
#define Mono 1 // Monochrome bitmap
|
||||
#define _16Color 4 // 16 color bitmap
|
||||
#define _256Color 8 // 256 color bitmap
|
||||
#define HIGHCOLOR 16 // 16bit (high color) bitmap
|
||||
#define TRUECOLOR24 24 // 24bit (true color) bitmap
|
||||
#define TRUECOLOR32 32 // 32bit (true color) bitmap
|
||||
|
||||
// Compression Types
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0 // none
|
||||
#define BI_RLE8 1 // RLE 8-bit / pixel
|
||||
#define BI_RLE4 2 // RLE 4-bit / pixel
|
||||
#define BI_BITFIELDS 3 // Bitfields
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
bool CImageUtil::LoadBmp( const CString &fileName,CImage &image )
|
||||
{
|
||||
#pragma pack(push,1)
|
||||
struct SRGBcolor
|
||||
{
|
||||
uchar red, green, blue;
|
||||
};
|
||||
struct SRGBPixel
|
||||
{
|
||||
uchar red, green, blue, alpha;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::vector<uchar> data;
|
||||
|
||||
CCryFile file;
|
||||
if (!file.Open( fileName,"rb"))
|
||||
{
|
||||
CLogFile::FormatLine( "File not found %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
long iSize = file.GetLength();
|
||||
|
||||
data.resize(iSize);
|
||||
uchar* iBuffer = &data[0];
|
||||
file.Read( iBuffer,iSize );
|
||||
|
||||
if (!((memcmp(iBuffer, BM, 2) == 0) && BISIZE(iBuffer) == WinHSize))
|
||||
{
|
||||
// Not bmp file.
|
||||
CLogFile::FormatLine( "Invalid BMP file format %s",(const char*)fileName );
|
||||
return false;
|
||||
}
|
||||
|
||||
int mWidth = BIWIDTH(iBuffer);
|
||||
int mHeight = BIHEIGHT(iBuffer);
|
||||
image.Allocate(mWidth,mHeight);
|
||||
const int bmp_size = mWidth * mHeight;
|
||||
|
||||
byte *iPtr = iBuffer + BFOFFBITS(iBuffer);
|
||||
|
||||
// The last scanline in BMP corresponds to the top line in the image
|
||||
int buffer_y = mWidth * (mHeight - 1);
|
||||
bool blip = false;
|
||||
|
||||
if (BITCOUNT(iBuffer) == _256Color)
|
||||
{
|
||||
//mpIndexImage = mfGet_IndexImage();
|
||||
byte *buffer = new uchar[mWidth*mHeight];
|
||||
SRGBcolor mspPal[256];
|
||||
SRGBcolor *pwork = mspPal;
|
||||
byte *inpal = BIPALETTE(iBuffer);
|
||||
//mfSet_bps (8);
|
||||
|
||||
for (int color=0; color<256; color++, pwork++)
|
||||
{
|
||||
// Whacky BMP palette is in BGR order.
|
||||
pwork->blue = *inpal++;
|
||||
pwork->green = *inpal++;
|
||||
pwork->red = *inpal++;
|
||||
inpal++; // Skip unused byte.
|
||||
}
|
||||
|
||||
if (BICOMP(iBuffer) == BI_RGB)
|
||||
{
|
||||
// Read the pixels from "top" to "bottom"
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
memcpy (buffer + buffer_y, iPtr, mWidth);
|
||||
iPtr += mWidth;
|
||||
buffer_y -= mWidth;
|
||||
} /* endwhile */
|
||||
}
|
||||
else
|
||||
if (BICOMP(iBuffer) == BI_RLE8)
|
||||
{
|
||||
// Decompress pixel data
|
||||
byte rl, rl1, i; // runlength
|
||||
byte clridx, clridx1; // colorindex
|
||||
int buffer_x = 0;
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
rl = rl1 = *iPtr++;
|
||||
clridx = clridx1 = *iPtr++;
|
||||
if (rl == 0)
|
||||
if (clridx == 0)
|
||||
{
|
||||
// new scanline
|
||||
if (!blip)
|
||||
{
|
||||
// if we didnt already jumped to the new line, do it now
|
||||
buffer_x = 0;
|
||||
buffer_y -= mWidth;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx == 1)
|
||||
// end of bitmap
|
||||
break;
|
||||
else
|
||||
if (clridx == 2)
|
||||
{
|
||||
// next 2 bytes mean column- and scanline- offset
|
||||
buffer_x += *iPtr++;
|
||||
buffer_y -= (mWidth * (*iPtr++));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx > 2)
|
||||
rl1 = clridx;
|
||||
|
||||
for ( i = 0; i < rl1; i++ )
|
||||
{
|
||||
if (!rl)
|
||||
clridx1 = *iPtr++;
|
||||
buffer [buffer_y + buffer_x] = clridx1;
|
||||
|
||||
if (++buffer_x >= mWidth)
|
||||
{
|
||||
buffer_x = 0;
|
||||
buffer_y -= mWidth;
|
||||
blip = true;
|
||||
}
|
||||
else
|
||||
blip = false;
|
||||
}
|
||||
// pad in case rl == 0 and clridx in [3..255]
|
||||
if (rl == 0 && (clridx & 0x01))
|
||||
iPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert indexed to RGBA
|
||||
for (int y = 0; y < mHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < mWidth; x++)
|
||||
{
|
||||
SRGBcolor &entry = mspPal[buffer[x+y*mWidth]];
|
||||
image.ValueAt(x,y) = 0xFF000000 | RGB(entry.red,entry.green,entry.blue);
|
||||
}
|
||||
}
|
||||
|
||||
delete buffer;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR24)
|
||||
{
|
||||
//mfSet_bps (24);
|
||||
SRGBPixel *buffer = (SRGBPixel*)image.GetData();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = mWidth; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = 255;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= mWidth;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR32)
|
||||
{
|
||||
//mfSet_bps (32);
|
||||
SRGBPixel *buffer = (SRGBPixel*)image.GetData();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = mWidth; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = *iPtr++;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= mWidth;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CLogFile::FormatLine( "Unknown BMP image format %s",(const char*)fileName );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::LoadImage( const CString &fileName, CImage &image )
|
||||
{
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
|
||||
_splitpath( fileName,drive,dir,fname,ext );
|
||||
if (stricmp(ext,".bmp") == 0)
|
||||
{
|
||||
return LoadBmp( fileName,image );
|
||||
} else if (stricmp(ext,".jpg") == 0)
|
||||
{
|
||||
return LoadJPEG( fileName,image );
|
||||
} else if (stricmp(ext,".gif") == 0)
|
||||
{
|
||||
CImageGif gif;
|
||||
return gif.Load( fileName,image );
|
||||
} else if (stricmp(ext,".pgm") == 0)
|
||||
{
|
||||
UINT w,h;
|
||||
uint *pData;
|
||||
bool res = LoadPGM( fileName,&w,&h,&pData );
|
||||
if (!res)
|
||||
return false;
|
||||
image.Allocate(w,h);
|
||||
memcpy( image.GetData(),pData,image.GetSize() );
|
||||
delete []pData;
|
||||
}
|
||||
else if (stricmp(ext,".dds") == 0)
|
||||
{
|
||||
// Load DDS file.
|
||||
CImage_DXTC dds;
|
||||
return dds.Load( fileName,image );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImageUtil::SaveImage( const CString &fileName, CImage &image )
|
||||
{
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
|
||||
// Remove the read-only attribute so the file can be overwritten.
|
||||
SetFileAttributes(fileName,FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
_splitpath( fileName,drive,dir,fname,ext );
|
||||
if (stricmp(ext,".bmp") == 0)
|
||||
{
|
||||
return SaveBitmap( fileName,image );
|
||||
} else if (stricmp(ext,".jpg") == 0)
|
||||
{
|
||||
return SaveJPEG( fileName,image );
|
||||
} else if (stricmp(ext,".pgm") == 0)
|
||||
{
|
||||
return SavePGM( fileName,image.GetWidth(),image.GetHeight(),image.GetData() );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CImageUtil::ScaleToFit( const CByteImage &srcImage,CByteImage &trgImage )
|
||||
{
|
||||
uint x,y,u,v;
|
||||
unsigned char *destRow,*dest,*src,*sourceRow;
|
||||
|
||||
uint srcW = srcImage.GetWidth();
|
||||
uint srcH = srcImage.GetHeight();
|
||||
|
||||
uint trgW = trgImage.GetWidth();
|
||||
uint trgH = trgImage.GetHeight();
|
||||
|
||||
uint xratio = (srcW << 16)/trgW;
|
||||
uint yratio = (srcH << 16)/trgH;
|
||||
|
||||
src = srcImage.GetData();
|
||||
destRow = trgImage.GetData();
|
||||
|
||||
v = 0;
|
||||
for (y = 0; y < trgH; y++)
|
||||
{
|
||||
u=0;
|
||||
sourceRow = src + (v >> 16) * srcW;
|
||||
dest = destRow;
|
||||
for (x = 0; x < trgW; x++)
|
||||
{
|
||||
*dest++ = sourceRow[u>>16];
|
||||
u += xratio;
|
||||
}
|
||||
v += yratio;
|
||||
destRow += trgW;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CImageUtil::ScaleToFit( const CImage &srcImage,CImage &trgImage )
|
||||
{
|
||||
uint x,y,u,v;
|
||||
unsigned int *destRow,*dest,*src,*sourceRow;
|
||||
|
||||
uint srcW = srcImage.GetWidth();
|
||||
uint srcH = srcImage.GetHeight();
|
||||
|
||||
uint trgW = trgImage.GetWidth();
|
||||
uint trgH = trgImage.GetHeight();
|
||||
|
||||
uint xratio = (srcW << 16)/trgW;
|
||||
uint yratio = (srcH << 16)/trgH;
|
||||
|
||||
src = srcImage.GetData();
|
||||
destRow = trgImage.GetData();
|
||||
|
||||
v = 0;
|
||||
for (y = 0; y < trgH; y++)
|
||||
{
|
||||
u=0;
|
||||
sourceRow = src + (v >> 16) * srcW;
|
||||
dest = destRow;
|
||||
for (x = 0; x < trgW; x++)
|
||||
{
|
||||
*dest++ = sourceRow[u>>16];
|
||||
u += xratio;
|
||||
}
|
||||
v += yratio;
|
||||
destRow += trgW;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CImageUtil::SmoothImage( CByteImage &image,int numSteps )
|
||||
{
|
||||
assert( numSteps > 0 );
|
||||
uchar *buf = image.GetData();
|
||||
int w = image.GetWidth();
|
||||
int h = image.GetHeight();
|
||||
|
||||
for (int steps = 0; steps < numSteps; steps++)
|
||||
{
|
||||
// Smooth the image.
|
||||
for (int y = 1; y < h-1; y++)
|
||||
{
|
||||
// Precalculate for better speed
|
||||
uchar *ptr = &buf[y*w + 1];
|
||||
|
||||
for (int x = 1; x < w-1; x++)
|
||||
{
|
||||
// Smooth it out
|
||||
*ptr =
|
||||
(
|
||||
(uint)ptr[1] +
|
||||
ptr[w] +
|
||||
ptr[-1] +
|
||||
ptr[-w] +
|
||||
ptr[w+1] +
|
||||
ptr[w-1] +
|
||||
ptr[-w+1] +
|
||||
ptr[-w-1]
|
||||
) >> 3;
|
||||
|
||||
// Next pixel
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char CImageUtil::GetBilinearFilteredAt( const int iniX256, const int iniY256, const CByteImage &image )
|
||||
{
|
||||
// assert(image.IsValid()); if(!image.IsValid())return(0); // this shouldn't be
|
||||
|
||||
DWORD x=(DWORD)(iniX256) >> 8;
|
||||
DWORD y=(DWORD)(iniY256) >> 8;
|
||||
|
||||
if(x>=image.GetWidth()-1 || y>=image.GetHeight()-1)
|
||||
return image.ValueAt(x,y); // border is not filtered, 255 to get in range 0..1
|
||||
|
||||
DWORD rx=(DWORD)(iniX256) & 0xff; // fractional aprt
|
||||
DWORD ry=(DWORD)(iniY256) & 0xff; // fractional aprt
|
||||
|
||||
DWORD top=(DWORD)image.ValueAt((int)x ,(int)y )*(256-rx) // left top
|
||||
+(DWORD)image.ValueAt((int)x+1,(int)y )*rx; // right top
|
||||
|
||||
DWORD bottom =(DWORD)image.ValueAt((int)x ,(int)y+1)*(256-rx) // left bottom
|
||||
+(DWORD)image.ValueAt((int)x+1,(int)y+1)*rx; // right bottom
|
||||
|
||||
return (unsigned char)((top*(256-ry) + bottom*ry)>>16);
|
||||
}
|
||||
|
||||
72
Editor/Util/ImageUtil.h
Normal file
72
Editor/Util/ImageUtil.h
Normal file
@@ -0,0 +1,72 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: ImageUtil.h
|
||||
// Version: v1.00
|
||||
// Created: 30/1/2002 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Image utilities.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __ImageUtil_h__
|
||||
#define __ImageUtil_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Utility Class to manipulate images.
|
||||
*/
|
||||
class CImageUtil
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Image loading.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Load image, detect image type by file extension.
|
||||
static bool LoadImage( const CString &fileName, CImage &image );
|
||||
//! Save image, detect image type by file extension.
|
||||
static bool SaveImage( const CString &fileName, CImage &image );
|
||||
|
||||
// General image fucntions
|
||||
static bool LoadJPEG( const CString &strFileName,CImage &image );
|
||||
static bool SaveJPEG( const CString &strFileName,CImage &image );
|
||||
|
||||
static bool SaveBitmap( const CString &szFileName, CImage &image,bool inverseY=true );
|
||||
static bool SaveBitmap(LPCSTR szFileName, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, HDC hdc);
|
||||
static bool LoadBmp( const CString &file,CImage &image );
|
||||
|
||||
//! Save image in PGM format.
|
||||
static bool SavePGM( const CString &fileName, uint dwWidth, uint dwHeight, uint *pData);
|
||||
//! Load image in PGM format.
|
||||
static bool LoadPGM( const CString &fileName, uint *pWidthOut, uint *pHeightOut, uint **pImageDataOut);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Image scaling.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Scale source image to fit size of target image.
|
||||
static void ScaleToFit( const CByteImage &srcImage,CByteImage &trgImage );
|
||||
//! Scale source image to fit size of target image.
|
||||
static void ScaleToFit( const CImage &srcImage,CImage &trgImage );
|
||||
|
||||
//! Smooth image.
|
||||
static void SmoothImage( CByteImage &image,int numSteps );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// filtered lookup
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! behaviour outside of the texture is not defined
|
||||
//! \param iniX in fix point 24.8
|
||||
//! \param iniY in fix point 24.8
|
||||
//! \return 0..255
|
||||
static unsigned char GetBilinearFilteredAt( const int iniX256, const int iniY256, const CByteImage &image );
|
||||
};
|
||||
|
||||
#endif // __ImageUtil_h__
|
||||
204
Editor/Util/Image_DXTC.cpp
Normal file
204
Editor/Util/Image_DXTC.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: image_dxtc.cpp
|
||||
// Version: v1.00
|
||||
// Created: 5/9/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Image_DXTC.h"
|
||||
#include <CryFile.h>
|
||||
|
||||
#ifndef MAKEFOURCC
|
||||
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
|
||||
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
|
||||
#endif //defined(MAKEFOURCC)
|
||||
#include "dds.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[]=__FILE__;
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
CImage_DXTC::CImage_DXTC()
|
||||
{
|
||||
}
|
||||
|
||||
CImage_DXTC::~CImage_DXTC()
|
||||
{
|
||||
}
|
||||
|
||||
static ETEX_Format DecodePixelFormat( DDS_PIXELFORMAT* pddpf )
|
||||
{
|
||||
ETEX_Format format = eTF_Unknown;
|
||||
switch( pddpf->dwFourCC )
|
||||
{
|
||||
case 0:
|
||||
// This dds texture isn't compressed so write out ARGB format
|
||||
format = eTF_8888;
|
||||
break;
|
||||
|
||||
case MAKEFOURCC('D','X','T','1'):
|
||||
format = eTF_DXT1;
|
||||
break;
|
||||
|
||||
case MAKEFOURCC('D','X','T','2'):
|
||||
//format = eTF_DXT2;
|
||||
break;
|
||||
|
||||
case MAKEFOURCC('D','X','T','3'):
|
||||
format = eTF_DXT3;
|
||||
break;
|
||||
|
||||
case MAKEFOURCC('D','X','T','4'):
|
||||
//format = eTF_DXT4;
|
||||
break;
|
||||
|
||||
case MAKEFOURCC('D','X','T','5'):
|
||||
format = eTF_DXT5;
|
||||
break;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CImage_DXTC::Load( const char *filename,CImage &outImage )
|
||||
{
|
||||
CCryFile file;
|
||||
if (!file.Open( filename,"rb" ))
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
DDS_HEADER ddsd;
|
||||
DWORD dwMagic;
|
||||
|
||||
BYTE *pCompBytes; // compressed image bytes
|
||||
BYTE *pDecompBytes;
|
||||
|
||||
|
||||
// Read magic number
|
||||
file.Read( &dwMagic, sizeof(DWORD) );
|
||||
|
||||
if( dwMagic != MAKEFOURCC('D','D','S',' ') )
|
||||
{
|
||||
return( false);
|
||||
}
|
||||
|
||||
// Read the surface description
|
||||
file.Read( &ddsd, sizeof(DDS_HEADER) );
|
||||
|
||||
|
||||
// Does texture have mipmaps?
|
||||
bool bMipTexture = ( ddsd.dwMipMapCount > 0 ) ? TRUE : FALSE;
|
||||
|
||||
ETEX_Format format = DecodePixelFormat( &ddsd.ddspf );
|
||||
|
||||
if (format == eTF_Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int nCompSize = file.GetLength() - sizeof(DDS_HEADER) - sizeof(DWORD);
|
||||
pCompBytes = new BYTE[nCompSize+32];
|
||||
file.Read( pCompBytes, nCompSize );
|
||||
|
||||
/*
|
||||
// Read only first mip level for now:
|
||||
if (ddsd.dwFlags & DDSD_LINEARSIZE)
|
||||
{
|
||||
pCompBytes = new BYTE[ddsd.dwLinearSize];
|
||||
if (pCompBytes == NULL )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
file.Read( pCompBytes, ddsd.dwLinearSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwBytesPerRow = ddsd.dwWidth * ddsd.ddspf.dwRGBBitCount / 8;
|
||||
pCompBytes = new BYTE[ddsd.lPitch*ddsd.dwHeight];
|
||||
if (pCompBytes == NULL )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
nCompSize = ddsd.lPitch * ddsd.dwHeight;
|
||||
nCompLineSz = dwBytesPerRow;
|
||||
|
||||
BYTE* pDest = pCompBytes;
|
||||
for( DWORD yp = 0; yp < ddsd.dwHeight; yp++ )
|
||||
{
|
||||
file.Read( pDest, dwBytesPerRow );
|
||||
pDest += ddsd.lPitch;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
outImage.Allocate( ddsd.dwWidth,ddsd.dwHeight );
|
||||
pDecompBytes = (BYTE*)outImage.GetData();
|
||||
if (!pDecompBytes)
|
||||
{
|
||||
Warning( "Cannot allocate image %dx%d, Out of memory",ddsd.dwWidth,ddsd.dwHeight );
|
||||
}
|
||||
|
||||
if (format == eTF_8888)
|
||||
{
|
||||
if (ddsd.ddspf.dwRGBBitCount == 24)
|
||||
{
|
||||
unsigned char *dest = pDecompBytes;
|
||||
unsigned char *src = pCompBytes;
|
||||
for (int y = 0; y < ddsd.dwHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < ddsd.dwWidth; x++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 255;
|
||||
dest+=4;
|
||||
src+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ddsd.ddspf.dwRGBBitCount == 32)
|
||||
{
|
||||
unsigned char *dest = pDecompBytes;
|
||||
unsigned char *src = pCompBytes;
|
||||
for (int y = 0; y < ddsd.dwHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < ddsd.dwWidth; x++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
dest+=4;
|
||||
src+=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
//memcpy( pDecompBytes,pCompBytes,nCompSize );
|
||||
}
|
||||
else if (format == eTF_DXT1 || format == eTF_DXT3 || format == eTF_DXT5)
|
||||
{
|
||||
GetIEditor()->GetRenderer()->DXTDecompress( pCompBytes,pDecompBytes,ddsd.dwWidth,ddsd.dwHeight,format,false,4 );
|
||||
}
|
||||
|
||||
delete []pCompBytes;
|
||||
|
||||
outImage.SwapRedAndBlue();
|
||||
|
||||
// done reading file
|
||||
return( true );
|
||||
}
|
||||
29
Editor/Util/Image_DXTC.h
Normal file
29
Editor/Util/Image_DXTC.h
Normal file
@@ -0,0 +1,29 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: image_dxtc.h
|
||||
// Version: v1.00
|
||||
// Created: 5/9/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __image_dxtc_h__
|
||||
#define __image_dxtc_h__
|
||||
#pragma once
|
||||
|
||||
class CImage_DXTC
|
||||
{
|
||||
public:
|
||||
bool Load( const char *filename,CImage &outImage ); // true if success
|
||||
|
||||
CImage_DXTC();
|
||||
~CImage_DXTC();
|
||||
};
|
||||
|
||||
#endif // __image_dxtc_h__
|
||||
332
Editor/Util/Math.h
Normal file
332
Editor/Util/Math.h
Normal file
@@ -0,0 +1,332 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: math.h
|
||||
// Version: v1.00
|
||||
// Created: 2/7/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Various math and geometry related functions.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __math_h__
|
||||
#define __math_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "BBox.h"
|
||||
|
||||
//! Half PI
|
||||
#define PI_HALF (3.1415926535897932384626433832795f / 2.0f)
|
||||
|
||||
//! Epsilon for vector comparasions.
|
||||
#define FLOAT_EPSILON 0.0001f
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** Compare two vectors if they are equal.
|
||||
*/
|
||||
inline bool IsVectorsEqual( const Vec3 &v1,const Vec3 &v2 )
|
||||
{
|
||||
if (fabs(v2.x-v1.x) < FLOAT_EPSILON && fabs(v2.y-v1.y) < FLOAT_EPSILON && fabs(v2.z-v1.z) < FLOAT_EPSILON)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** Compare two matrices if they are equal.
|
||||
*/
|
||||
inline bool IsMatrixEqual( const Matrix44 &tm1,const Matrix44 &tm2 )
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (fabs(tm1[i][0] - tm2[i][0]) > FLOAT_EPSILON ||
|
||||
fabs(tm1[i][1] - tm2[i][1]) > FLOAT_EPSILON ||
|
||||
fabs(tm1[i][2] - tm2[i][2]) > FLOAT_EPSILON ||
|
||||
fabs(tm1[i][3] - tm2[i][3]) > FLOAT_EPSILON)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Math utilities.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline float PointToLineDistance2D( const Vec3 &p1,const Vec3 &p2,const Vec3 &p3 )
|
||||
{
|
||||
float dx = p2.x-p1.x;
|
||||
float dy = p2.y-p1.y;
|
||||
float u = ((p3.x-p1.x)*dx + (p3.y-p1.y)*dy) / (dx*dx + dy*dy);
|
||||
if (u < 0)
|
||||
return (float)sqrt( (p3.x-p1.x)*(p3.x-p1.x) + (p3.y-p1.y)*(p3.y-p1.y) );
|
||||
else if (u > 1)
|
||||
return (float)sqrt( (p3.x-p2.x)*(p3.x-p2.x) + (p3.y-p2.y)*(p3.y-p2.y) );
|
||||
else
|
||||
{
|
||||
float x = p1.x + u*dx;
|
||||
float y = p1.y + u*dy;
|
||||
return (float)sqrt( (p3.x-x)*(p3.x-x) + (p3.y-y)*(p3.y-y) );
|
||||
}
|
||||
}
|
||||
|
||||
inline float PointToLineDistance( const Vec3 &p1,const Vec3 &p2,const Vec3 &p3 )
|
||||
{
|
||||
Vec3 d = p2 - p1;
|
||||
float u = d.Dot(p3-p1) / GetLengthSquared(d);
|
||||
if (u < 0)
|
||||
return (p3 - p1).Length();
|
||||
else if (u > 1)
|
||||
return (p3 - p2).Length();
|
||||
else
|
||||
{
|
||||
Vec3 p = p1 + u*d;
|
||||
return (p3 - p).Length();
|
||||
}
|
||||
}
|
||||
|
||||
/** Calculate distance between point and line.
|
||||
@param p1 Source line point.
|
||||
@param p2 Target line point.
|
||||
@param p3 Point to find intersecion with.
|
||||
@param intersectPoint Intersection point on the line.
|
||||
@return Distance between point and line.
|
||||
*/
|
||||
inline float PointToLineDistance( const Vec3 &p1,const Vec3 &p2,const Vec3 &p3,Vec3 &intersectPoint )
|
||||
{
|
||||
Vec3 d = p2 - p1;
|
||||
float u = d.Dot(p3-p1) / GetLengthSquared(d);
|
||||
if (u < 0)
|
||||
{
|
||||
intersectPoint = p1;
|
||||
return (p3 - p1).Length();
|
||||
}
|
||||
else if (u > 1)
|
||||
{
|
||||
intersectPoint = p2;
|
||||
return (p3 - p2).Length();
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 p = p1 + u*d;
|
||||
intersectPoint = p;
|
||||
return (p3 - p).Length();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calculate the line segment PaPb that is the shortest route between
|
||||
two lines P1P2 and P3P4. Calculate also the values of mua and mub where
|
||||
Pa = P1 + mua (P2 - P1)
|
||||
Pb = P3 + mub (P4 - P3)
|
||||
|
||||
@param p1 Source point of first line.
|
||||
@param p2 Target point of first line.
|
||||
@param p3 Source point of second line.
|
||||
@param p4 Target point of second line.
|
||||
@return FALSE if no solution exists.
|
||||
*/
|
||||
inline bool LineLineIntersect( const Vec3 &p1,const Vec3 &p2,const Vec3 &p3,const Vec3 &p4,
|
||||
Vec3 &pa,Vec3 &pb,float &mua,float &mub )
|
||||
{
|
||||
Vec3 p13,p43,p21;
|
||||
float d1343,d4321,d1321,d4343,d2121;
|
||||
float numer,denom;
|
||||
|
||||
p13.x = p1.x - p3.x;
|
||||
p13.y = p1.y - p3.y;
|
||||
p13.z = p1.z - p3.z;
|
||||
p43.x = p4.x - p3.x;
|
||||
p43.y = p4.y - p3.y;
|
||||
p43.z = p4.z - p3.z;
|
||||
if (fabs(p43.x) < LINE_EPS && fabs(p43.y) < LINE_EPS && fabs(p43.z) < LINE_EPS)
|
||||
return false;
|
||||
p21.x = p2.x - p1.x;
|
||||
p21.y = p2.y - p1.y;
|
||||
p21.z = p2.z - p1.z;
|
||||
if (fabs(p21.x) < LINE_EPS && fabs(p21.y) < LINE_EPS && fabs(p21.z) < LINE_EPS)
|
||||
return false;
|
||||
|
||||
d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z;
|
||||
d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z;
|
||||
d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z;
|
||||
d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z;
|
||||
d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z;
|
||||
|
||||
denom = d2121 * d4343 - d4321 * d4321;
|
||||
if (fabs(denom) < LINE_EPS)
|
||||
return(FALSE);
|
||||
numer = d1343 * d4321 - d1321 * d4343;
|
||||
|
||||
mua = numer / denom;
|
||||
mub = (d1343 + d4321 * (mua)) / d4343;
|
||||
|
||||
pa.x = p1.x + mua * p21.x;
|
||||
pa.y = p1.y + mua * p21.y;
|
||||
pa.z = p1.z + mua * p21.z;
|
||||
pb.x = p3.x + mub * p43.x;
|
||||
pb.y = p3.y + mub * p43.y;
|
||||
pb.z = p3.z + mub * p43.z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculates shortest distance between ray and a arbitary line segment.
|
||||
@param raySrc Source point of ray.
|
||||
@param rayTrg Target point of ray.
|
||||
@param p1 First point of line segment.
|
||||
@param p2 Second point of line segment.
|
||||
@param intersectPoint This parameter returns nearest point on line segment to ray.
|
||||
@return distance fro ray to line segment.
|
||||
*/
|
||||
inline float RayToLineDistance( const Vec3 &raySrc,const Vec3 &rayTrg,const Vec3 &p1,const Vec3 &p2,Vec3 &nearestPoint )
|
||||
{
|
||||
Vec3 intPnt;
|
||||
Vec3 rayLineP1 = raySrc;
|
||||
Vec3 rayLineP2 = rayTrg;
|
||||
Vec3 pa,pb;
|
||||
float ua,ub;
|
||||
|
||||
if (!LineLineIntersect( p1,p2, rayLineP1,rayLineP2, pa,pb,ua,ub ))
|
||||
return FLT_MAX;
|
||||
|
||||
float d = 0;
|
||||
if (ua < 0)
|
||||
d = PointToLineDistance( rayLineP1,rayLineP2,p1,intPnt );
|
||||
else if (ua > 1)
|
||||
d = PointToLineDistance( rayLineP1,rayLineP2,p2,intPnt );
|
||||
else
|
||||
{
|
||||
intPnt = rayLineP1 + ub*(rayLineP2-rayLineP1);
|
||||
d = (pb-pa).Length();
|
||||
}
|
||||
nearestPoint = intPnt;
|
||||
return d;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline Matrix44 MatrixFromVector( const Vec3d &dir )
|
||||
{
|
||||
Matrix44 M;
|
||||
// LookAt transform.
|
||||
Vec3d xAxis,yAxis,zAxis;
|
||||
Vec3d upVector;
|
||||
|
||||
yAxis = GetNormalized(dir);
|
||||
|
||||
if (yAxis.x == 0.0 && yAxis.y == 0)
|
||||
upVector( -yAxis.z,0,0 );
|
||||
else
|
||||
upVector( 0,0,1.0f );
|
||||
|
||||
xAxis = GetNormalized((upVector.Cross(yAxis)));
|
||||
zAxis = GetNormalized( -(xAxis.Cross(yAxis)) );
|
||||
|
||||
/*
|
||||
// D3D kind of matrix.
|
||||
M[0][0] = xAxis.x;
|
||||
M[0][1] = yAxis.x;
|
||||
M[0][2] = zAxis.x;
|
||||
M[0][3] = 0;
|
||||
|
||||
M[1][0] = xAxis.y;
|
||||
M[1][1] = yAxis.y;
|
||||
M[1][2] = zAxis.y;
|
||||
M[1][3] = 0;
|
||||
|
||||
M[2][0] = xAxis.z;
|
||||
M[2][1] = yAxis.z;
|
||||
M[2][2] = zAxis.z;
|
||||
M[2][3] = 0;
|
||||
|
||||
M[3][0] = 0;
|
||||
M[3][1] = 0;
|
||||
M[3][2] = 0;
|
||||
M[3][3] = 1;
|
||||
*/
|
||||
|
||||
// OpenGL kind of matrix.
|
||||
M[0][0] = xAxis.x;
|
||||
M[1][0] = yAxis.x;
|
||||
M[2][0] = zAxis.x;
|
||||
M[3][0] = 0;
|
||||
|
||||
M[0][1] = xAxis.y;
|
||||
M[1][1] = yAxis.y;
|
||||
M[2][1] = zAxis.y;
|
||||
M[3][1] = 0;
|
||||
|
||||
M[0][2] = xAxis.z;
|
||||
M[1][2] = yAxis.z;
|
||||
M[2][2] = zAxis.z;
|
||||
M[3][2] = 0;
|
||||
|
||||
M[0][3] = 0;
|
||||
M[1][3] = 0;
|
||||
M[2][3] = 0;
|
||||
M[3][3] = 1;
|
||||
|
||||
return M;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline Matrix44 MatrixFromVector( const Vec3d &dir,const Vec3d &up,float rollAngle=0 )
|
||||
{
|
||||
Matrix44 M;
|
||||
// LookAt transform.
|
||||
Vec3d xAxis,yAxis,zAxis;
|
||||
Vec3d upVector = up;
|
||||
|
||||
yAxis = GetNormalized(-dir);
|
||||
|
||||
//if (zAxis.x == 0.0 && zAxis.z == 0) up.Set( -zAxis.y,0,0 ); else up.Set( 0,1.0f,0 );
|
||||
|
||||
xAxis = GetNormalized((upVector.Cross(yAxis)));
|
||||
zAxis = GetNormalized(xAxis.Cross(yAxis));
|
||||
|
||||
// OpenGL kind of matrix.
|
||||
M[0][0] = xAxis.x;
|
||||
M[1][0] = yAxis.x;
|
||||
M[2][0] = zAxis.x;
|
||||
M[3][0] = 0;
|
||||
|
||||
M[0][1] = xAxis.y;
|
||||
M[1][1] = yAxis.y;
|
||||
M[2][1] = zAxis.y;
|
||||
M[3][1] = 0;
|
||||
|
||||
M[0][2] = xAxis.z;
|
||||
M[1][2] = yAxis.z;
|
||||
M[2][2] = zAxis.z;
|
||||
M[3][2] = 0;
|
||||
|
||||
M[0][3] = 0;
|
||||
M[1][3] = 0;
|
||||
M[2][3] = 0;
|
||||
M[3][3] = 1;
|
||||
|
||||
if (rollAngle != 0)
|
||||
{
|
||||
Matrix44 RollMtx;
|
||||
RollMtx.SetIdentity();
|
||||
|
||||
float s = sinf(rollAngle);
|
||||
float c = cosf(rollAngle);
|
||||
|
||||
RollMtx[0][0] = c; RollMtx[2][0] = -s;;
|
||||
RollMtx[0][2] = s; RollMtx[2][2] = c;
|
||||
|
||||
// Matrix multiply.
|
||||
M = RollMtx * M;
|
||||
}
|
||||
|
||||
return M;
|
||||
}
|
||||
|
||||
#endif // __math_h__
|
||||
169
Editor/Util/MemoryBlock.cpp
Normal file
169
Editor/Util/MemoryBlock.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: memoryblock.cpp
|
||||
// Version: v1.00
|
||||
// Created: 10/10/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "MemoryBlock.h"
|
||||
|
||||
#include "..\zlib\zlib.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMemoryBlock::CMemoryBlock()
|
||||
{
|
||||
m_buffer = 0;
|
||||
m_size = 0;
|
||||
m_uncompressedSize = 0;
|
||||
m_owns = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMemoryBlock::CMemoryBlock( const CMemoryBlock &mem )
|
||||
{
|
||||
// Invoke operator=.
|
||||
*this = mem;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMemoryBlock::~CMemoryBlock()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMemoryBlock& CMemoryBlock::operator=( const CMemoryBlock &mem )
|
||||
{
|
||||
if (mem.GetSize() > 0)
|
||||
{
|
||||
// Do not reallocate.
|
||||
if (mem.GetSize() > GetSize())
|
||||
{
|
||||
if (!Allocate(mem.GetSize()))
|
||||
return *this;
|
||||
}
|
||||
Copy( mem.GetBuffer(),mem.GetSize() );
|
||||
}
|
||||
m_uncompressedSize = mem.m_uncompressedSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CMemoryBlock::Allocate( int size,int uncompressedSize )
|
||||
{
|
||||
assert( size > 0 );
|
||||
if (m_buffer)
|
||||
{
|
||||
m_buffer = realloc(m_buffer,size);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer = malloc(size);
|
||||
}
|
||||
if (!m_buffer)
|
||||
{
|
||||
Warning( "Warning CMemoryBlock::Allocate failed to allocate %dMb of Memory",size/(1024*1024) );
|
||||
}
|
||||
|
||||
m_owns = true;
|
||||
m_size = size;
|
||||
m_uncompressedSize = uncompressedSize;
|
||||
// Check if allocation failed.
|
||||
if (m_buffer == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Free()
|
||||
{
|
||||
if (m_buffer && m_owns)
|
||||
free( m_buffer );
|
||||
m_buffer = 0;
|
||||
m_owns = false;
|
||||
m_size = 0;
|
||||
m_uncompressedSize = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Copy( void *src,int size )
|
||||
{
|
||||
assert( size <= m_size );
|
||||
memcpy( m_buffer,src,size );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Attach( void *buffer,int size,int uncompressedSize )
|
||||
{
|
||||
Free();
|
||||
m_owns = false;
|
||||
m_buffer = buffer;
|
||||
m_size = size;
|
||||
m_uncompressedSize = uncompressedSize;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Detach()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Compress( CMemoryBlock &toBlock ) const
|
||||
{
|
||||
// Cannot compress to itself.
|
||||
assert( this != &toBlock );
|
||||
unsigned long destSize = m_size*2+128;
|
||||
CMemoryBlock temp;
|
||||
temp.Allocate( destSize );
|
||||
|
||||
compress( (unsigned char*)temp.GetBuffer(),&destSize,(unsigned char*)GetBuffer(),m_size );
|
||||
|
||||
toBlock.Allocate( destSize );
|
||||
toBlock.Copy( temp.GetBuffer(),destSize );
|
||||
toBlock.m_uncompressedSize = GetSize();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Uncompress( CMemoryBlock &toBlock ) const
|
||||
{
|
||||
assert( this != &toBlock );
|
||||
toBlock.Allocate( m_uncompressedSize );
|
||||
toBlock.m_uncompressedSize = 0;
|
||||
unsigned long destSize = m_uncompressedSize;
|
||||
int result = uncompress( (unsigned char*)toBlock.GetBuffer(),&destSize,(unsigned char*)GetBuffer(),GetSize() );
|
||||
assert( result == Z_OK );
|
||||
assert( destSize == m_uncompressedSize );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMemoryBlock::Serialize( CArchive &ar )
|
||||
{
|
||||
if (ar.IsLoading())
|
||||
{
|
||||
int size;
|
||||
// Loading.
|
||||
ar >> size;
|
||||
if (size != m_size)
|
||||
Allocate( size );
|
||||
m_size = size;
|
||||
ar >> m_uncompressedSize;
|
||||
ar.Read( m_buffer,m_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
ar << m_size;
|
||||
ar << m_uncompressedSize;
|
||||
ar.Write( m_buffer,m_size );
|
||||
}
|
||||
}
|
||||
85
Editor/Util/MemoryBlock.h
Normal file
85
Editor/Util/MemoryBlock.h
Normal file
@@ -0,0 +1,85 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: memoryblock.h
|
||||
// Version: v1.00
|
||||
// Created: 10/10/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __memoryblock_h__
|
||||
#define __memoryblock_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "RefCountBase.h"
|
||||
|
||||
/** Encapsulate block of memory.
|
||||
*/
|
||||
class CMemoryBlock : public CRefCountBase
|
||||
{
|
||||
public:
|
||||
CMemoryBlock();
|
||||
CMemoryBlock( const CMemoryBlock &mem );
|
||||
~CMemoryBlock();
|
||||
|
||||
CMemoryBlock& operator=( const CMemoryBlock &mem );
|
||||
|
||||
//! Allocate or reallocare memory for this block.
|
||||
//! @param size Ammount of memory in bytes to allocate.
|
||||
//! @return true if allocation successed.
|
||||
bool Allocate( int size,int uncompressedSize=0 );
|
||||
|
||||
//! Frees memory allocated in this block.
|
||||
void Free();
|
||||
|
||||
//! Attach memory buffer to this block.
|
||||
void Attach( void *buffer,int size,int uncompressedSize=0 );
|
||||
//! Detach memory buffer that was previously attached.
|
||||
void Detach();
|
||||
|
||||
//! Returns ammount of allocated memory in this block.
|
||||
int GetSize() const { return m_size; }
|
||||
|
||||
//! Returns ammount of allocated memory in this block.
|
||||
int GetUncompressedSize() const { return m_uncompressedSize; }
|
||||
|
||||
void* GetBuffer() const { return m_buffer; };
|
||||
|
||||
//! Copy memory range to memory block.
|
||||
void Copy( void *src,int size );
|
||||
|
||||
//! Compress this memory block to specified memory block.
|
||||
//! @param toBlock target memory block where compressed result will be stored.
|
||||
void Compress( CMemoryBlock &toBlock ) const;
|
||||
|
||||
//! Uncompress this memory block to specified memory block.
|
||||
//! @param toBlock target memory block where compressed result will be stored.
|
||||
void Uncompress( CMemoryBlock &toBlock ) const;
|
||||
|
||||
//! Serialize memory block to archive.
|
||||
void Serialize( CArchive &ar );
|
||||
|
||||
//! Is MemoryBlock is empty.
|
||||
bool IsEmpty() const { return m_buffer == 0; }
|
||||
|
||||
private:
|
||||
void* m_buffer;
|
||||
int m_size;
|
||||
//! If not 0, memory block is compressed.
|
||||
int m_uncompressedSize;
|
||||
//! True if memory block owns its memory.
|
||||
bool m_owns;
|
||||
};
|
||||
|
||||
SMARTPTR_TYPEDEF( CMemoryBlock );
|
||||
|
||||
#endif // __memoryblock_h__
|
||||
317
Editor/Util/NamedData.cpp
Normal file
317
Editor/Util/NamedData.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: NamedData.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/10/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Collection of Named data blocks.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "NamedData.h"
|
||||
#include "..\zlib\zlib.h"
|
||||
#include "PakFile.h"
|
||||
|
||||
IMPLEMENT_SERIAL(CNamedData, CObject, 1)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CNamedData::CNamedData()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CNamedData::~CNamedData()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNamedData::AddDataBlock( const CString &blockName,void* pData,int nSize,bool bCompress )
|
||||
{
|
||||
assert( pData );
|
||||
assert( nSize > 0 );
|
||||
|
||||
bCompress = false;
|
||||
|
||||
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
|
||||
if (pBlock)
|
||||
{
|
||||
delete pBlock;
|
||||
}
|
||||
|
||||
pBlock = new DataBlock;
|
||||
|
||||
if (bCompress)
|
||||
{
|
||||
pBlock->bCompressed = true;
|
||||
CMemoryBlock temp;
|
||||
temp.Attach( pData,nSize );
|
||||
temp.Compress( pBlock->compressedData );
|
||||
}
|
||||
else
|
||||
{
|
||||
pBlock->bCompressed = false;
|
||||
pBlock->data.Allocate( nSize );
|
||||
pBlock->data.Copy( pData,nSize );
|
||||
}
|
||||
m_blocks[blockName] = pBlock;
|
||||
}
|
||||
|
||||
void CNamedData::AddDataBlock( const CString &blockName,CMemoryBlock &mem )
|
||||
{
|
||||
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
|
||||
if (pBlock)
|
||||
{
|
||||
delete pBlock;
|
||||
}
|
||||
pBlock = new DataBlock;
|
||||
if (mem.GetUncompressedSize() != 0)
|
||||
{
|
||||
// This is compressed block.
|
||||
pBlock->bCompressed = true;
|
||||
pBlock->compressedData = mem;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBlock->bCompressed = false;
|
||||
pBlock->data = mem;
|
||||
}
|
||||
m_blocks[blockName] = pBlock;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNamedData::Clear()
|
||||
{
|
||||
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CNamedData::GetDataBlock( const CString &blockName,void* &pData, int &nSize )
|
||||
{
|
||||
pData = 0;
|
||||
nSize = 0;
|
||||
|
||||
bool bUncompressed = false;
|
||||
CMemoryBlock *mem = GetDataBlock( blockName,bUncompressed );
|
||||
if (mem)
|
||||
{
|
||||
pData = mem->GetBuffer();
|
||||
nSize = mem->GetSize();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CMemoryBlock* CNamedData::GetDataBlock( const CString &blockName,bool &bCompressed )
|
||||
{
|
||||
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
|
||||
if (!pBlock)
|
||||
return 0;
|
||||
|
||||
if (bCompressed)
|
||||
{
|
||||
// Return compressed data.
|
||||
if (!pBlock->compressedData.IsEmpty())
|
||||
return &pBlock->compressedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return normal data.
|
||||
if (!pBlock->data.IsEmpty())
|
||||
{
|
||||
return &pBlock->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Uncompress compressed block.
|
||||
if (!pBlock->compressedData.IsEmpty())
|
||||
{
|
||||
pBlock->compressedData.Uncompress( pBlock->data );
|
||||
return &pBlock->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNamedData::Serialize(CArchive& ar)
|
||||
{
|
||||
CObject::Serialize(ar);
|
||||
|
||||
if (ar.IsStoring())
|
||||
{
|
||||
int iSize = m_blocks.size();
|
||||
ar << iSize;
|
||||
|
||||
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
|
||||
{
|
||||
CString key = it->first;
|
||||
DataBlock* pBlock = it->second;
|
||||
|
||||
unsigned int nOriginalSize;
|
||||
unsigned int nSizeFlags;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (pBlock->bCompressed)
|
||||
{
|
||||
nOriginalSize = pBlock->compressedData.GetUncompressedSize();
|
||||
// Compressed data.
|
||||
unsigned long destSize = pBlock->compressedData.GetSize();
|
||||
void *dest = pBlock->compressedData.GetBuffer();
|
||||
nSizeFlags = destSize | (1<<31);
|
||||
|
||||
ar << key;
|
||||
ar << nSizeFlags; // Current size of data + 1 bit for compressed flag.
|
||||
ar << nOriginalSize; // Size of uncompressed data.
|
||||
ar << flags; // Some additional flags.
|
||||
ar.Write( dest,destSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
nOriginalSize = pBlock->data.GetSize();
|
||||
void *dest = pBlock->data.GetBuffer();
|
||||
|
||||
nSizeFlags = nOriginalSize;
|
||||
ar << key;
|
||||
ar << nSizeFlags;
|
||||
ar << nOriginalSize; // Size of uncompressed data.
|
||||
ar << flags; // Some additional flags.
|
||||
ar.Write( dest,nOriginalSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Clear();
|
||||
|
||||
int iSize;
|
||||
ar >> iSize;
|
||||
|
||||
for(int i = 0; i < iSize; i++)
|
||||
{
|
||||
CString key;
|
||||
unsigned int nSizeFlags = 0;
|
||||
unsigned int nSize = 0;
|
||||
unsigned int nOriginalSize = 0;
|
||||
unsigned int flags = 0;
|
||||
bool bCompressed = false;
|
||||
|
||||
DataBlock *pBlock = new DataBlock;
|
||||
|
||||
ar >> key;
|
||||
ar >> nSizeFlags;
|
||||
ar >> nOriginalSize;
|
||||
ar >> flags;
|
||||
|
||||
nSize = nSizeFlags & (~(1<<31));
|
||||
bCompressed = (nSizeFlags & (1<<31)) != 0;
|
||||
|
||||
if (bCompressed)
|
||||
{
|
||||
pBlock->compressedData.Allocate( nSize,nOriginalSize );
|
||||
void *pSrcData = pBlock->compressedData.GetBuffer();
|
||||
// Read compressed data.
|
||||
ar.Read( pSrcData,nSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
pBlock->data.Allocate( nSize );
|
||||
void *pSrcData = pBlock->data.GetBuffer();
|
||||
|
||||
// Read uncompressed data.
|
||||
ar.Read( pSrcData,nSize );
|
||||
}
|
||||
m_blocks[key] = pBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNamedData::Save( CPakFile &pakFile )
|
||||
{
|
||||
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
|
||||
{
|
||||
CString key = it->first;
|
||||
DataBlock* pBlock = it->second;
|
||||
if (!pBlock->bCompressed)
|
||||
{
|
||||
CString filename = key + ".editor_data";
|
||||
pakFile.UpdateFile( filename,pBlock->data );
|
||||
}
|
||||
else
|
||||
{
|
||||
int nOriginalSize = pBlock->compressedData.GetUncompressedSize();
|
||||
CMemFile memFile;
|
||||
// Write uncompressed data size.
|
||||
memFile.Write( &nOriginalSize,sizeof(nOriginalSize) );
|
||||
// Write compressed data.
|
||||
memFile.Write( pBlock->compressedData.GetBuffer(),pBlock->compressedData.GetSize() );
|
||||
pakFile.UpdateFile( key+".editor_datac",memFile,false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNamedData::Load( const CString &levelPath,CPakFile &pakFile )
|
||||
{
|
||||
int i;
|
||||
CFileUtil::FileArray files;
|
||||
CFileUtil::ScanDirectory( levelPath,"*.editor_data",files,false );
|
||||
for (i = 0; i < files.size(); i++)
|
||||
{
|
||||
CString filename = files[i].filename;
|
||||
CCryFile cfile;
|
||||
if (cfile.Open( Path::Make(levelPath,filename),"rb"))
|
||||
{
|
||||
int fileSize = cfile.GetLength();
|
||||
if (fileSize > 0)
|
||||
{
|
||||
CString key = Path::GetFileName(filename);
|
||||
// Read data block.
|
||||
DataBlock *pBlock = new DataBlock;
|
||||
pBlock->data.Allocate( fileSize );
|
||||
cfile.Read( pBlock->data.GetBuffer(),fileSize );
|
||||
m_blocks[key] = pBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
files.clear();
|
||||
// Scan compressed data.
|
||||
CFileUtil::ScanDirectory( levelPath,"*.editor_datac",files,false );
|
||||
for (i = 0; i < files.size(); i++)
|
||||
{
|
||||
CString filename = files[i].filename;
|
||||
CCryFile cfile;
|
||||
if (cfile.Open( Path::Make(levelPath,filename),"rb"))
|
||||
{
|
||||
int fileSize = cfile.GetLength();
|
||||
if (fileSize > 0)
|
||||
{
|
||||
// Read uncompressed data size.
|
||||
int nOriginalSize = 0;
|
||||
cfile.Read( &nOriginalSize,sizeof(nOriginalSize) );
|
||||
// Read uncompressed data.
|
||||
int nDataSize = fileSize - sizeof(nOriginalSize);
|
||||
|
||||
CString key = Path::GetFileName(filename);
|
||||
// Read data block.
|
||||
DataBlock *pBlock = new DataBlock;
|
||||
pBlock->compressedData.Allocate( nDataSize,nOriginalSize );
|
||||
cfile.Read( pBlock->compressedData.GetBuffer(),nDataSize );
|
||||
m_blocks[key] = pBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Editor/Util/NamedData.h
Normal file
65
Editor/Util/NamedData.h
Normal file
@@ -0,0 +1,65 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: NamedData.h
|
||||
// Version: v1.00
|
||||
// Created: 30/10/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Collection of Named data blocks.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __NamedData_h__
|
||||
#define __NamedData_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "MemoryBlock.h"
|
||||
|
||||
class CPakFile;
|
||||
|
||||
class CNamedData : public CObject
|
||||
{
|
||||
DECLARE_SERIAL( CNamedData )
|
||||
public:
|
||||
CNamedData();
|
||||
virtual ~CNamedData();
|
||||
void AddDataBlock( const CString &blockName,void* pData,int nSize,bool bCompress=true );
|
||||
void AddDataBlock( const CString &blockName,CMemoryBlock &block );
|
||||
//! Returns uncompressed block data.
|
||||
bool GetDataBlock( const CString &blockName,void* &pData, int &nSize );
|
||||
//! Returns raw data block in original form (Compressed or Uncompressed).
|
||||
CMemoryBlock* GetDataBlock( const CString &blockName,bool &bCompressed );
|
||||
|
||||
void Clear();
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CCurveObject)
|
||||
public:
|
||||
virtual void Serialize(CArchive& ar);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
//! Save named data to pak file.
|
||||
void Save( CPakFile &pakFile );
|
||||
//! Load named data from pak file.
|
||||
void Load( const CString &levelPath,CPakFile &pakFile );
|
||||
|
||||
private:
|
||||
struct DataBlock
|
||||
{
|
||||
CString blockName;
|
||||
CMemoryBlock data;
|
||||
CMemoryBlock compressedData;
|
||||
//! This block is compressed.
|
||||
bool bCompressed;
|
||||
};
|
||||
typedef std::map<CString,DataBlock*,stl::less_stricmp<CString> > Blocks;
|
||||
Blocks m_blocks;
|
||||
};
|
||||
|
||||
#endif // __NamedData_h__
|
||||
116
Editor/Util/PakFile.cpp
Normal file
116
Editor/Util/PakFile.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: pakfile.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/6/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "PakFile.h"
|
||||
#include <ICryPak.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPakFile::CPakFile()
|
||||
{
|
||||
m_pArchive = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPakFile::~CPakFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPakFile::CPakFile( const char *filename )
|
||||
{
|
||||
m_pArchive = NULL;
|
||||
Open( filename );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPakFile::Close()
|
||||
{
|
||||
m_pArchive = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::Open( const char *filename,bool bAbsolutePath )
|
||||
{
|
||||
if (m_pArchive)
|
||||
Close();
|
||||
if (bAbsolutePath)
|
||||
m_pArchive = GetIEditor()->GetSystem()->GetIPak()->OpenArchive( filename,ICryArchive::FLAGS_ABSOLUTE_PATHS );
|
||||
else
|
||||
m_pArchive = GetIEditor()->GetSystem()->GetIPak()->OpenArchive( filename );
|
||||
if (m_pArchive)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::OpenForRead( const char *filename )
|
||||
{
|
||||
if (m_pArchive)
|
||||
Close();
|
||||
//m_pArchive = GetIEditor()->GetSystem()->GetIPak()->OpenArchive( filename,ICryArchive::FLAGS_OPTIMIZED_READ_ONLY|ICryArchive::FLAGS_RELATIVE_PATHS_ONLY|ICryArchive::FLAGS_IGNORE_MODS );
|
||||
m_pArchive = GetIEditor()->GetSystem()->GetIPak()->OpenArchive( filename,ICryArchive::FLAGS_OPTIMIZED_READ_ONLY|ICryArchive::FLAGS_ABSOLUTE_PATHS|ICryArchive::FLAGS_IGNORE_MODS );
|
||||
if (m_pArchive)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::UpdateFile( const char *filename,CMemFile &file,bool bCompress )
|
||||
{
|
||||
if (m_pArchive)
|
||||
{
|
||||
int nSize = file.GetLength();
|
||||
UpdateFile( filename,file.Detach(),nSize,bCompress );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::UpdateFile( const char *filename,CMemoryBlock &mem,bool bCompress )
|
||||
{
|
||||
if (m_pArchive)
|
||||
{
|
||||
UpdateFile( filename,mem.GetBuffer(),mem.GetSize(),bCompress );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::UpdateFile( const char *filename,void *pBuffer,int nSize,bool bCompress )
|
||||
{
|
||||
if (m_pArchive)
|
||||
{
|
||||
if (bCompress)
|
||||
m_pArchive->UpdateFile( filename,pBuffer,nSize, ICryArchive::METHOD_DEFLATE, ICryArchive::LEVEL_BETTER);
|
||||
else
|
||||
m_pArchive->UpdateFile( filename,pBuffer,nSize );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPakFile::RemoveFile( const char *filename )
|
||||
{
|
||||
if (m_pArchive)
|
||||
{
|
||||
return m_pArchive->RemoveFile( filename );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
56
Editor/Util/PakFile.h
Normal file
56
Editor/Util/PakFile.h
Normal file
@@ -0,0 +1,56 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: pakfile.h
|
||||
// Version: v1.00
|
||||
// Created: 30/6/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __pakfile_h__
|
||||
#define __pakfile_h__
|
||||
#pragma once
|
||||
|
||||
// forward references.
|
||||
struct ICryArchive;
|
||||
TYPEDEF_AUTOPTR(ICryArchive);
|
||||
|
||||
|
||||
/*! CPakFile Wraps game implementation of ICryArchive.
|
||||
Used for storing multiple files into zip archive file.
|
||||
*/
|
||||
class CPakFile
|
||||
{
|
||||
public:
|
||||
CPakFile();
|
||||
~CPakFile();
|
||||
//! Opens archive for writing.
|
||||
explicit CPakFile( const char *filename );
|
||||
//! Opens archive for writing.
|
||||
bool Open( const char *filename,bool bAbsolutePath=true );
|
||||
//! Opens archive for reading only.
|
||||
bool OpenForRead( const char *filename );
|
||||
|
||||
void Close();
|
||||
//! Adds or update file in archive.
|
||||
bool UpdateFile( const char *filename,CMemFile &file,bool bCompress=true );
|
||||
//! Adds or update file in archive.
|
||||
bool UpdateFile( const char *filename,CMemoryBlock &mem,bool bCompress=true );
|
||||
//! Adds or update file in archive.
|
||||
bool UpdateFile( const char *filename,void *pBuffer,int nSize,bool bCompress=true );
|
||||
//! Remove file from archive.
|
||||
bool RemoveFile( const char *filename );
|
||||
|
||||
//! Return archive of this pak file wrapper.
|
||||
ICryArchive* GetArchive() { return m_pArchive; };
|
||||
private:
|
||||
ICryArchive_AutoPtr m_pArchive;
|
||||
};
|
||||
|
||||
#endif // __pakfile_h__
|
||||
144
Editor/Util/PathUtil.h
Normal file
144
Editor/Util/PathUtil.h
Normal file
@@ -0,0 +1,144 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: pathutil.h
|
||||
// Version: v1.00
|
||||
// Created: 5/11/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Utility functions to simplify working with paths.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __pathutil_h__
|
||||
#define __pathutil_h__
|
||||
#pragma once
|
||||
|
||||
namespace Path
|
||||
{
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param file [OUT] Extracted file (with extension).
|
||||
inline void Split( const CString &filepath,CString &path,CString &file )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( filepath,drive,dir,fname,ext );
|
||||
_makepath( path_buffer,drive,dir,0,0 );
|
||||
path = path_buffer;
|
||||
_makepath( path_buffer,0,0,fname,ext );
|
||||
file = path_buffer;
|
||||
}
|
||||
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param filename [OUT] Extracted file (without extension).
|
||||
//! @param ext [OUT] Extracted files extension.
|
||||
inline void Split( const CString &filepath,CString &path,CString &filename,CString &fext )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( filepath,drive,dir,fname,ext );
|
||||
_makepath( path_buffer,drive,dir,0,0 );
|
||||
path = path_buffer;
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
|
||||
//! Extract extension from full specified file path.
|
||||
inline CString GetExt( const CString &filepath )
|
||||
{
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( filepath,0,0,0,ext );
|
||||
if (ext[0] == '.')
|
||||
return ext+1;
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
//! Extract path from full specified file path.
|
||||
inline CString GetPath( const CString &filepath )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
_splitpath( filepath,drive,dir,0,0 );
|
||||
_makepath( path_buffer,drive,dir,0,0 );
|
||||
return path_buffer;
|
||||
}
|
||||
|
||||
//! Extract file name with extension from full specified file path.
|
||||
inline CString GetFile( const CString &filepath )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( filepath,0,0,fname,ext );
|
||||
_makepath( path_buffer,0,0,fname,ext );
|
||||
return path_buffer;
|
||||
}
|
||||
|
||||
//! Extract file name without extension from full specified file path.
|
||||
inline CString GetFileName( const CString &filepath )
|
||||
{
|
||||
char fname[_MAX_FNAME];
|
||||
_splitpath( filepath,0,0,fname,0 );
|
||||
return fname;
|
||||
}
|
||||
|
||||
//! Removes the trailing backslash from a given path.
|
||||
inline CString RemoveBackslash( const CString &path )
|
||||
{
|
||||
if (path.IsEmpty() || path[path.GetLength()-1] != '\\')
|
||||
return path;
|
||||
return path.Mid( 0,path.GetLength()-1 );
|
||||
}
|
||||
|
||||
//! add a backslash if needed
|
||||
inline CString AddBackslash( const CString &path )
|
||||
{
|
||||
if(path.IsEmpty() || path[path.GetLength()-1] == '\\')
|
||||
return path;
|
||||
|
||||
return path + "\\";
|
||||
}
|
||||
|
||||
//! Replace extension for givven file.
|
||||
inline CString ReplaceExtension( const CString &filepath,const CString &ext )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
_splitpath( filepath,drive,dir,fname,0 );
|
||||
_makepath( path_buffer,drive,dir,fname,ext );
|
||||
return path_buffer;
|
||||
}
|
||||
|
||||
//! Makes a fully specified file path from path and file name.
|
||||
inline CString Make( const CString &path,const CString &file )
|
||||
{
|
||||
return AddBackslash(path) + file;
|
||||
}
|
||||
|
||||
//! Makes a fully specified file path from path and file name.
|
||||
inline CString Make( const CString &dir,const CString &filename,const CString &ext )
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
_makepath( path_buffer,NULL,dir,filename,ext );
|
||||
return path_buffer;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __pathutil_h__
|
||||
84
Editor/Util/RefCountBase.h
Normal file
84
Editor/Util/RefCountBase.h
Normal file
@@ -0,0 +1,84 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: refcountbase.h
|
||||
// Version: v1.00
|
||||
// Created: 21/2/2002 by Timur.
|
||||
// Compilers: Visual C++.NET
|
||||
// Description: Reference counted base object.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __refcountbase_h__
|
||||
#define __refcountbase_h__
|
||||
#pragma once
|
||||
|
||||
//! Derive from this class to get reference counting for your class.
|
||||
class CRYEDIT_API CRefCountBase : public CObject
|
||||
{
|
||||
public:
|
||||
CRefCountBase() { m_nRefCount = 0; };
|
||||
|
||||
//! Add new refrence to this object.
|
||||
int AddRef()
|
||||
{
|
||||
m_nRefCount++;
|
||||
return m_nRefCount;
|
||||
};
|
||||
|
||||
//! Release refrence to this object.
|
||||
//! when reference count reaches zero, object is deleted.
|
||||
int Release()
|
||||
{
|
||||
int refs = --m_nRefCount;
|
||||
if (m_nRefCount <= 0)
|
||||
delete this;
|
||||
return refs;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~CRefCountBase() {};
|
||||
|
||||
private:
|
||||
int m_nRefCount;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Derive from this class to get reference counting for your class.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class ParentClass>
|
||||
class CRYEDIT_API TRefCountBase : public ParentClass
|
||||
{
|
||||
public:
|
||||
TRefCountBase() { m_nRefCount = 0; };
|
||||
|
||||
//! Add new refrence to this object.
|
||||
int AddRef()
|
||||
{
|
||||
m_nRefCount++;
|
||||
return m_nRefCount;
|
||||
};
|
||||
|
||||
//! Release refrence to this object.
|
||||
//! when reference count reaches zero, object is deleted.
|
||||
int Release()
|
||||
{
|
||||
int refs = --m_nRefCount;
|
||||
if (m_nRefCount <= 0)
|
||||
delete this;
|
||||
return refs;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~TRefCountBase() {};
|
||||
|
||||
private:
|
||||
int m_nRefCount;
|
||||
};
|
||||
|
||||
|
||||
#endif // __refcountbase_h__
|
||||
227
Editor/Util/StlUtil.h
Normal file
227
Editor/Util/StlUtil.h
Normal file
@@ -0,0 +1,227 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: stlutil.h
|
||||
// Version: v1.00
|
||||
// Created: 27/9/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Utility functions to simplify usage of STL.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __stlutil_h__
|
||||
#define __stlutil_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/** Contain extensions for STL library.
|
||||
*/
|
||||
namespace stl
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Searches the given entry in the map by key, and if there is none, returns the default value
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifdef WIN64 // workaround
|
||||
template <class Map, typename mapped_type, typename key_type>
|
||||
inline mapped_type& find_in_map( Map& mapKeyToValue, const key_type &key, mapped_type &valueDefault)
|
||||
{
|
||||
Map::iterator it = mapKeyToValue.find(key);
|
||||
if (it == mapKeyToValue.end())
|
||||
return valueDefault;
|
||||
else
|
||||
{
|
||||
mapped_type &ref = it->second;
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
#else //WIN64
|
||||
template <class Map>
|
||||
inline Map::mapped_type& find_in_map( Map& mapKeyToValue, const Map::key_type &key, Map::mapped_type &valueDefault)
|
||||
{
|
||||
Map::iterator it = mapKeyToValue.find(key);
|
||||
if (it == mapKeyToValue.end())
|
||||
return valueDefault;
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
#endif //WIN64
|
||||
|
||||
#ifdef WIN64 // workaround
|
||||
template <class Map, typename mapped_type, typename key_type>
|
||||
inline const mapped_type& find_in_map(const Map& mapKeyToValue, const key_type &key, const mapped_type &valueDefault)
|
||||
{
|
||||
Map::const_iterator it = mapKeyToValue.find (key);
|
||||
if (it == mapKeyToValue.end())
|
||||
return valueDefault;
|
||||
else
|
||||
{
|
||||
const mapped_type &ref = it->second;
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
#else //WIN64
|
||||
template <class Map>
|
||||
inline const Map::mapped_type& find_in_map(const Map& mapKeyToValue, const Map::key_type &key, const Map::mapped_type &valueDefault)
|
||||
{
|
||||
Map::const_iterator it = mapKeyToValue.find (key);
|
||||
if (it == mapKeyToValue.end())
|
||||
return valueDefault;
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
#endif //WIN64
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Fills Vector with contents of Map.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Map,class Value>
|
||||
inline void map_to_vector( const Map& theMap,std::vector<Value> &array )
|
||||
{
|
||||
array.clear();
|
||||
array.reserve( theMap.size() );
|
||||
for (Map::const_iterator it = theMap.begin(); it != theMap.end(); ++it)
|
||||
{
|
||||
array.push_back( it->second );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find and erase element from container.
|
||||
// @return true if item was find and erased, false if item not found.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Container,class Value>
|
||||
inline bool find_and_erase( Container& container,const Value &value )
|
||||
{
|
||||
Container::iterator it = std::find( container.begin(),container.end(),value );
|
||||
if (it != container.end())
|
||||
{
|
||||
container.erase( it );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Push back to container unique element.
|
||||
// @return true if item added, false overwise.
|
||||
template <class Container,class Value>
|
||||
inline bool push_back_unique( Container& container,const Value &value )
|
||||
{
|
||||
if (std::find(container.begin(),container.end(),value) == container.end())
|
||||
{
|
||||
container.push_back( value );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find element in container.
|
||||
// @return true if item found.
|
||||
template <class Container,class Value>
|
||||
inline bool find( Container& container,const Value &value )
|
||||
{
|
||||
return std::find(container.begin(),container.end(),value) != container.end();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Convert arbitary class to const char*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
inline const char* constchar_cast( const Type &type )
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
//! Specialization of string to const char cast.
|
||||
template <>
|
||||
inline const char* constchar_cast( const string &type )
|
||||
{
|
||||
return type.c_str();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case sensetive less key for any type convertable to const char*.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
struct less_strcmp : public std::binary_function<Type,Type,bool>
|
||||
{
|
||||
bool operator()( const Type &left,const Type &right ) const
|
||||
{
|
||||
return strcmp(constchar_cast(left),constchar_cast(right)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case insensetive less key for any type convertable to const char*.
|
||||
template <class Type>
|
||||
struct less_stricmp : public std::binary_function<Type,Type,bool>
|
||||
{
|
||||
bool operator()( const Type &left,const Type &right ) const
|
||||
{
|
||||
return stricmp(constchar_cast(left),constchar_cast(right)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case sensetive string hash map compare structure.
|
||||
template <class Key>
|
||||
class hash_strcmp
|
||||
{
|
||||
public:
|
||||
enum { // parameters for hash table
|
||||
bucket_size = 4, // 0 < bucket_size
|
||||
min_buckets = 8 };// min_buckets = 2 ^^ N, 0 < N
|
||||
|
||||
size_t operator()( const Key& key ) const
|
||||
{
|
||||
unsigned long h = 0;
|
||||
const char *s = constchar_cast(key);
|
||||
for (; *s; ++s) h = 5*h + *(unsigned char*)s;
|
||||
return size_t(h);
|
||||
|
||||
};
|
||||
bool operator()( const Key& key1,const Key& key2 ) const
|
||||
{
|
||||
return strcmp(constchar_cast(key1),constchar_cast(key2)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case insensetive string hash map compare structure.
|
||||
template <class Key>
|
||||
class hash_stricmp
|
||||
{
|
||||
public:
|
||||
enum { // parameters for hash table
|
||||
bucket_size = 4, // 0 < bucket_size
|
||||
min_buckets = 8 };// min_buckets = 2 ^^ N, 0 < N
|
||||
|
||||
size_t operator()( const Key& key ) const
|
||||
{
|
||||
unsigned long h = 0;
|
||||
const char *s = constchar_cast(key);
|
||||
for (; *s; ++s) h = 5*h + *(unsigned char*)s;
|
||||
return size_t(h);
|
||||
|
||||
};
|
||||
bool operator()( const Key& key1,const Key& key2 ) const
|
||||
{
|
||||
return stricmp(constchar_cast(key1),constchar_cast(key2)) < 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // __stlutil_h__
|
||||
95
Editor/Util/Thread.cpp
Normal file
95
Editor/Util/Thread.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// VisualStation Header File.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: CThread.cpp
|
||||
// Version: v1.00
|
||||
// Last modified: (12/07/98)
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Implementation of threading.
|
||||
// -------------------------------------------------------------------------
|
||||
// Copyright (C), 3dion Inc.. 1996-1999:
|
||||
// Timur Davidenko (aka Adept/Esteem).
|
||||
// email: adept@iname.com
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// You are not permitted to distribute, sell or use any part of
|
||||
// this source for your software without special permision of author.
|
||||
//
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "ThreadWin32.h"
|
||||
#else
|
||||
//#include "ThreadOS.h"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CThread class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void CThread::ThreadFunc( void *param )
|
||||
{
|
||||
CThread *thread = (CThread*)param;
|
||||
thread->Run();
|
||||
|
||||
threads::end(thread->m_handle);
|
||||
delete thread;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
m_handle = 0;
|
||||
}
|
||||
|
||||
void CThread::Start() // Start thread.
|
||||
{
|
||||
m_handle = threads::begin( ThreadFunc,this );
|
||||
}
|
||||
|
||||
uint CThread::GetCurrentId() {
|
||||
return threads::getCurrentThreadId();
|
||||
}
|
||||
|
||||
/*
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Monitor class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void CMonitor::Lock()
|
||||
{
|
||||
m_mutex.Wait();
|
||||
}
|
||||
|
||||
void CMonitor::Release()
|
||||
{
|
||||
m_mutex.Release();
|
||||
}
|
||||
|
||||
CMonitor::Condition::Condition( CMonitor *mon )
|
||||
{
|
||||
m_semCount = 0;
|
||||
m_monitor = mon;
|
||||
}
|
||||
|
||||
void CMonitor::Condition::Wait()
|
||||
{
|
||||
m_semCount++; // One more thread waiting for this condition.
|
||||
m_monitor->Release(); // Release monitor lock.
|
||||
m_semaphore.Wait(); // Block until condition signaled.
|
||||
m_monitor->Lock(); // If signaled and unblocked, re-aquire monitor`s lock.
|
||||
m_semCount--; // Got monitor lock, no longer in wait state.
|
||||
}
|
||||
|
||||
void CMonitor::Condition::Signal()
|
||||
{
|
||||
// Release any thread blocked by semaphore.
|
||||
if (m_semCount > 0)
|
||||
m_semaphore.Release();
|
||||
}
|
||||
*/
|
||||
243
Editor/Util/Thread.h
Normal file
243
Editor/Util/Thread.h
Normal file
@@ -0,0 +1,243 @@
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// VisualStation Header File.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: Thread.h
|
||||
// Version: v1.00
|
||||
// Last modified: (12/07/98)
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Header file for event handler.
|
||||
// -------------------------------------------------------------------------
|
||||
// Copyright (C), 3dion Inc.. 1996-1999:
|
||||
// Timur Davidenko (aka Adept/Esteem).
|
||||
// email: adept@iname.com
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// You are not permitted to distribute, sell or use any part of
|
||||
// this source for your software without special permision of author.
|
||||
//
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
#ifndef THREAD_HEADER
|
||||
#define THREAD_HEADER
|
||||
|
||||
#include <afxmt.h>
|
||||
#include <deque>
|
||||
|
||||
enum EThreadWaitStatus
|
||||
{
|
||||
THREAD_WAIT_FAILED,
|
||||
THREAD_WAIT_ABANDONED,
|
||||
THREAD_WAIT_OBJECT_0,
|
||||
THREAD_WAIT_TIMEOUT,
|
||||
THREAD_WAIT_IO_COMPLETION
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Thread.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CRYEDIT_API CThread
|
||||
{
|
||||
public:
|
||||
CThread();
|
||||
|
||||
void Start(); // Start thread.
|
||||
|
||||
static uint GetCurrentId();
|
||||
|
||||
protected:
|
||||
virtual ~CThread() {};
|
||||
static void ThreadFunc( void *param );
|
||||
|
||||
virtual void Run() = 0; // Derived classes must ovveride this.
|
||||
|
||||
UINT_PTR m_handle;
|
||||
};
|
||||
|
||||
/*
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Monitor class.
|
||||
//
|
||||
// Monitor encapsulate shared among threads data and guaranties that only
|
||||
// one thread at time can access shared data.
|
||||
// This, combined with the fact that shared data can only be access by
|
||||
// executing a monitor`s precudres, serializes access to the shared data.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CRYEDIT_API CMonitor
|
||||
{
|
||||
public:
|
||||
friend class Condition;
|
||||
|
||||
class Condition {
|
||||
public:
|
||||
Condition( CMonitor *mon );
|
||||
void Wait();
|
||||
void Signal();
|
||||
protected:
|
||||
CSemaphore m_semaphore; // Semaphore object.
|
||||
int m_semCount; // Number of waiting threads on semaphore.
|
||||
CMonitor* m_monitor;
|
||||
};
|
||||
|
||||
CMonitor() {};
|
||||
virtual ~CMonitor() {};
|
||||
|
||||
virtual void Lock();
|
||||
virtual void Release();
|
||||
|
||||
private:
|
||||
CMutex m_mutex;
|
||||
};
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MTDeqeue class, Multithread Safe Deque container.
|
||||
//
|
||||
template <class T>
|
||||
class CRYEDIT_API MTDeque
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
cs.Lock();
|
||||
bool isempty = q.empty();
|
||||
cs.Unlock();
|
||||
return isempty;
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
cs.Lock();
|
||||
int sz = q.size();
|
||||
cs.Unlock();
|
||||
return sz;
|
||||
}
|
||||
|
||||
void resize( int sz )
|
||||
{
|
||||
cs.Lock();
|
||||
q.resize( sz );
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
void reserve( int sz )
|
||||
{
|
||||
cs.Lock();
|
||||
q.reserve( sz );
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
cs.Lock();
|
||||
q.clear();
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
T& operator[]( int pos )
|
||||
{
|
||||
cs.Lock();
|
||||
T& v = q[pos];
|
||||
cs.Unlock();
|
||||
return v;
|
||||
}
|
||||
|
||||
const T& operator[]( int pos ) const
|
||||
{
|
||||
cs.Lock();
|
||||
const T& v = q[pos];
|
||||
cs.Unlock();
|
||||
return v;
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
{
|
||||
cs.Lock();
|
||||
const T& v = q.front();
|
||||
cs.Unlock();
|
||||
return v;
|
||||
}
|
||||
|
||||
const T& back() const
|
||||
{
|
||||
cs.Lock();
|
||||
const T& v = q.back();
|
||||
cs.Unlock();
|
||||
return v;
|
||||
}
|
||||
|
||||
void push_front(const T& x)
|
||||
{
|
||||
cs.Lock();
|
||||
q.push_front( x );
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
void push_back(const T& x)
|
||||
{
|
||||
cs.Lock();
|
||||
q.push_back( x );
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
void pop_front()
|
||||
{
|
||||
cs.Lock();
|
||||
q.pop_front();
|
||||
cs.Unlock();
|
||||
}
|
||||
*/
|
||||
|
||||
// Thread Safe pop front.
|
||||
bool pop_front( T& to )
|
||||
{
|
||||
cs.Lock();
|
||||
if (q.empty())
|
||||
{
|
||||
cs.Unlock();
|
||||
return false;
|
||||
}
|
||||
to = q.front();
|
||||
q.pop_front();
|
||||
cs.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
cs.Lock();
|
||||
q.pop_back();
|
||||
cs.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<T> q;
|
||||
mutable CCriticalSection cs;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MTQueue class, Multithread Safe Queue container.
|
||||
//
|
||||
template <class T>
|
||||
class MTQueue
|
||||
{
|
||||
public:
|
||||
bool empty() const { return q.empty(); };
|
||||
int size() const { return q.size(); };
|
||||
const T& top() const { return q.back(); };
|
||||
void push(const T& x) { return q.push_back(x); };
|
||||
void pop() { return q.pop_back(); };
|
||||
|
||||
private:
|
||||
MTDeque<T> q;
|
||||
};
|
||||
|
||||
#endif
|
||||
127
Editor/Util/ThreadWin32.h
Normal file
127
Editor/Util/ThreadWin32.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// VisualStation Header File.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: Win32Thread.cpp
|
||||
// Version: v1.00
|
||||
// Last modified: (12/07/98)
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Implementation of Windows threading.
|
||||
// -------------------------------------------------------------------------
|
||||
// Copyright (C), 3dion Inc.. 1996-1999:
|
||||
// Timur Davidenko (aka Adept/Esteem).
|
||||
// email: adept@iname.com
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// You are not permitted to distribute, sell or use any part of
|
||||
// this source for your software without special permision of author.
|
||||
//
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
#include "StdAfx.h"
|
||||
//#include "thread.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
typedef UINT_PTR ThreadHandle;
|
||||
|
||||
namespace threads
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Win32 threading implementation.
|
||||
|
||||
typedef void (_cdecl *ThreadFuncType)( void* );
|
||||
|
||||
// Thread.
|
||||
ThreadHandle begin( void *f,void *param ) {
|
||||
ThreadFuncType func = (ThreadFuncType)f;
|
||||
return _beginthread( func,0,param );
|
||||
}
|
||||
|
||||
void end( ThreadHandle handle )
|
||||
{
|
||||
}
|
||||
|
||||
DWORD getCurrentThreadId() {
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
// Critical section.
|
||||
ThreadHandle createCriticalSection() {
|
||||
CRITICAL_SECTION *lpSection = new CRITICAL_SECTION;
|
||||
InitializeCriticalSection( lpSection );
|
||||
return (ThreadHandle)lpSection;
|
||||
}
|
||||
|
||||
void deleteCriticalSection( ThreadHandle handle ) {
|
||||
CRITICAL_SECTION *lpSection = (CRITICAL_SECTION*)handle;
|
||||
DeleteCriticalSection( lpSection );
|
||||
delete lpSection;
|
||||
}
|
||||
|
||||
void enterCriticalSection( ThreadHandle handle ) {
|
||||
EnterCriticalSection( (CRITICAL_SECTION*)handle );
|
||||
}
|
||||
|
||||
void leaveCriticalSection( ThreadHandle handle ) {
|
||||
LeaveCriticalSection( (CRITICAL_SECTION*)handle );
|
||||
}
|
||||
|
||||
// Shared by synchronization objects.
|
||||
bool closeHandle( ThreadHandle handle ) {
|
||||
assert( CloseHandle( (HANDLE)handle ) == TRUE );
|
||||
return true;
|
||||
}
|
||||
|
||||
EThreadWaitStatus waitObject( ThreadHandle handle,ThreadHandle milliseconds )
|
||||
{
|
||||
DWORD status = WaitForSingleObjectEx( (HANDLE)handle,milliseconds,TRUE );
|
||||
switch (status) {
|
||||
case WAIT_ABANDONED: return THREAD_WAIT_ABANDONED;
|
||||
case WAIT_OBJECT_0: return THREAD_WAIT_OBJECT_0;
|
||||
case WAIT_TIMEOUT: return THREAD_WAIT_TIMEOUT;
|
||||
case WAIT_IO_COMPLETION: return THREAD_WAIT_IO_COMPLETION;
|
||||
}
|
||||
return THREAD_WAIT_FAILED;
|
||||
}
|
||||
|
||||
// Mutex.
|
||||
ThreadHandle createMutex( bool own ) {
|
||||
return (ThreadHandle)CreateMutex( NULL,own,NULL );
|
||||
}
|
||||
|
||||
bool releaseMutex( ThreadHandle handle ) {
|
||||
if (ReleaseMutex( (HANDLE)handle ) != 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Semaphore.
|
||||
ThreadHandle createSemaphore( uint initCount,uint maxCount ) {
|
||||
return (ThreadHandle)CreateSemaphore( NULL,initCount,maxCount,NULL );
|
||||
}
|
||||
|
||||
bool releaseSemaphore( ThreadHandle handle,int releaseCount ) {
|
||||
if (ReleaseSemaphore( (HANDLE)handle,releaseCount,NULL ) != 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Event
|
||||
ThreadHandle createEvent( bool manualReset,bool initialState ) {
|
||||
return (ThreadHandle)CreateEvent( NULL,manualReset,initialState,NULL );
|
||||
}
|
||||
|
||||
bool setEvent( ThreadHandle handle ) {
|
||||
return SetEvent( (HANDLE)handle );
|
||||
}
|
||||
|
||||
bool resetEvent( ThreadHandle handle ) {
|
||||
return ResetEvent( (HANDLE)handle );
|
||||
}
|
||||
|
||||
bool pulseEvent( ThreadHandle handle ) {
|
||||
return PulseEvent( (HANDLE)handle );
|
||||
}
|
||||
|
||||
} // namespace threads.
|
||||
138
Editor/Util/Triangulate.cpp
Normal file
138
Editor/Util/Triangulate.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <StdAfx.h>
|
||||
#include "Triangulate.h"
|
||||
|
||||
static const float EPSILON=0.0000000001f;
|
||||
|
||||
float CTriangulate::Area(const Vector2dVector &contour)
|
||||
{
|
||||
|
||||
int n = contour.size();
|
||||
|
||||
float A=0.0f;
|
||||
|
||||
for(int p=n-1,q=0; q<n; p=q++)
|
||||
{
|
||||
A+= contour[p].x*contour[q].y - contour[q].x*contour[p].y;
|
||||
}
|
||||
return A*0.5f;
|
||||
}
|
||||
|
||||
/*
|
||||
InsideTriangle decides if a point P is Inside of the triangle
|
||||
defined by A, B, C.
|
||||
*/
|
||||
bool CTriangulate::InsideTriangle(float Ax, float Ay,
|
||||
float Bx, float By,
|
||||
float Cx, float Cy,
|
||||
float Px, float Py)
|
||||
|
||||
{
|
||||
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||||
float cCROSSap, bCROSScp, aCROSSbp;
|
||||
|
||||
ax = Cx - Bx; ay = Cy - By;
|
||||
bx = Ax - Cx; by = Ay - Cy;
|
||||
cx = Bx - Ax; cy = By - Ay;
|
||||
apx= Px - Ax; apy= Py - Ay;
|
||||
bpx= Px - Bx; bpy= Py - By;
|
||||
cpx= Px - Cx; cpy= Py - Cy;
|
||||
|
||||
aCROSSbp = ax*bpy - ay*bpx;
|
||||
cCROSSap = cx*apy - cy*apx;
|
||||
bCROSScp = bx*cpy - by*cpx;
|
||||
|
||||
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||||
};
|
||||
|
||||
bool CTriangulate::Snip(const Vector2dVector &contour,int u,int v,int w,int n,int *V)
|
||||
{
|
||||
int p;
|
||||
float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
|
||||
|
||||
Ax = contour[V[u]].x;
|
||||
Ay = contour[V[u]].y;
|
||||
|
||||
Bx = contour[V[v]].x;
|
||||
By = contour[V[v]].y;
|
||||
|
||||
Cx = contour[V[w]].x;
|
||||
Cy = contour[V[w]].y;
|
||||
|
||||
if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false;
|
||||
|
||||
for (p=0;p<n;p++)
|
||||
{
|
||||
if( (p == u) || (p == v) || (p == w) ) continue;
|
||||
Px = contour[V[p]].x;
|
||||
Py = contour[V[p]].y;
|
||||
if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTriangulate::Process(const Vector2dVector &contour,Vector2dVector &result)
|
||||
{
|
||||
/* allocate and initialize list of Vertices in polygon */
|
||||
|
||||
int n = contour.size();
|
||||
if ( n < 3 ) return false;
|
||||
|
||||
int *V = new int[n];
|
||||
|
||||
/* we want a counter-clockwise polygon in V */
|
||||
|
||||
if ( 0.0f < Area(contour) )
|
||||
for (int v=0; v<n; v++) V[v] = v;
|
||||
else
|
||||
for(int v=0; v<n; v++) V[v] = (n-1)-v;
|
||||
|
||||
int nv = n;
|
||||
|
||||
/* remove nv-2 Vertices, creating 1 triangle every time */
|
||||
int count = 2*nv; /* error detection */
|
||||
|
||||
for(int m=0, v=nv-1; nv>2; )
|
||||
{
|
||||
/* if we loop, it is probably a non-simple polygon */
|
||||
if (0 >= (count--))
|
||||
{
|
||||
//** CTriangulate: ERROR - probable bad polygon!
|
||||
return false;
|
||||
}
|
||||
|
||||
/* three consecutive vertices in current polygon, <u,v,w> */
|
||||
int u = v ; if (nv <= u) u = 0; /* previous */
|
||||
v = u+1; if (nv <= v) v = 0; /* new v */
|
||||
int w = v+1; if (nv <= w) w = 0; /* next */
|
||||
|
||||
if ( Snip(contour,u,v,w,nv,V) )
|
||||
{
|
||||
int a,b,c,s,t;
|
||||
|
||||
/* true names of the vertices */
|
||||
a = V[u]; b = V[v]; c = V[w];
|
||||
|
||||
/* output Triangle */
|
||||
result.push_back( contour[a] );
|
||||
result.push_back( contour[b] );
|
||||
result.push_back( contour[c] );
|
||||
|
||||
m++;
|
||||
|
||||
/* remove v from remaining polygon */
|
||||
for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
|
||||
|
||||
/* resest error detection counter */
|
||||
count = 2*nv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
delete V;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
71
Editor/Util/Triangulate.h
Normal file
71
Editor/Util/Triangulate.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// ** THIS IS A CODE SNIPPET WHICH WILL EFFICIEINTLY TRIANGULATE ANY
|
||||
// ** POLYGON/CONTOUR (without holes) AS A STATIC CLASS. THIS SNIPPET
|
||||
// ** IS COMPRISED OF 3 FILES, TRIANGULATE.H, THE HEADER FILE FOR THE
|
||||
// ** TRIANGULATE BASE CLASS, TRIANGULATE.CPP, THE IMPLEMENTATION OF
|
||||
// ** THE TRIANGULATE BASE CLASS, AND TEST.CPP, A SMALL TEST PROGRAM
|
||||
// ** DEMONSTRATING THE USAGE OF THE TRIANGULATOR. THE TRIANGULATE
|
||||
// ** BASE CLASS ALSO PROVIDES TWO USEFUL HELPER METHODS, ONE WHICH
|
||||
// ** COMPUTES THE AREA OF A POLYGON, AND ANOTHER WHICH DOES AN EFFICENT
|
||||
// ** POINT IN A TRIANGLE TEST.
|
||||
// ** SUBMITTED BY JOHN W. RATCLIFF (jratcliff@verant.com) July 22, 2000
|
||||
|
||||
/**********************************************************************/
|
||||
/************ HEADER FILE FOR TRIANGULATE.H ***************************/
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
#ifndef TRIANGULATE_H
|
||||
|
||||
#define TRIANGULATE_H
|
||||
|
||||
/*****************************************************************/
|
||||
/** Static class to triangulate any contour/polygon efficiently **/
|
||||
/** You should replace Vector2d with whatever your own Vector **/
|
||||
/** class might be. Does not support polygons with holes. **/
|
||||
/** Uses STL vectors to represent a dynamic array of vertices. **/
|
||||
/** This code snippet was submitted to FlipCode.com by **/
|
||||
/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000 **/
|
||||
/** I did not write the original code/algorithm for this **/
|
||||
/** this triangulator, in fact, I can't even remember where I **/
|
||||
/** found it in the first place. However, I did rework it into **/
|
||||
/** the following black-box static class so you can make easy **/
|
||||
/** use of it in your own code. Simply replace Vector2d with **/
|
||||
/** whatever your own Vector implementation might be. **/
|
||||
/*****************************************************************/
|
||||
|
||||
|
||||
#include <vector> // Include STL vector class.
|
||||
|
||||
// Typedef an STL vector of vertices which are used to represent
|
||||
// a polygon/contour and a series of triangles.
|
||||
typedef std::vector< Vec3 > Vector2dVector;
|
||||
|
||||
|
||||
class CTriangulate
|
||||
{
|
||||
public:
|
||||
|
||||
// triangulate a contour/polygon, places results in STL vector
|
||||
// as series of triangles.
|
||||
static bool Process(const Vector2dVector &contour,
|
||||
Vector2dVector &result);
|
||||
|
||||
// compute area of a contour/polygon
|
||||
static float Area(const Vector2dVector &contour);
|
||||
|
||||
// decide if point Px/Py is inside triangle defined by
|
||||
// (Ax,Ay) (Bx,By) (Cx,Cy)
|
||||
static bool InsideTriangle(float Ax, float Ay,
|
||||
float Bx, float By,
|
||||
float Cx, float Cy,
|
||||
float Px, float Py);
|
||||
|
||||
|
||||
private:
|
||||
static bool Snip(const Vector2dVector &contour,int u,int v,int w,int n,int *V);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
483
Editor/Util/Variable.cpp
Normal file
483
Editor/Util/Variable.cpp
Normal file
@@ -0,0 +1,483 @@
|
||||
#include <StdAfx.h>
|
||||
|
||||
#include "Variable.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock::~CVarBlock()
|
||||
{
|
||||
/*
|
||||
// When destroying var block, callbacks of all holded variables must be deleted.
|
||||
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
var->
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarBlock* CVarBlock::Clone( bool bRecursive ) const
|
||||
{
|
||||
CVarBlock *vb = new CVarBlock;
|
||||
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
vb->AddVariable( var->Clone(bRecursive) );
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::CopyValues( CVarBlock *fromVarBlock )
|
||||
{
|
||||
// Copy all variables.
|
||||
int numSrc = fromVarBlock->GetVarsCount();
|
||||
int numTrg = GetVarsCount();
|
||||
for (int i = 0; i < numSrc && i < numTrg; i++)
|
||||
{
|
||||
GetVariable(i)->CopyValue( fromVarBlock->GetVariable(i) );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::CopyValuesByName( CVarBlock *fromVarBlock )
|
||||
{
|
||||
// Copy values using saving and loading to/from xml.
|
||||
XmlNodeRef node = new CXmlNode( "Temp" );
|
||||
fromVarBlock->Serialize( node,false );
|
||||
Serialize( node,true );
|
||||
/*
|
||||
// Copy all variables.
|
||||
int numSrc = fromVarBlock->GetVarsCount();
|
||||
for (int i = 0; i < numSrc; i++)
|
||||
{
|
||||
IVariable *srcVar = fromVarBlock->GetVariable(i);
|
||||
IVariable *trgVar = FindVariable( srcVar->GetName(),false );
|
||||
if (trgVar)
|
||||
{
|
||||
CopyVarByName( srcVar,trgVar );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::CopyVarByName( IVariable *src,IVariable *trg )
|
||||
{
|
||||
assert( src && trg );
|
||||
// Check if type match.
|
||||
if (src->GetType() != trg->GetType())
|
||||
return;
|
||||
|
||||
int numSrc = src->NumChildVars();
|
||||
if (numSrc == 0)
|
||||
{
|
||||
// Copy single value.
|
||||
trg->CopyValue( src );
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
int numTrg = trg->NumChildVars();
|
||||
std::map<CString,IVariable*> nameMap;
|
||||
for (int i = 0; i < numTrg; i++)
|
||||
{
|
||||
}
|
||||
|
||||
// Copy array items, matching by name.
|
||||
for (int i = 0; i < numSrc; i++)
|
||||
{
|
||||
IVariable *srcChild = src->GetChildVar(i);
|
||||
IVariable *trgChild = 0;
|
||||
FindVariable( srcChild->GetName(),false );
|
||||
if (trgChild)
|
||||
{
|
||||
CopyVarByName( srcChild,trgChild );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::AddVariable( IVariable *var )
|
||||
{
|
||||
m_vars.push_back(var);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IVariable* CVarBlock::FindVariable( const char *name,bool bRecursive ) const
|
||||
{
|
||||
// Search all top level variables.
|
||||
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
if (strcmp(var->GetName(),name) == 0)
|
||||
return var;
|
||||
}
|
||||
// If not found search childs.
|
||||
if (bRecursive)
|
||||
{
|
||||
// Search all top level variables.
|
||||
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
IVariable *found = FindChildVar(name,var);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IVariable* CVarBlock::FindChildVar( const char *name,IVariable *pParentVar ) const
|
||||
{
|
||||
if (strcmp(pParentVar->GetName(),name) == 0)
|
||||
return pParentVar;
|
||||
int numSubVar = pParentVar->NumChildVars();
|
||||
for (int i = 0; i < numSubVar; i++)
|
||||
{
|
||||
IVariable *var = FindChildVar( name,pParentVar->GetChildVar(i) );
|
||||
if (var)
|
||||
return var;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::Serialize( XmlNodeRef &vbNode,bool load )
|
||||
{
|
||||
if (load)
|
||||
{
|
||||
// Loading.
|
||||
CString name;
|
||||
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
if (var->NumChildVars())
|
||||
{
|
||||
XmlNodeRef child = vbNode->findChild(var->GetName());
|
||||
if (child)
|
||||
var->Serialize( child,load );
|
||||
}
|
||||
else
|
||||
var->Serialize( vbNode,load );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
if (var->NumChildVars())
|
||||
{
|
||||
XmlNodeRef child = vbNode->newChild(var->GetName());
|
||||
var->Serialize( child,load );
|
||||
}
|
||||
else
|
||||
var->Serialize( vbNode,load );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::ReserveNumVariables( int numVars )
|
||||
{
|
||||
m_vars.reserve( numVars );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::WireVar( IVariable *src,IVariable *trg,bool bWire )
|
||||
{
|
||||
if (bWire)
|
||||
src->Wire(trg);
|
||||
else
|
||||
src->Unwire(trg);
|
||||
int numSrcVars = src->NumChildVars();
|
||||
if (numSrcVars > 0)
|
||||
{
|
||||
int numTrgVars = trg->NumChildVars();
|
||||
for (int i = 0; i < numSrcVars && i < numTrgVars; i++)
|
||||
{
|
||||
WireVar(src->GetChildVar(i),trg->GetChildVar(i),bWire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::Wire( CVarBlock *toVarBlock )
|
||||
{
|
||||
Variables::iterator tit = toVarBlock->m_vars.begin();
|
||||
Variables::iterator sit = m_vars.begin();
|
||||
for (; sit != m_vars.end() && tit != toVarBlock->m_vars.end(); ++sit,++tit)
|
||||
{
|
||||
IVariable *src = *sit;
|
||||
IVariable *trg = *tit;
|
||||
WireVar(src,trg,true);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::Unwire( CVarBlock *toVarBlock )
|
||||
{
|
||||
Variables::iterator tit = toVarBlock->m_vars.begin();
|
||||
Variables::iterator sit = m_vars.begin();
|
||||
for (; sit != m_vars.end() && tit != toVarBlock->m_vars.end(); ++sit,++tit)
|
||||
{
|
||||
IVariable *src = *sit;
|
||||
IVariable *trg = *tit;
|
||||
WireVar(src,trg,false);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::AddOnSetCallback( IVariable::OnSetCallback func )
|
||||
{
|
||||
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
SetCallbackToVar( func,var,true );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::RemoveOnSetCallback( IVariable::OnSetCallback func )
|
||||
{
|
||||
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
SetCallbackToVar( func,var,false );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::SetCallbackToVar( IVariable::OnSetCallback func,IVariable *pVar,bool bAdd )
|
||||
{
|
||||
if (bAdd)
|
||||
pVar->AddOnSetCallback(func);
|
||||
else
|
||||
pVar->RemoveOnSetCallback(func);
|
||||
int numVars = pVar->NumChildVars();
|
||||
if (numVars > 0)
|
||||
{
|
||||
for (int i = 0; i < numVars; i++)
|
||||
{
|
||||
SetCallbackToVar( func,pVar->GetChildVar(i),bAdd );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::GatherUsedResources( CUsedResources &resources )
|
||||
{
|
||||
for (int i = 0; i < GetVarsCount(); i++)
|
||||
{
|
||||
IVariable *pVar = GetVariable(i);
|
||||
GatherUsedResourcesInVar( pVar,resources );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarBlock::GatherUsedResourcesInVar( IVariable *pVar,CUsedResources &resources )
|
||||
{
|
||||
int type = pVar->GetDataType();
|
||||
if (type == IVariable::DT_FILE || type == IVariable::DT_OBJECT || type == IVariable::DT_SOUND
|
||||
|| type == IVariable::DT_TEXTURE)
|
||||
{
|
||||
// this is file.
|
||||
CString filename;
|
||||
pVar->Get( filename );
|
||||
if (!filename.IsEmpty())
|
||||
resources.Add( filename );
|
||||
}
|
||||
for (int i = 0; i < pVar->NumChildVars(); i++)
|
||||
{
|
||||
GatherUsedResourcesInVar( pVar->GetChildVar(i),resources );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarObject::CVarObject()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVarObject::~CVarObject()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarObject::AddVariable( CVariableBase &var,const CString &varName,VarOnSetCallback cb,unsigned char dataType )
|
||||
{
|
||||
if (!m_vars)
|
||||
m_vars = new CVarBlock;
|
||||
var.AddRef(); // Variables are local and must not be released by CVarBlock.
|
||||
var.SetName(varName);
|
||||
var.SetDataType(dataType);
|
||||
if (cb)
|
||||
var.AddOnSetCallback(cb);
|
||||
m_vars->AddVariable(&var);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarObject::AddVariable( CVariableBase &var,const CString &varName,const CString &varHumanName,VarOnSetCallback cb,unsigned char dataType )
|
||||
{
|
||||
if (!m_vars)
|
||||
m_vars = new CVarBlock;
|
||||
var.AddRef(); // Variables are local and must not be released by CVarBlock.
|
||||
var.SetName(varName);
|
||||
var.SetHumanName(varHumanName);
|
||||
var.SetDataType(dataType);
|
||||
if (cb)
|
||||
var.AddOnSetCallback(cb);
|
||||
m_vars->AddVariable(&var);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarObject::ReserveNumVariables( int numVars )
|
||||
{
|
||||
m_vars->ReserveNumVariables( numVars );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarObject::CopyVariableValues( CVarObject *sourceObject )
|
||||
{
|
||||
// Check if compatable types.
|
||||
assert( GetRuntimeClass() == sourceObject->GetRuntimeClass() );
|
||||
if (m_vars != NULL && sourceObject->m_vars != NULL)
|
||||
m_vars->CopyValues(sourceObject->m_vars);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CVarObject::Serialize( XmlNodeRef node,bool load )
|
||||
{
|
||||
if (m_vars)
|
||||
{
|
||||
m_vars->Serialize( node,load );
|
||||
}
|
||||
}
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CEntity : public CVarObject
|
||||
{
|
||||
public:
|
||||
CEntity();
|
||||
public:
|
||||
CVariable<Vec3> m_pos;
|
||||
CVariable<Vec3> m_angles;
|
||||
CVariable<float> m_scale;
|
||||
CVariable<float> m_fov;
|
||||
|
||||
CVarBlock vars;
|
||||
|
||||
void Serialize( XmlNodeRef node,bool load )
|
||||
{
|
||||
CVarObject::Serialize( node,load );
|
||||
if (load)
|
||||
{
|
||||
XmlNodeRef props = node->findChild("Properties");
|
||||
if (props)
|
||||
vars.Serialize( props,load );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlNodeRef props = node->newChild("Properties");
|
||||
vars.Serialize( props,load );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void OnPosChanged( IVariable *var ) const
|
||||
{
|
||||
std::cout << "Var Changed: " << var->GetName() << "\n";
|
||||
}
|
||||
void OnFovChanged( IVariable *var ) const
|
||||
{
|
||||
std::cout << "FOV FOV! Changed: " << var->GetName() << "\n";
|
||||
}
|
||||
void Cool( int i )
|
||||
{
|
||||
std::cout << "" << i << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEntity::CEntity()
|
||||
{
|
||||
// typedef void (CEntity::*MemFunc)(IVariable*);
|
||||
// MemFunc f = CEntity::OnPosChanged;
|
||||
// CBMemberTranslator1<IVariable*,CEntity,MemFunc>(*this,f);
|
||||
|
||||
AddVariable( "Pos",0,m_pos,functor(*this,OnPosChanged) );
|
||||
AddVariable( "Angles",0,m_angles );
|
||||
AddVariable( "Scale",0,m_scale );
|
||||
AddVariable( "Fov",0,m_fov );
|
||||
|
||||
CVariableBase *v;
|
||||
|
||||
v = new CVariable<float>;
|
||||
v->SetName("Width");
|
||||
v->Set(10);
|
||||
vars.AddVariable(v);
|
||||
|
||||
v = new CVariable<float>;
|
||||
v->SetName("Height");
|
||||
v->Set(20);
|
||||
vars.AddVariable(v);
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
CEntity *entity = new CEntity;
|
||||
entity->m_pos = Vec3(4,5,6);
|
||||
entity->m_angles = Vec3(1,2,3);
|
||||
entity->m_fov = 10;
|
||||
entity->m_scale = 30;
|
||||
|
||||
XmlNodeRef node = new CXmlNode( "Root" );
|
||||
//XmlParser parser;
|
||||
//node = parser.parse("c:\\test.xml");
|
||||
entity->Serialize( node,false );
|
||||
node->saveToFile("c:\\test.xml");
|
||||
|
||||
std::vector<int> v;
|
||||
|
||||
std::list<char> lst;
|
||||
|
||||
float f = 4.452f;
|
||||
double d;
|
||||
int i;
|
||||
short s;
|
||||
unsigned char c;
|
||||
Vec3 vec;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << f;
|
||||
ss >> f;
|
||||
|
||||
//cast_stream(f,i);
|
||||
//cast_stream(f,d);
|
||||
//cast_stream(f,s);
|
||||
//cast_stream(f,c);
|
||||
|
||||
//Tvareter<int> a("aa");
|
||||
//Tvareter<Vec3> b("bb");
|
||||
std::stringstream str;
|
||||
|
||||
str << f;
|
||||
str >> i;
|
||||
str >> d;
|
||||
str >> s;
|
||||
str >> c;
|
||||
|
||||
typeid(int);
|
||||
|
||||
str >> s;
|
||||
|
||||
CVariable<float> vara;
|
||||
f = vara;
|
||||
vara = f;
|
||||
}
|
||||
*/
|
||||
997
Editor/Util/Variable.h
Normal file
997
Editor/Util/Variable.h
Normal file
@@ -0,0 +1,997 @@
|
||||
#ifndef __Variable_h__
|
||||
#define __Variable_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//typedef string CString;
|
||||
inline const char* to_c_str( const char *str ) { return str; }
|
||||
inline const char* to_c_str( const string &str ) { return str.c_str(); }
|
||||
inline const char* to_c_str( const CString &str ) { return str; }
|
||||
#define MAX_VAR_STRING_LENGTH 4096
|
||||
|
||||
#define DEFAULT_VARIABLE_MIN -100000
|
||||
#define DEFAULT_VARIABLE_MAX 100000
|
||||
|
||||
struct IVarEnumList;
|
||||
class CUsedResources;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** IVariable is the variant variable interface.
|
||||
*/
|
||||
struct IVariable : public CRefCountBase
|
||||
{
|
||||
/** Type of data stored in variable.
|
||||
*/
|
||||
enum EType
|
||||
{
|
||||
UNKNOWN, //!< Unknown paremeter type.
|
||||
INT, //!< Integer property.
|
||||
BOOL, //!< Boolean property.
|
||||
FLOAT, //!< Float property.
|
||||
VECTOR, //!< Vector property.
|
||||
QUAT, //!< Quaternion property.
|
||||
STRING, //!< String property.
|
||||
ARRAY //!< Array of parameters.
|
||||
};
|
||||
|
||||
//! Type of data holded by variable.
|
||||
enum EDataType
|
||||
{
|
||||
DT_SIMPLE = 0, //!< Standart param type.
|
||||
DT_PERCENT, //!< Percent data type, (Same as simple but value is from 0-1 and UI will be from 0-100).
|
||||
DT_COLOR,
|
||||
DT_ANGLE,
|
||||
DT_FILE,
|
||||
DT_TEXTURE,
|
||||
DT_SOUND,
|
||||
DT_OBJECT,
|
||||
DT_SHADER,
|
||||
DT_AI_BEHAVIOR,
|
||||
DT_AI_ANCHOR,
|
||||
DT_AI_CHARACTER,
|
||||
DT_LOCAL_STRING,
|
||||
DT_EQUIP,
|
||||
DT_SOUNDPRESET,
|
||||
DT_EAXPRESET,
|
||||
DT_MATERIAL
|
||||
};
|
||||
|
||||
// Flags that can used with variables.
|
||||
enum EFlags
|
||||
{
|
||||
// User interface related flags.
|
||||
UI_DISABLED = 0x01, //!< If Set this variable will be disabled in UI.
|
||||
UI_BOLD = 0x02, //!< If set, variable name in properties will be bold.
|
||||
};
|
||||
|
||||
typedef Functor1<IVariable*> OnSetCallback;
|
||||
|
||||
//! Get name of parameter.
|
||||
virtual const char* GetName() const = 0;
|
||||
//! Set name of parameter.
|
||||
virtual void SetName( const CString &name ) = 0;
|
||||
|
||||
//! Get human readable name of parameter (Normally same as name).
|
||||
virtual const char* GetHumanName() const = 0;
|
||||
//! Set human readable name of parameter (Normall same as name).
|
||||
virtual void SetHumanName( const CString &name ) = 0;
|
||||
|
||||
//! Get variable description.
|
||||
virtual const char* GetDescription() const = 0;
|
||||
//! Set variable description.
|
||||
virtual void SetDescription( const char *desc ) = 0;
|
||||
|
||||
//! Get paremeter type.
|
||||
virtual EType GetType() const = 0;
|
||||
//! Get size of parameter.
|
||||
virtual int GetSize() const = 0;
|
||||
|
||||
//! Type of data stored in this variable.
|
||||
virtual unsigned char GetDataType() const = 0;
|
||||
virtual void SetDataType( unsigned char dataType ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Flags
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Set variable flags, (Limited to 8 flags).
|
||||
virtual void SetFlags( int flags ) = 0;
|
||||
virtual int GetFlags() const = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Set methods.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
virtual void Set( int value ) = 0;
|
||||
virtual void Set( bool value ) = 0;
|
||||
virtual void Set( float value ) = 0;
|
||||
virtual void Set( const Vec3 &value ) = 0;
|
||||
virtual void Set( const Quat &value ) = 0;
|
||||
virtual void Set( const CString &value ) = 0;
|
||||
virtual void Set( const char *value ) = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Get methods.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
virtual void Get( int &value ) const = 0;
|
||||
virtual void Get( bool &value ) const = 0;
|
||||
virtual void Get( float &value ) const = 0;
|
||||
virtual void Get( Vec3 &value ) const = 0;
|
||||
virtual void Get( Quat &value ) const = 0;
|
||||
virtual void Get( CString &value ) const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For vector parameters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual int NumChildVars() const = 0;
|
||||
virtual IVariable* GetChildVar( int index ) const = 0;
|
||||
virtual void AddChildVar( IVariable *var ) = 0;
|
||||
virtual void DeleteAllChilds() = 0;
|
||||
|
||||
//! Return cloned value of variable.
|
||||
virtual IVariable* Clone( bool bRecursive ) const = 0;
|
||||
|
||||
//! Copy variable value from specified variable.
|
||||
//! This method executed always recursively on all sub hierachy of variables,
|
||||
//! In Array vars, will never create new variables, only copy values of corresponding childs.
|
||||
//! @param fromVar Source variable to copy value from.
|
||||
virtual void CopyValue( IVariable *fromVar ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Value Limits.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Set value limits.
|
||||
virtual void SetLimits( float min,float max ) = 0;
|
||||
//! Get value limits.
|
||||
virtual void GetLimits( float &min,float &max ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Wire/Unwire variables.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Wire variable, wired variable will be changed when this var changes.
|
||||
virtual void Wire( IVariable *targetVar ) = 0;
|
||||
//! Unwire variable.
|
||||
virtual void Unwire( IVariable *targetVar ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Assign on set callback.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void AddOnSetCallback( OnSetCallback func ) = 0;
|
||||
virtual void RemoveOnSetCallback( OnSetCallback func ) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Retrieve pointer to selection list used by variable.
|
||||
virtual IVarEnumList* GetEnumList() const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Serialize variable to XML.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Serialize( XmlNodeRef node,bool load ) = 0;
|
||||
};
|
||||
|
||||
// Smart pointer to this parameter.
|
||||
typedef TSmartPtr<IVariable> IVariablePtr;
|
||||
|
||||
/**
|
||||
**************************************************************************************
|
||||
* CVariableBase implements IVariable interface and provide default implementation
|
||||
* for basic IVariable functionality (Name, Flags, etc...)
|
||||
* CVariableBase cannot be instantiated directly and should be used as the base class for
|
||||
* actual Variant implementation classes.
|
||||
***************************************************************************************
|
||||
*/
|
||||
class CVariableBase : public IVariable
|
||||
{
|
||||
public:
|
||||
~CVariableBase() {}
|
||||
|
||||
void SetName( const CString &name ) { m_name = name; };
|
||||
//! Get name of parameter.
|
||||
const char* GetName() const { return to_c_str(m_name); };
|
||||
|
||||
const char* GetHumanName() const
|
||||
{
|
||||
if (!m_humanName.IsEmpty())
|
||||
return m_humanName;
|
||||
return m_name;
|
||||
}
|
||||
void SetHumanName( const CString &name ) { m_humanName = name; }
|
||||
|
||||
void SetDescription( const char *desc ) { m_description = desc; };
|
||||
//! Get name of parameter.
|
||||
const char* GetDescription() const { return to_c_str(m_description); };
|
||||
|
||||
EType GetType() const { return IVariable::UNKNOWN; };
|
||||
int GetSize() const { return sizeof(*this); };
|
||||
|
||||
unsigned char GetDataType() const { return m_dataType; };
|
||||
void SetDataType( unsigned char dataType ) { m_dataType = dataType; }
|
||||
|
||||
void SetFlags( int flags ) { m_flags = flags; }
|
||||
int GetFlags() const { return m_flags; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Set( int value ) { assert(0); }
|
||||
void Set( bool value ) { assert(0); }
|
||||
void Set( float value ) { assert(0); }
|
||||
void Set( const Vec3 &value ) { assert(0); }
|
||||
void Set( const Quat &value ) { assert(0); }
|
||||
void Set( const CString &value ) { assert(0); }
|
||||
void Set( const char *value ) { assert(0); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Get( int &value ) const { assert(0); }
|
||||
void Get( bool &value ) const { assert(0); }
|
||||
void Get( float &value ) const { assert(0); }
|
||||
void Get( Vec3 &value ) const { assert(0); }
|
||||
void Get( Quat &value ) const { assert(0); }
|
||||
void Get( CString &value ) const { assert(0); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implementation functions.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int NumChildVars() const { return 0; }
|
||||
IVariable* GetChildVar( int index ) const { return 0; }
|
||||
void AddChildVar( IVariable *var ) { assert(0); }; // Not supported.
|
||||
void DeleteAllChilds() {};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Wire( IVariable *var )
|
||||
{
|
||||
m_wiredVars.push_back(var);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Unwire( IVariable *var )
|
||||
{
|
||||
if (!var)
|
||||
{
|
||||
// Unwire all.
|
||||
m_wiredVars.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
stl::find_and_erase( m_wiredVars,var );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void AddOnSetCallback( OnSetCallback func )
|
||||
{
|
||||
m_onSetFuncs.push_back(func);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void RemoveOnSetCallback( OnSetCallback func )
|
||||
{
|
||||
stl::find_and_erase( m_onSetFuncs,func );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Serialize( XmlNodeRef node,bool load )
|
||||
{
|
||||
if (load)
|
||||
{
|
||||
// Loading.
|
||||
if (node->haveAttr(to_c_str(m_name)))
|
||||
{
|
||||
const char *str = node->getAttr(to_c_str(m_name));
|
||||
Set( CString(str) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
CString str;
|
||||
Get( str );
|
||||
node->setAttr( to_c_str(m_name),to_c_str(str) );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetLimits( float min,float max ) {};
|
||||
virtual void GetLimits( float &min,float &max ) {};
|
||||
virtual IVarEnumList* GetEnumList() const { return 0; };
|
||||
|
||||
protected:
|
||||
// Constructor.
|
||||
CVariableBase() {
|
||||
m_dataType = DT_SIMPLE;
|
||||
m_flags = 0;
|
||||
};
|
||||
// Copy constructor.
|
||||
CVariableBase( const CVariableBase &var )
|
||||
{
|
||||
m_name = var.m_name;
|
||||
m_humanName = var.m_humanName;
|
||||
m_flags = var.m_flags;
|
||||
m_dataType = var.m_dataType;
|
||||
// Never copy callback function or wired variables they are private to specific variable,
|
||||
|
||||
};
|
||||
private:
|
||||
// Not allow.
|
||||
CVariableBase& operator=( const CVariableBase &var )
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Variables.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef std::vector<OnSetCallback> OnSetCallbackList;
|
||||
typedef std::vector<IVariablePtr> WiredList;
|
||||
|
||||
CString m_name;
|
||||
CString m_humanName;
|
||||
CString m_description;
|
||||
|
||||
//! Extended data (Extended data is never copied, it's always private to this variable).
|
||||
WiredList m_wiredVars;
|
||||
OnSetCallbackList m_onSetFuncs;
|
||||
|
||||
// Wired params.
|
||||
//! Limited to 8 flags.
|
||||
unsigned char m_flags;
|
||||
unsigned char m_dataType;
|
||||
};
|
||||
|
||||
/**
|
||||
**************************************************************************************
|
||||
* CVariableArray implements variable of type array of IVariables.
|
||||
***************************************************************************************
|
||||
*/
|
||||
class CVariableArray : public CVariableBase
|
||||
{
|
||||
public:
|
||||
CVariableArray() {};
|
||||
// Copy Constructor.
|
||||
CVariableArray( const CVariableArray &var ) : CVariableBase(var)
|
||||
{}
|
||||
|
||||
//! Get name of parameter.
|
||||
virtual EType GetType() const { return IVariable::ARRAY; };
|
||||
virtual int GetSize() const { return sizeof(CVariableArray); };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Set( const char *value )
|
||||
{
|
||||
if (m_strValue != value)
|
||||
{
|
||||
m_strValue = value;
|
||||
// If have wired variables or OnSet callback, process them.
|
||||
// Call on set callback.
|
||||
for (OnSetCallbackList::iterator it = m_onSetFuncs.begin(); it != m_onSetFuncs.end(); ++it)
|
||||
{
|
||||
// Call on set callback.
|
||||
(*it)(this);
|
||||
}
|
||||
// Send value to wired variable.
|
||||
for (WiredList::iterator it = m_wiredVars.begin(); it != m_wiredVars.end(); ++it)
|
||||
{
|
||||
// Set current value on each wired variable.
|
||||
(*it)->Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Get( CString &value ) const { value = m_strValue; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IVariable* Clone( bool bRecursive ) const
|
||||
{
|
||||
CVariableArray *var = new CVariableArray(*this);
|
||||
for (Vars::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
var->m_vars.push_back( (*it)->Clone(bRecursive) );
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CopyValue( IVariable *fromVar )
|
||||
{
|
||||
assert(fromVar);
|
||||
if (fromVar->GetType() != IVariable::ARRAY)
|
||||
return;
|
||||
int numSrc = fromVar->NumChildVars();
|
||||
int numTrg = m_vars.size();
|
||||
for (int i = 0; i < numSrc && i < numTrg; i++)
|
||||
{
|
||||
// Copy Every child variable.
|
||||
m_vars[i]->CopyValue( fromVar->GetChildVar(i) );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int NumChildVars() const { return m_vars.size(); }
|
||||
IVariable* GetChildVar( int index ) const
|
||||
{
|
||||
assert( index >= 0 && index < (int)m_vars.size() );
|
||||
return m_vars[index];
|
||||
}
|
||||
void AddChildVar( IVariable *var )
|
||||
{
|
||||
m_vars.push_back(var);
|
||||
}
|
||||
|
||||
void DeleteAllChilds()
|
||||
{
|
||||
m_vars.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Serialize( XmlNodeRef node,bool load )
|
||||
{
|
||||
if (load)
|
||||
{
|
||||
// Loading.
|
||||
CString name;
|
||||
for (Vars::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
if (var->NumChildVars())
|
||||
{
|
||||
XmlNodeRef child = node->findChild(var->GetName());
|
||||
if (child)
|
||||
var->Serialize( child,load );
|
||||
}
|
||||
else
|
||||
var->Serialize( node,load );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
for (Vars::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
|
||||
{
|
||||
IVariable *var = *it;
|
||||
if (var->NumChildVars())
|
||||
{
|
||||
XmlNodeRef child = node->newChild(var->GetName());
|
||||
var->Serialize( child,load );
|
||||
}
|
||||
else
|
||||
var->Serialize( node,load );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef std::vector<IVariablePtr> Vars;
|
||||
Vars m_vars;
|
||||
//! Any string value displayed in properties.
|
||||
CString m_strValue;
|
||||
};
|
||||
|
||||
/** var_type namespace includes type definitions needed for CVariable implementaton.
|
||||
*/
|
||||
namespace var_type
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <int TypeID,bool IsStandart,bool IsInteger,bool IsSigned>
|
||||
struct type_traits_base
|
||||
{
|
||||
static int type() { return TypeID; };
|
||||
//! Return true if standart C++ type.
|
||||
static bool is_standart() { return IsStandart; };
|
||||
static bool is_integer() { return IsInteger; };
|
||||
static bool is_signed() { return IsSigned; };
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
struct type_traits : public type_traits_base<IVariable::UNKNOWN,false,false,false> {};
|
||||
|
||||
// Types specialization.
|
||||
template<> struct type_traits<int> : public type_traits_base<IVariable::INT,true,true,true> {};
|
||||
template<> struct type_traits<bool> : public type_traits_base<IVariable::BOOL,true,true,false> {};
|
||||
template<> struct type_traits<float> : public type_traits_base<IVariable::FLOAT,true,false,false> {};
|
||||
template<> struct type_traits<Vec3> : public type_traits_base<IVariable::VECTOR,false,false,false> {};
|
||||
template<> struct type_traits<Quat> : public type_traits_base<IVariable::QUAT,false,false,false> {};
|
||||
template<> struct type_traits<CString> : public type_traits_base<IVariable::STRING,false,false,false> {};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Extended stream operatios.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Put CString to out stream operator.
|
||||
inline std::ostream& operator<<( std::ostream &stream,const CString &s )
|
||||
{
|
||||
stream << to_c_str(s);
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Put Vec3 to out stream operator.
|
||||
inline std::ostream& operator<<( std::ostream &stream,const Vec3 &v )
|
||||
{
|
||||
stream << v.x << "," << v.y << "," << v.z;
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Put Quat to out stream operator.
|
||||
inline std::ostream& operator<<( std::ostream &stream,const Quat &q )
|
||||
{
|
||||
stream << q.w << "," << q.v.x << "," << q.v.y << "," << q.v.z;
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Get CString from input stream operator.
|
||||
inline std::istream& operator>>( std::istream &stream,CString &s )
|
||||
{
|
||||
// String is limited..
|
||||
char str[MAX_VAR_STRING_LENGTH];
|
||||
stream >> str;
|
||||
s = str;
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Get Vec3 from input stream operator.
|
||||
inline std::istream& operator>>( std::istream &stream,Vec3 &v )
|
||||
{
|
||||
char s[64];
|
||||
stream >> s;
|
||||
v.x = v.y = v.z = 0;
|
||||
sscanf( s,"%f,%f,%f",&v.x,&v.y,&v.z );
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Get Quat from input stream operator.
|
||||
inline std::istream& operator>>( std::istream &stream,Quat &q )
|
||||
{
|
||||
char s[64];
|
||||
stream >> s;
|
||||
q.v.x = q.v.y = q.v.z = q.w = 0;
|
||||
sscanf( s,"%f,%f,%f,%f",&q.w,&q.v.x,&q.v.y,&q.v.z );
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// General one type to another type convertor class.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class From,class To>
|
||||
struct type_convertor
|
||||
{
|
||||
void operator()( const From &value,To &to ) const
|
||||
{
|
||||
// Use stream conversion.
|
||||
std::stringstream ss;
|
||||
ss << value; // first insert value to stream
|
||||
ss >> to; // write value to result
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Specialized faster conversions.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template<> void type_convertor<int,int>::operator()( const int &from,int &to ) const { to = from; }
|
||||
template<> void type_convertor<int,bool>::operator()( const int &from,bool &to ) const { to = from != 0; }
|
||||
template<> void type_convertor<int,float>::operator()( const int &from,float &to ) const { to = (float)from; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template<> void type_convertor<bool,int>::operator()( const bool &from,int &to ) const { to = from; }
|
||||
template<> void type_convertor<bool,bool>::operator()( const bool &from,bool &to ) const { to = from; }
|
||||
template<> void type_convertor<bool,float>::operator()( const bool &from,float &to ) const { to = from; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template<> void type_convertor<float,int>::operator()( const float &from,int &to ) const { to = (int)from; }
|
||||
template<> void type_convertor<float,bool>::operator()( const float &from,bool &to ) const { to = from != 0; }
|
||||
template<> void type_convertor<float,float>::operator()( const float &from,float &to ) const { to = from; }
|
||||
|
||||
template<> void type_convertor<Vec3,Vec3>::operator()( const Vec3 &from,Vec3 &to ) const { to = from; }
|
||||
template<> void type_convertor<Quat,Quat>::operator()( const Quat &from,Quat &to ) const { to = from; }
|
||||
template<> void type_convertor<CString,CString>::operator()( const CString &from,CString &to ) const { to = from; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Custom comparasion functions for different variable type's values,.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
inline bool compare( const Type &arg1,const Type &arg2 )
|
||||
{
|
||||
return arg1 == arg2;
|
||||
};
|
||||
inline bool compare( const Vec3 &v1,const Vec3 &v2 )
|
||||
{
|
||||
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
|
||||
}
|
||||
inline bool compare( const Quat &q1,const Quat &q2 )
|
||||
{
|
||||
return q1.v.x == q2.v.x && q1.v.y == q2.v.y && q1.v.z == q2.v.z && q1.w == q2.w;
|
||||
}
|
||||
inline bool compare( const char* s1,const char* s2 )
|
||||
{
|
||||
return strcmp(s1,s2) == 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Custom Initializaton functions for different variable type's values,.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
inline void init( Type &val )
|
||||
{
|
||||
val = 0;
|
||||
};
|
||||
inline void init( Vec3 &val )
|
||||
{
|
||||
val.x = 0; val.y = 0;val.z = 0;
|
||||
};
|
||||
inline void init( Quat &val )
|
||||
{
|
||||
val.v.x = 0; val.v.y = 0; val.v.z = 0; val.w = 0;
|
||||
};
|
||||
inline void init( const char* &val )
|
||||
{
|
||||
val = "";
|
||||
};
|
||||
inline void init( CString &val )
|
||||
{
|
||||
// self initializing.
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class CVariable : public CVariableBase
|
||||
{
|
||||
typedef CVariable<T> Self;
|
||||
public:
|
||||
// Constructor.
|
||||
CVariable()
|
||||
{
|
||||
// Initialize value to zero or empty string.
|
||||
var_type::init( m_value );
|
||||
m_valueMin = DEFAULT_VARIABLE_MIN;
|
||||
m_valueMax = DEFAULT_VARIABLE_MAX;
|
||||
}
|
||||
|
||||
//! Get name of parameter.
|
||||
virtual EType GetType() const { return (EType)var_type::type_traits<T>::type(); };
|
||||
virtual int GetSize() const { return sizeof(T); };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Set( int value ) { SetValue(value); }
|
||||
virtual void Set( bool value ) { SetValue(value); }
|
||||
virtual void Set( float value ) { SetValue(value); }
|
||||
virtual void Set( const Vec3 &value ) { SetValue(value); }
|
||||
virtual void Set( const Quat &value ) { SetValue(value); }
|
||||
virtual void Set( const CString &value ) { SetValue(value); }
|
||||
virtual void Set( const char *value ) { SetValue(CString(value)); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Get( int &value ) const { GetValue(value); }
|
||||
virtual void Get( bool &value ) const { GetValue(value); }
|
||||
virtual void Get( float &value ) const { GetValue(value); }
|
||||
virtual void Get( Vec3 &value ) const { GetValue(value); }
|
||||
virtual void Get( Quat &value ) const { GetValue(value); }
|
||||
virtual void Get( CString &value ) const { GetValue(value); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Limits.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetLimits( float min,float max )
|
||||
{
|
||||
m_valueMin = min;
|
||||
m_valueMax = max;
|
||||
}
|
||||
virtual void GetLimits( float &min,float &max )
|
||||
{
|
||||
min = m_valueMin;
|
||||
max = m_valueMax;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Access operators.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Cast to holded type.
|
||||
operator T() const { return m_value; }
|
||||
|
||||
//! Assign operator for variable.
|
||||
void operator=( const T& value ) { SetValue(value); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IVariable* Clone( bool bRecursive ) const
|
||||
{
|
||||
Self *var = new Self(*this);
|
||||
return var;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CopyValue( IVariable *fromVar )
|
||||
{
|
||||
assert(fromVar);
|
||||
T val;
|
||||
fromVar->Get(val);
|
||||
SetValue(val);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Copy Constructor.
|
||||
CVariable( const CVariable<T> &var ) : CVariableBase(var)
|
||||
{
|
||||
m_value = var.m_value;
|
||||
m_valueMin = var.m_valueMin;
|
||||
m_valueMax = var.m_valueMax;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class P>
|
||||
void SetValue( const P &value )
|
||||
{
|
||||
T newValue;
|
||||
var_type::type_convertor<P,T> convertor;
|
||||
convertor( value,newValue );
|
||||
|
||||
// compare old and new values.
|
||||
if (!var_type::compare(m_value,newValue))
|
||||
{
|
||||
m_value = newValue;
|
||||
// If have wired variables or OnSet callback, process them.
|
||||
// Call on set callback.
|
||||
for (OnSetCallbackList::iterator it = m_onSetFuncs.begin(); it != m_onSetFuncs.end(); ++it)
|
||||
{
|
||||
// Call on set callback.
|
||||
(*it)(this);
|
||||
}
|
||||
// Send value to wired variable.
|
||||
for (WiredList::iterator it = m_wiredVars.begin(); it != m_wiredVars.end(); ++it)
|
||||
{
|
||||
// Set current value on each wired variable.
|
||||
(*it)->Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class P>
|
||||
void GetValue( P &value ) const
|
||||
{
|
||||
var_type::type_convertor<T,P> convertor;
|
||||
convertor( m_value,value );
|
||||
}
|
||||
|
||||
protected:
|
||||
T m_value;
|
||||
|
||||
// Min/Max value.
|
||||
float m_valueMin;
|
||||
float m_valueMax;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Selection list shown in combo box, for enumerated variable.
|
||||
struct IVarEnumList : public CRefCountBase
|
||||
{
|
||||
//! Get the number of entries in enumeration.
|
||||
virtual int GetItemsCount() = 0;
|
||||
//! Get the name of specified value in enumeration.
|
||||
virtual const CString& GetItemName( int index ) = 0;
|
||||
//! Set the value of variable to the value of entry with specified name.
|
||||
virtual void SetVariableValue( IVariable *pVar,const CString &name ) = 0;
|
||||
//! Gets the name of entry which have same value as variable.
|
||||
virtual CString GetNameFromVariableValue( IVariable *pVar ) = 0;
|
||||
};
|
||||
typedef TSmartPtr<IVarEnumList> IVarEnumListPtr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Selection list shown in combo box, for enumerated variable.
|
||||
template <class T>
|
||||
class CVarEnumList : public IVarEnumList
|
||||
{
|
||||
public:
|
||||
struct Item {
|
||||
CString name;
|
||||
T value;
|
||||
};
|
||||
int GetItemsCount() { return m_items.size(); }
|
||||
const CString& GetItemName( int index )
|
||||
{
|
||||
assert( index >= 0 && index < m_items.size() );
|
||||
return m_items[index].name;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetVariableValue( IVariable *pVar,const CString &name )
|
||||
{
|
||||
assert(pVar);
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
if (name == m_items[i].name)
|
||||
{
|
||||
pVar->Set( m_items[i].value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CString GetNameFromVariableValue( IVariable *pVar )
|
||||
{
|
||||
assert(pVar);
|
||||
for (int i = 0; i < m_items.size(); i++)
|
||||
{
|
||||
T value;
|
||||
pVar->Get(value);
|
||||
if (value == m_items[i].value)
|
||||
{
|
||||
return m_items[i].name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
//! Add new item to the selection.
|
||||
void AddItem( const CString &name,const T &value )
|
||||
{
|
||||
Item item;
|
||||
item.name = name;
|
||||
item.value = value;
|
||||
m_items.push_back(item);
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<Item> m_items;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// CVariableEnum is the same as CVariable but it display enumerated values in UI
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class CVariableEnum : public CVariable<T>
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVariableEnum() {};
|
||||
|
||||
//! Cast to holded type.
|
||||
operator T() const { return m_value; }
|
||||
//! Assign operator for variable.
|
||||
void operator=( const T& value ) { SetValue(value); }
|
||||
|
||||
//! Add new item to the enumeration.
|
||||
void AddEnumItem( const CString &name,const T &value )
|
||||
{
|
||||
if (!m_enum)
|
||||
m_enum = new CVarEnumList<T>;
|
||||
m_enum->Add( name,value );
|
||||
};
|
||||
void SetEnumList( CVarEnumList<T> *enumList )
|
||||
{
|
||||
m_enum = enumList;
|
||||
}
|
||||
IVarEnumList* GetEnumList() const
|
||||
{
|
||||
return m_enum;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IVariable* Clone( bool bRecursive ) const
|
||||
{
|
||||
CVariableEnum<T> *var = new CVariableEnum<T>(*this);
|
||||
return var;
|
||||
}
|
||||
protected:
|
||||
// Copy Constructor.
|
||||
CVariableEnum( const CVariableEnum<T> &var ) : CVariable<T>(var)
|
||||
{
|
||||
m_enum = var.m_enum;
|
||||
}
|
||||
private:
|
||||
TSmartPtr<CVarEnumList<T> > m_enum;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CVarBlock : public CRefCountBase
|
||||
{
|
||||
public:
|
||||
// Dtor.
|
||||
~CVarBlock();
|
||||
//! Add parameter to block.
|
||||
void AddVariable( IVariable *var );
|
||||
|
||||
//! Find variable by name.
|
||||
IVariable* FindVariable( const char *name,bool bRecursive=true ) const;
|
||||
|
||||
//! Return true if vriable block is empty (Does not have any vars).
|
||||
bool IsEmpty() const { return m_vars.empty(); }
|
||||
//! Returns number of variables in block.
|
||||
int GetVarsCount() const { return m_vars.size(); }
|
||||
//! Get pointer to stored variable by index.
|
||||
IVariable* GetVariable( int index )
|
||||
{
|
||||
assert( index >= 0 && index < m_vars.size() );
|
||||
return m_vars[index];
|
||||
}
|
||||
// Clear all vars from VarBlock.
|
||||
void Clear() { m_vars.clear(); };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Clone var block.
|
||||
CVarBlock* Clone( bool bRecursive ) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Copy variable values from specifed var block.
|
||||
//! Do not create new variables, only copy values of existing ones.
|
||||
//! Should only be used to copy identical var blocks (eg. not Array type var copied to String type var)
|
||||
//! @param fromVarBlock Source variable block that contain copied values, must be identical to this var block.
|
||||
void CopyValues( CVarBlock *fromVarBlock );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Copy variable values from specifed var block.
|
||||
//! Do not create new variables, only copy values of existing ones.
|
||||
//! Can be used to copy slighly different var blocks, matching performed by variable name.
|
||||
//! @param fromVarBlock Source variable block that contain copied values.
|
||||
void CopyValuesByName( CVarBlock *fromVarBlock );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Wire/Unwire other variable blocks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Wire to other variable block.
|
||||
//! Only equialent VarBlocks can be wired (same number of variables with same type).
|
||||
//! Recursive wiring of array variables is supported.
|
||||
void Wire( CVarBlock *toVarBlock );
|
||||
//! Unwire var block.
|
||||
void Unwire( CVarBlock *varBlock );
|
||||
|
||||
//! Add this callback to every variable in block (recursively).
|
||||
void AddOnSetCallback( IVariable::OnSetCallback func );
|
||||
//! Remove this callback from every variable in block (recursively).
|
||||
void RemoveOnSetCallback( IVariable::OnSetCallback func );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Serialize( XmlNodeRef &vbNode,bool load );
|
||||
|
||||
void ReserveNumVariables( int numVars );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Gather resources in this variable block.
|
||||
virtual void GatherUsedResources( CUsedResources &resources );
|
||||
|
||||
protected:
|
||||
IVariable* FindChildVar( const char *name,IVariable *pParentVar ) const;
|
||||
void SetCallbackToVar( IVariable::OnSetCallback func,IVariable *pVar,bool bAdd );
|
||||
void WireVar( IVariable *src,IVariable *trg,bool bWire );
|
||||
void GatherUsedResourcesInVar( IVariable *pVar,CUsedResources &resources );
|
||||
|
||||
typedef std::vector<IVariablePtr> Variables;
|
||||
Variables m_vars;
|
||||
};
|
||||
|
||||
typedef TSmartPtr<CVarBlock> CVarBlockPtr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CVarObject : public CRefCountBase
|
||||
{
|
||||
public:
|
||||
typedef IVariable::OnSetCallback VarOnSetCallback;
|
||||
|
||||
CVarObject();
|
||||
~CVarObject();
|
||||
|
||||
void Serialize( XmlNodeRef node,bool load );
|
||||
CVarBlock* GetVarBlock() const { return m_vars; };
|
||||
|
||||
void AddVariable( CVariableBase &var,const CString &varName,VarOnSetCallback cb=NULL,unsigned char dataType=IVariable::DT_SIMPLE );
|
||||
void AddVariable( CVariableBase &var,const CString &varName,const CString &varHumanName,VarOnSetCallback cb=NULL,unsigned char dataType=IVariable::DT_SIMPLE );
|
||||
void ReserveNumVariables( int numVars );
|
||||
|
||||
protected:
|
||||
//! Copy values of variables from other VarObject.
|
||||
//! Source object must be of same type.
|
||||
void CopyVariableValues( CVarObject *sourceObject );
|
||||
|
||||
private:
|
||||
CVarBlockPtr m_vars;
|
||||
};
|
||||
|
||||
#endif // __Variable_h__
|
||||
96
Editor/Util/XmlArchive.cpp
Normal file
96
Editor/Util/XmlArchive.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: XmlArchive.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/1/2002 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "XmlArchive.h"
|
||||
#include "PakFile.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CXmlArchive
|
||||
bool CXmlArchive::Load( const CString &file )
|
||||
{
|
||||
bLoading = true;
|
||||
|
||||
CFile cFile;
|
||||
if (!cFile.Open( file, CFile::modeRead))
|
||||
{
|
||||
CLogFile::FormatLine("Warning: Loading of %s failed",(const char*)file );
|
||||
return false;
|
||||
}
|
||||
CArchive ar(&cFile, CArchive::load);
|
||||
|
||||
CString str;
|
||||
|
||||
ar >> str;
|
||||
pNamedData->Serialize( ar );
|
||||
|
||||
XmlParser parser;
|
||||
root = parser.parseBuffer( str );
|
||||
if (!root)
|
||||
{
|
||||
CLogFile::FormatLine("Warning: Loading of %s failed",(const char*)file );
|
||||
}
|
||||
|
||||
if (root)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlArchive::Save( const CString &file )
|
||||
{
|
||||
bLoading = false;
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
CFile cFile;
|
||||
// Open the file for writing, create it if needed
|
||||
if (!cFile.Open(file, CFile::modeCreate | CFile::modeWrite))
|
||||
{
|
||||
CLogFile::FormatLine("Warning: Saving of %s failed",(const char*)file );
|
||||
return;
|
||||
}
|
||||
// Create the archive object
|
||||
CArchive ar(&cFile, CArchive::store);
|
||||
|
||||
CString xml = root->getXML();
|
||||
ar << xml;
|
||||
pNamedData->Serialize( ar );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlArchive::SaveToPak( const CString &levelPath,CPakFile &pakFile )
|
||||
{
|
||||
CString xml = root->getXML();
|
||||
// Save xml file.
|
||||
CString xmlFilename = "Level.editor_xml";
|
||||
pakFile.UpdateFile( xmlFilename,(void*)((const char*)xml),xml.GetLength() );
|
||||
|
||||
pNamedData->Save( pakFile );
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlArchive::LoadFromPak( const CString &levelPath,CPakFile &pakFile )
|
||||
{
|
||||
CString xmlFilename = levelPath + "Level.editor_xml";
|
||||
XmlParser parser;
|
||||
root = parser.parse( xmlFilename );
|
||||
if (!root)
|
||||
return false;
|
||||
|
||||
pNamedData->Load( levelPath,pakFile );
|
||||
return true;
|
||||
}
|
||||
72
Editor/Util/XmlArchive.h
Normal file
72
Editor/Util/XmlArchive.h
Normal file
@@ -0,0 +1,72 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: XmlArchive.h
|
||||
// Version: v1.00
|
||||
// Created: 30/1/2002 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Stores XML in MFC archive.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __XmlArchive_h__
|
||||
#define __XmlArchive_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "NamedData.h"
|
||||
|
||||
class CPakFile;
|
||||
/*!
|
||||
* CXmlArcive used to stores XML in MFC archive.
|
||||
*/
|
||||
class CXmlArchive
|
||||
{
|
||||
public:
|
||||
XmlNodeRef root;
|
||||
CNamedData* pNamedData;
|
||||
bool bLoading;
|
||||
bool bOwnNamedData;
|
||||
|
||||
CXmlArchive() {
|
||||
bLoading = false;
|
||||
bOwnNamedData= true;
|
||||
pNamedData = new CNamedData;
|
||||
};
|
||||
explicit CXmlArchive( const CString &xmlRoot ) {
|
||||
bLoading = false;
|
||||
bOwnNamedData= true;
|
||||
pNamedData = new CNamedData;
|
||||
root = new CXmlNode(xmlRoot);
|
||||
};
|
||||
~CXmlArchive() {
|
||||
if (bOwnNamedData)
|
||||
delete pNamedData;
|
||||
};
|
||||
CXmlArchive( const CXmlArchive &ar ) { *this = ar; }
|
||||
CXmlArchive& operator=( const CXmlArchive &ar )
|
||||
{
|
||||
root = ar.root;
|
||||
pNamedData = ar.pNamedData;
|
||||
bLoading = ar.bLoading;
|
||||
bOwnNamedData = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Load( const CString &file );
|
||||
void Save( const CString &file );
|
||||
|
||||
//! Save XML Archive to pak file.
|
||||
//! @return true if saved.
|
||||
bool SaveToPak( const CString &levelPath,CPakFile &pakFile );
|
||||
bool LoadFromPak( const CString &levelPath,CPakFile &pakFile );
|
||||
};
|
||||
|
||||
|
||||
#endif // __XmlArchive_h__
|
||||
204
Editor/Util/XmlTemplate.cpp
Normal file
204
Editor/Util/XmlTemplate.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: XmlTemplate.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: CXmlTemplate implementation.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <StdAfx.h>
|
||||
#include "XmlTemplate.h"
|
||||
#include "FileEnum.h"
|
||||
|
||||
#include <io.h>
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CXmlTemplate implementation
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::GetValues( XmlNodeRef &node, const XmlNodeRef &fromNode )
|
||||
{
|
||||
assert( node != 0 && fromNode != 0 );
|
||||
|
||||
for (int i = 0; i < node->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef prop = node->getChild(i);
|
||||
|
||||
if (prop->getChildCount() == 0)
|
||||
{
|
||||
CString value;
|
||||
if (fromNode->getAttr( prop->getTag(),value ))
|
||||
{
|
||||
prop->setAttr( "Value",value );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Have childs.
|
||||
XmlNodeRef fromNodeChild = fromNode->findChild(prop->getTag());
|
||||
if (fromNodeChild)
|
||||
{
|
||||
CXmlTemplate::GetValues( prop,fromNodeChild );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::SetValues( const XmlNodeRef &node,XmlNodeRef &toNode )
|
||||
{
|
||||
assert( node != 0 && toNode != 0 );
|
||||
|
||||
toNode->removeAllAttributes();
|
||||
toNode->removeAllChilds();
|
||||
for (int i = 0; i < node->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef prop = node->getChild(i);
|
||||
if (prop)
|
||||
{
|
||||
if (prop->getChildCount() > 0)
|
||||
{
|
||||
XmlNodeRef childToNode = toNode->newChild(prop->getTag());
|
||||
if (childToNode)
|
||||
CXmlTemplate::SetValues( prop,childToNode );
|
||||
}
|
||||
else
|
||||
{
|
||||
CString value;
|
||||
prop->getAttr( "Value",value );
|
||||
toNode->setAttr( prop->getTag(),value );
|
||||
}
|
||||
}else
|
||||
TRACE("NULL returned from node->GetChild()");
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlTemplate::SetValues( const XmlNodeRef &node,XmlNodeRef &toNode,const XmlNodeRef &modifiedNode )
|
||||
{
|
||||
assert( node != 0 && toNode != 0 && modifiedNode != 0 );
|
||||
|
||||
for (int i = 0; i < node->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef prop = node->getChild(i);
|
||||
if (prop)
|
||||
{
|
||||
if (prop->getChildCount() > 0)
|
||||
{
|
||||
XmlNodeRef childToNode = toNode->findChild(prop->getTag());
|
||||
if (childToNode)
|
||||
{
|
||||
if (CXmlTemplate::SetValues( prop,childToNode,modifiedNode ))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (prop == modifiedNode)
|
||||
{
|
||||
CString value;
|
||||
prop->getAttr( "Value",value );
|
||||
toNode->setAttr( prop->getTag(),value );
|
||||
return true;
|
||||
}
|
||||
}else
|
||||
TRACE("NULL returned from node->GetChild()");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::AddParam( XmlNodeRef &templ,const char *sName,bool value )
|
||||
{
|
||||
XmlNodeRef param = templ->newChild(sName);
|
||||
param->setAttr( "type","Bool" );
|
||||
param->setAttr( "value",value );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::AddParam( XmlNodeRef &templ,const char *sName,int value,int min,int max )
|
||||
{
|
||||
XmlNodeRef param = templ->newChild(sName);
|
||||
param->setAttr( "type","Int" );
|
||||
param->setAttr( "value",value );
|
||||
param->setAttr( "min",min );
|
||||
param->setAttr( "max",max );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::AddParam( XmlNodeRef &templ,const char *sName,float value,float min,float max )
|
||||
{
|
||||
XmlNodeRef param = templ->newChild(sName);
|
||||
param->setAttr( "type","Float" );
|
||||
param->setAttr( "value",value );
|
||||
param->setAttr( "min",min );
|
||||
param->setAttr( "max",max );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplate::AddParam( XmlNodeRef &templ,const char *sName,const char *sValue )
|
||||
{
|
||||
XmlNodeRef param = templ->newChild(sName);
|
||||
param->setAttr( "type","String" );
|
||||
param->setAttr( "value",sValue );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CXmlTemplateRegistry implementation
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CXmlTemplateRegistry::CXmlTemplateRegistry()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplateRegistry::LoadTemplates( const CString &path )
|
||||
{
|
||||
XmlParser parser;
|
||||
|
||||
CString dir = Path::AddBackslash(path);
|
||||
|
||||
std::vector<CFileUtil::FileDesc> files;
|
||||
CFileUtil::ScanDirectory( dir,"*.xml",files,false );
|
||||
|
||||
for (int k = 0; k < files.size(); k++)
|
||||
{
|
||||
XmlNodeRef child;
|
||||
// Construct the full filepath of the current file
|
||||
XmlNodeRef node = parser.parse( dir + files[k].filename );
|
||||
if (node != 0 && node->isTag("Templates"))
|
||||
{
|
||||
CString name;
|
||||
for (int i = 0; i < node->getChildCount(); i++)
|
||||
{
|
||||
child = node->getChild(i);
|
||||
AddTemplate( child->getTag(),child );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CXmlTemplateRegistry::AddTemplate( const CString &name,XmlNodeRef &tmpl )
|
||||
{
|
||||
m_templates[name] = tmpl;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
XmlNodeRef CXmlTemplateRegistry::FindTemplate( const CString &name )
|
||||
{
|
||||
XmlNodeRef node;
|
||||
if (m_templates.Find( name,node )) {
|
||||
return node;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
64
Editor/Util/XmlTemplate.h
Normal file
64
Editor/Util/XmlTemplate.h
Normal file
@@ -0,0 +1,64 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: XmlTemplate.h
|
||||
// Version: v1.00
|
||||
// Created: 28/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: CXmlTemplate declaration.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __XmlTemplate_h__
|
||||
#define __XmlTemplate_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* CXmlTemplate is XML base template of parameters.
|
||||
*
|
||||
*/
|
||||
class CXmlTemplate
|
||||
{
|
||||
public:
|
||||
//! Scans properties of XML template,
|
||||
//! for each property try to find corresponding attribute in specified XML node, and copy
|
||||
//! value to Value attribute of template.
|
||||
static void GetValues( XmlNodeRef &templateNode,const XmlNodeRef &fromNode );
|
||||
|
||||
//! Scans properties of XML template, fetch Value attribute of each and put as Attribute in
|
||||
//! specified XML node.
|
||||
static void SetValues( const XmlNodeRef &templateNode,XmlNodeRef &toNode );
|
||||
static bool SetValues( const XmlNodeRef &templateNode,XmlNodeRef &toNode,const XmlNodeRef &modifiedNode );
|
||||
|
||||
//! Add parameter to template.
|
||||
static void AddParam( XmlNodeRef &templ,const char *paramName,bool value );
|
||||
static void AddParam( XmlNodeRef &templ,const char *paramName,int value,int min=0,int max=10000 );
|
||||
static void AddParam( XmlNodeRef &templ,const char *paramName,float value,float min=-10000,float max=10000 );
|
||||
static void AddParam( XmlNodeRef &templ,const char *paramName,const char *sValue );
|
||||
};
|
||||
|
||||
/*!
|
||||
* CXmlTemplateRegistry is a collection of all registred templates.
|
||||
*/
|
||||
class CXmlTemplateRegistry
|
||||
{
|
||||
public:
|
||||
CXmlTemplateRegistry();
|
||||
|
||||
void LoadTemplates( const CString &path );
|
||||
void AddTemplate( const CString &name,XmlNodeRef &tmpl );
|
||||
|
||||
XmlNodeRef FindTemplate( const CString &name );
|
||||
|
||||
private:
|
||||
StdMap<CString,XmlNodeRef> m_templates;
|
||||
};
|
||||
|
||||
#endif // __XmlTemplate_h__
|
||||
198
Editor/Util/bitarray.h
Normal file
198
Editor/Util/bitarray.h
Normal file
@@ -0,0 +1,198 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bitarray.h
|
||||
// Version: v1.00
|
||||
// Created: 29/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: Array of bits.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __bitarray_h__
|
||||
#define __bitarray_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
class CBitArray
|
||||
{
|
||||
public:
|
||||
CBitArray() { m_base = NULL; bits = NULL; m_size = 0; };
|
||||
CBitArray( int c ) { reserve( c ); };
|
||||
~CBitArray() { if (m_base) free(m_base); };
|
||||
|
||||
void reserve( int c ) {
|
||||
int newSize = ((c+63)&(~63)) >> 5;
|
||||
if (newSize > m_size)
|
||||
alloc( newSize );
|
||||
}
|
||||
void reserve( const CBitArray &b ) {
|
||||
alloc( b.m_size );
|
||||
}
|
||||
|
||||
void copy( const CBitArray &b ) {
|
||||
if (m_size != b.m_size) {
|
||||
alloc( b.m_size );
|
||||
}
|
||||
memcpy( bits,b.bits,m_size*sizeof(uint) );
|
||||
};
|
||||
void set() {
|
||||
memset( bits,0xFFFFFFFF,m_size*sizeof(uint) ); // Set all bits.
|
||||
}
|
||||
void set_num( int numBits ) {
|
||||
int num = (numBits >> 3) + 1;
|
||||
if (num > (m_size*sizeof(uint))) num = m_size*sizeof(uint);
|
||||
memset( bits,0xFFFFFFFF,num ); // Reset num bits.
|
||||
}
|
||||
void clear() {
|
||||
memset( bits,0,m_size*sizeof(uint) ); // Reset all bits.
|
||||
}
|
||||
void clear_num( int numBits ) {
|
||||
int num = (numBits >> 3) + 1;
|
||||
if (num > (m_size*sizeof(uint))) num = m_size*sizeof(uint);
|
||||
memset( bits,0,num ); // Reset num bits.
|
||||
}
|
||||
void set( int pos ) {
|
||||
bits[index(pos)] |= shift(pos);
|
||||
}
|
||||
void clear( int pos ) {
|
||||
bits[index(pos)] &= ~shift(pos);
|
||||
}
|
||||
void flip( int pos ) {
|
||||
//bits[index(pos)] ^= ~shift(pos);
|
||||
}
|
||||
int size() const { return m_size; };
|
||||
|
||||
bool valid() { return m_size > 0; };
|
||||
|
||||
int count() const {
|
||||
int c = 0;
|
||||
for (int i = 0; i < m_size; i++) {
|
||||
uint v = bits[i];
|
||||
for (int j = 0; j < 32; j++) {
|
||||
if (v & (1 << (j & 0x1F))) c++; // if bit set increase bit count.
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
int operator[]( int pos ) {
|
||||
return bits[index(pos)] & shift(pos);
|
||||
}
|
||||
bool checkByte( int pos ) { return reinterpret_cast<char*>(bits)[pos] != 0; };
|
||||
|
||||
CBitArray& operator =( const CBitArray &b ) {
|
||||
copy( b );
|
||||
return *this;
|
||||
}
|
||||
|
||||
void compress( CBitArray &b ) {
|
||||
int i,countz,compsize,bsize;
|
||||
char *out;
|
||||
char *in;
|
||||
|
||||
bsize = m_size*4;
|
||||
compsize = 0;
|
||||
in = (char*)bits;
|
||||
for (i = 0; i < bsize; i++) {
|
||||
compsize++;
|
||||
if (in[i] == 0) {
|
||||
countz = 1;
|
||||
while (++i < bsize) {
|
||||
if (in[i] == 0 && countz != 255) countz++; else break;
|
||||
}
|
||||
i--;
|
||||
compsize++;
|
||||
}
|
||||
}
|
||||
b.reserve( (compsize+1)<<3 );
|
||||
out = (char*)b.bits;
|
||||
in = (char*)bits;
|
||||
*out++ = bsize;
|
||||
for (i = 0; i < bsize; i++) {
|
||||
*out++ = in[i];
|
||||
if (in[i] == 0) {
|
||||
countz = 1;
|
||||
while (++i < bsize) {
|
||||
if (in[i] == 0 && countz != 255) countz++; else break;
|
||||
}
|
||||
i--;
|
||||
*out++ = countz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decompress( CBitArray &b ) {
|
||||
int raw,decompressed,c;
|
||||
char *out,*in;
|
||||
|
||||
in = (char*)bits;
|
||||
out = (char*)b.bits;
|
||||
decompressed = 0;
|
||||
raw = *in++;
|
||||
while (decompressed < raw) {
|
||||
if (*in != 0)
|
||||
{
|
||||
*out++ = *in++;
|
||||
decompressed++;
|
||||
} else {
|
||||
in++;
|
||||
c = *in++;
|
||||
decompressed += c;
|
||||
while (c) { *out++ = 0; c--; };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copyFromMem( const char *src,int size ) {
|
||||
alloc( size );
|
||||
memcpy( bits,src,size );
|
||||
}
|
||||
int copyToMem( char *trg ) {
|
||||
memcpy( trg,bits,m_size );
|
||||
return m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
void *m_base;
|
||||
uint *bits;
|
||||
int m_size;
|
||||
|
||||
void alloc( int s ) {
|
||||
if (m_base) free(m_base);
|
||||
m_size = s;
|
||||
m_base = (char*)malloc(m_size*sizeof(uint)+32);
|
||||
bits = (uint*)( ((UINT_PTR)m_base + 31) & (~31) ); // align by 32.
|
||||
}
|
||||
unsigned int shift( int pos ) {
|
||||
return (1 << (pos&0x1F));
|
||||
}
|
||||
unsigned int index( int pos ) {
|
||||
return pos >> 5;
|
||||
}
|
||||
|
||||
friend int concatBitarray( CBitArray &b1,CBitArray &b2,CBitArray &test,CBitArray &res );
|
||||
};
|
||||
|
||||
inline int concatBitarray( CBitArray &b1,CBitArray &b2,CBitArray &test,CBitArray &res )
|
||||
{
|
||||
unsigned int b,any;
|
||||
any = 0;
|
||||
for (int i = 0; i < b1.size(); i++) {
|
||||
b = b1.bits[i] & b2.bits[i];
|
||||
any |= (b & (~test.bits[i])); // test if any different from test(i) bit set.
|
||||
res.bits[i] = b;
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
#endif // __bitarray_h__
|
||||
76
Editor/Util/crc32.cpp
Normal file
76
Editor/Util/crc32.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "stdafx.h"
|
||||
#include "crc32.h"
|
||||
|
||||
Crc32Gen::Crc32Gen()
|
||||
{
|
||||
init_CRC32_Table();
|
||||
}
|
||||
|
||||
// Call this function only once to initialize the CRC table.
|
||||
void Crc32Gen::init_CRC32_Table()
|
||||
{
|
||||
// This is the official polynomial used by CRC-32
|
||||
// in PKZip, WinZip and Ethernet.
|
||||
unsigned int ulPolynomial = 0x04c11db7;
|
||||
|
||||
// 256 values representing ASCII character codes.
|
||||
for(int i = 0; i <= 0xFF; i++)
|
||||
{
|
||||
crc32_table[i] = reflect(i, 8) << 24;
|
||||
for (int j = 0; j < 8; j++)
|
||||
crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (1 << 31) ? ulPolynomial : 0);
|
||||
crc32_table[i] = reflect(crc32_table[i], 32);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Crc32Gen::reflect(unsigned int ref, char ch)
|
||||
{// Used only by Init_CRC32_Table().
|
||||
unsigned int value = 0;
|
||||
|
||||
// Swap bit 0 for bit 7
|
||||
// bit 1 for bit 6, etc.
|
||||
for(int i = 1; i < (ch + 1); i++)
|
||||
{
|
||||
if(ref & 1)
|
||||
value |= 1 << (ch - i);
|
||||
ref >>= 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned int Crc32Gen::get_CRC32( const char *data, int size, unsigned int ulCRC )
|
||||
{// Pass a text string to this function and it will return the CRC.
|
||||
|
||||
// Once the lookup table has been filled in by the two functions above,
|
||||
// this function creates all CRCs using only the lookup table.
|
||||
|
||||
// Be sure to use unsigned variables, because negative values introduce high bits where zero bits are required.
|
||||
|
||||
// Start out with all bits set high.
|
||||
int len;
|
||||
unsigned char* buffer;
|
||||
|
||||
// Get the length.
|
||||
len = size;
|
||||
|
||||
// Save the text in the buffer.
|
||||
buffer = (unsigned char*)data;
|
||||
// Perform the algorithm on each character in the string, using the lookup table values.
|
||||
|
||||
while(len--)
|
||||
ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ *buffer++];
|
||||
// Exclusive OR the result with the beginning value.
|
||||
return ulCRC ^ 0xffffffff;
|
||||
}
|
||||
|
||||
unsigned int Crc32Gen::GetCRC32( const char *text )
|
||||
{
|
||||
int len = strlen(text);
|
||||
return GetCRC32( text,len,0xffffffff );
|
||||
}
|
||||
|
||||
unsigned int Crc32Gen::GetCRC32( const char *data, int size, unsigned int ulCRC )
|
||||
{
|
||||
static Crc32Gen stdCrc32Generator;
|
||||
return stdCrc32Generator.get_CRC32( data,size,ulCRC );
|
||||
}
|
||||
38
Editor/Util/crc32.h
Normal file
38
Editor/Util/crc32.h
Normal file
@@ -0,0 +1,38 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: crc32.h
|
||||
// Version: v1.00
|
||||
// Created: 31/10/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __crc32_h__
|
||||
#define __crc32_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class Crc32Gen {
|
||||
public:
|
||||
Crc32Gen();
|
||||
//! Creates a CRC from a text string
|
||||
static unsigned int GetCRC32( const char *text );
|
||||
static unsigned int GetCRC32( const char *data,int size,unsigned int ulCRC );
|
||||
|
||||
protected:
|
||||
unsigned int crc32_table[256]; //!< Lookup table array
|
||||
void init_CRC32_Table(); //!< Builds lookup table array
|
||||
unsigned int reflect( unsigned int ref, char ch); //!< Reflects CRC bits in the lookup table
|
||||
unsigned int get_CRC32( const char *data,int size,unsigned int ulCRC );
|
||||
};
|
||||
|
||||
#endif // __crc32_h__
|
||||
103
Editor/Util/dds.h
Normal file
103
Editor/Util/dds.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// dds.h
|
||||
//
|
||||
// This header defines constants and structures that are useful when parsing
|
||||
// DDS files. DDS files were originally designed to use several structures
|
||||
// and constants that are native to DirectDraw and are defined in ddraw.h,
|
||||
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
|
||||
// (compatible) constants and structures so that one can use DDS files
|
||||
// without needing to include ddraw.h.
|
||||
|
||||
#ifndef _DDS_H_
|
||||
#define _DDS_H_
|
||||
|
||||
struct DDS_PIXELFORMAT
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwFourCC;
|
||||
DWORD dwRGBBitCount;
|
||||
DWORD dwRBitMask;
|
||||
DWORD dwGBitMask;
|
||||
DWORD dwBBitMask;
|
||||
DWORD dwABitMask;
|
||||
};
|
||||
|
||||
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
|
||||
#define DDS_RGB 0x00000040 // DDPF_RGB
|
||||
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT1 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT2 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT3 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
|
||||
|
||||
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
|
||||
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
|
||||
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
|
||||
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
|
||||
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
|
||||
|
||||
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
|
||||
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
|
||||
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
|
||||
|
||||
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
|
||||
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
|
||||
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
|
||||
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
|
||||
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
|
||||
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
|
||||
|
||||
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
|
||||
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
|
||||
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
|
||||
|
||||
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
|
||||
|
||||
#define DDS_RESF1_NORMALMAP 0x01000000
|
||||
#define DDS_RESF1_DSDT 0x02000000
|
||||
|
||||
|
||||
struct DDS_HEADER
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwHeaderFlags;
|
||||
DWORD dwHeight;
|
||||
DWORD dwWidth;
|
||||
DWORD dwPitchOrLinearSize;
|
||||
DWORD dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags
|
||||
DWORD dwMipMapCount;
|
||||
DWORD dwReserved1[11];
|
||||
DDS_PIXELFORMAT ddspf;
|
||||
DWORD dwSurfaceFlags;
|
||||
DWORD dwCubemapFlags;
|
||||
DWORD dwReserved2[3];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
78
Editor/Util/dxtlib.h
Normal file
78
Editor/Util/dxtlib.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*********************************************************************NVMH2****
|
||||
Path: C:\Dev\devrel\Nv_sdk_4\Dx8_private\PhotoShop\dxtlib
|
||||
File: dxtlib.h
|
||||
|
||||
Copyright (C) 1999, 2000 NVIDIA Corporation
|
||||
This file is provided without support, instruction, or implied warranty of any
|
||||
kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is
|
||||
not liable under any circumstances for any damages or loss whatsoever arising
|
||||
from the use or inability to use this file or items derived from it.
|
||||
|
||||
Comments:
|
||||
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef HRESULT (*MIPcallback)(void * data, int miplevel, DWORD size);
|
||||
// call back
|
||||
// pointer to data
|
||||
// mip level
|
||||
// size of chunk
|
||||
|
||||
|
||||
/*
|
||||
Compresses an image with a user supplied callback with the data for each MIP level created
|
||||
Only supports input of RGB 24 or ARGB 32 bpp
|
||||
*/
|
||||
HRESULT nvDXTcompress(unsigned char * raw_data, // pointer to data (24 or 32 bit)
|
||||
unsigned long w, // width in texels
|
||||
unsigned long h, // height in texels
|
||||
DWORD TextureFormat, // list below
|
||||
bool bGenMipMaps, // auto gen MIP maps
|
||||
bool bDither,
|
||||
DWORD depth, // 3 or 4
|
||||
MIPcallback callback = 0); // callback for generated levels
|
||||
// if callback is == 0 (or not specified), then WriteDTXnFile is called with all file info
|
||||
//
|
||||
// You must write the routines (or provide stubs)
|
||||
// void WriteDTXnFile(count, buffer);
|
||||
// void ReadDTXnFile(count, buffer);
|
||||
//
|
||||
//
|
||||
/* returns
|
||||
w width
|
||||
h height
|
||||
depth ( 3 or 4)
|
||||
total_width
|
||||
rowBytes - pitch
|
||||
|
||||
*/
|
||||
unsigned char * nvDXTdecompress(int & w, int & h, int & depth, int & total_width, int & rowBytes);
|
||||
|
||||
|
||||
// see examples
|
||||
|
||||
|
||||
void WriteDTXnFile(DWORD count, void * buffer);
|
||||
void ReadDTXnFile(DWORD count, void * buffer);
|
||||
|
||||
|
||||
// TextureFormat
|
||||
#define TF_DXT1 10
|
||||
#define TF_DXT1_1BitAlpha 11
|
||||
#define TF_DXT3 12
|
||||
#define TF_DXT5 13
|
||||
#define TF_RGB4444 14
|
||||
#define TF_RGB1555 15
|
||||
#define TF_RGB565 16
|
||||
#define TF_RGB8888 17
|
||||
|
||||
|
||||
#define DXTERR_INPUT_POINTER_ZERO -1
|
||||
#define DXTERR_DEPTH_IS_NOT_3_OR_4 -2
|
||||
#define DXTERR_NON_POWER_2 -3
|
||||
|
||||
112
Editor/Util/fastlib.h
Normal file
112
Editor/Util/fastlib.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef __FAST_CODE_H_INCLUDED__
|
||||
#define __FAST_CODE_H_INCLUDED__
|
||||
|
||||
// Needed to control floating-point pecision
|
||||
#include <float.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Casting - Taken from the www.gamedev.net forums and www.nvidia.com
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define __clamp(v, _min, _max) ( (v>_max) ? (_max) : ( (v<_min) ? (_min) : (v) ) )
|
||||
|
||||
#ifdef WIN64
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Round a floating point number to an integer. Note that (int + .5)
|
||||
// is rounded to (int + 1).
|
||||
__forceinline int RoundFloatToInt (float f)
|
||||
{
|
||||
return (int)(f+0.5f);
|
||||
}
|
||||
|
||||
// Doesn't take the pointer, is a bit faster
|
||||
__forceinline int __stdcall FloatToIntRet(float x)
|
||||
{
|
||||
return (int)(x+0.5f);
|
||||
}
|
||||
|
||||
// Casting floats to unsigned chars is also very expensive, just
|
||||
// NEVER cast with (unsigned char)
|
||||
__forceinline BYTE __stdcall FloatToByte(float x)
|
||||
{
|
||||
float t = x + (float) 0xC00000;
|
||||
return * (BYTE *) &t;
|
||||
}
|
||||
|
||||
// Fast floor() for (x >= 0) && (x < 2^31). MUCH faster than the normal
|
||||
// floor()
|
||||
__forceinline unsigned int __stdcall ifloor(float x)
|
||||
{
|
||||
DWORD e = (0x7F + 31) - ((* (DWORD *) &x & 0x7F800000) >> 23);
|
||||
DWORD m = 0x80000000 | (* (DWORD *) &x << 8);
|
||||
return (m >> e) & -(e < 32);
|
||||
}
|
||||
|
||||
// Converts to integer equal to or less than, asm version
|
||||
__forceinline int ftoi(float f)
|
||||
{
|
||||
return (int)(f);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#else //WIN64
|
||||
|
||||
// Round a floating point number to an integer. Note that (int + .5)
|
||||
// is rounded to (int + 1).
|
||||
__forceinline int RoundFloatToInt (float f)
|
||||
{
|
||||
int i;
|
||||
__asm fld [f]
|
||||
__asm fistp [i]
|
||||
return i;
|
||||
}
|
||||
|
||||
// Doesn't take the pointer, is a bit faster
|
||||
__forceinline int __stdcall FloatToIntRet(float x)
|
||||
{
|
||||
int t;
|
||||
__asm fld x
|
||||
__asm fistp t
|
||||
return t;
|
||||
}
|
||||
|
||||
// Casting floats to unsigned chars is also very expensive, just
|
||||
// NEVER cast with (unsigned char)
|
||||
__forceinline BYTE __stdcall FloatToByte(float x)
|
||||
{
|
||||
float t = x + (float) 0xC00000;
|
||||
return * (BYTE *) &t;
|
||||
}
|
||||
|
||||
// Fast floor() for (x >= 0) && (x < 2^31). MUCH faster than the normal
|
||||
// floor()
|
||||
__forceinline unsigned int __stdcall ifloor(float x)
|
||||
{
|
||||
DWORD e = (0x7F + 31) - ((* (DWORD *) &x & 0x7F800000) >> 23);
|
||||
DWORD m = 0x80000000 | (* (DWORD *) &x << 8);
|
||||
return (m >> e) & -(e < 32);
|
||||
}
|
||||
|
||||
// Converts to integer equal to or less than, asm version
|
||||
__forceinline int ftoi(float f)
|
||||
{
|
||||
static float Half = 0.5;
|
||||
int i;
|
||||
__asm fld [f]
|
||||
__asm fsub [Half]
|
||||
__asm fistp [i]
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif //WIN64
|
||||
|
||||
//! Return random value in [-1,1] diaposone.
|
||||
inline float frand()
|
||||
{
|
||||
return ((float)rand()*2.0f / RAND_MAX) - 1.0f;
|
||||
}
|
||||
|
||||
#endif // __FAST_CODE_H_INCLUDED__
|
||||
1412
Editor/Util/functor.h
Normal file
1412
Editor/Util/functor.h
Normal file
File diff suppressed because it is too large
Load Diff
126
Editor/Util/smartptr.h
Normal file
126
Editor/Util/smartptr.h
Normal file
@@ -0,0 +1,126 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: smartptr.h
|
||||
// Version: v1.00
|
||||
// Created: 27/11/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __smartptr_h__
|
||||
#define __smartptr_h__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef WIN64
|
||||
|
||||
#define TSmartPtr _smart_ptr
|
||||
|
||||
#else // WIN64
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class TSmartPtr<T>.
|
||||
// Smart pointer warper class that implements reference counting on IUnknown
|
||||
// interface compatable class.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
class TSmartPtr {
|
||||
Type* p;
|
||||
public:
|
||||
TSmartPtr() : p(NULL) {}
|
||||
TSmartPtr( Type* p_ ) : p(p_) { if (p) (p)->AddRef(); }
|
||||
TSmartPtr( const TSmartPtr<Type>& p_ ) : p(p_.p) { if (p) (p)->AddRef(); } // Copy constructor.
|
||||
TSmartPtr( int Null ) : p(NULL) {}
|
||||
~TSmartPtr() { if (p) (p)->Release(); }
|
||||
|
||||
operator Type*() const { return p; }
|
||||
operator const Type*() const { return p; }
|
||||
Type& operator*() const { return *p; }
|
||||
Type* operator->(void) const { return p; }
|
||||
|
||||
TSmartPtr& operator=( Type* newp ) {
|
||||
if (newp)
|
||||
(newp)->AddRef();
|
||||
if (p)
|
||||
(p)->Release();
|
||||
p = newp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TSmartPtr& operator=( const TSmartPtr<Type> &newp ) {
|
||||
if (newp.p)
|
||||
(newp.p)->AddRef();
|
||||
if (p)
|
||||
(p)->Release();
|
||||
p = newp.p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Type* ptr() const { return p; };
|
||||
|
||||
//operator bool() { return p != NULL; };
|
||||
operator bool() const { return p != NULL; };
|
||||
//bool operator !() { return p == NULL; };
|
||||
bool operator !() const { return p == NULL; };
|
||||
|
||||
// Misc compare functions.
|
||||
bool operator == ( const Type* p2 ) const { return p == p2; };
|
||||
bool operator != ( const Type* p2 ) const { return p != p2; };
|
||||
bool operator < ( const Type* p2 ) const { return p < p2; };
|
||||
bool operator > ( const Type* p2 ) const { return p > p2; };
|
||||
|
||||
bool operator == ( const TSmartPtr<Type> &p2 ) const { return p == p2.p; };
|
||||
bool operator != ( const TSmartPtr<Type> &p2 ) const { return p != p2.p; };
|
||||
bool operator < ( const TSmartPtr<Type> &p2 ) const { return p < p2.p; };
|
||||
bool operator > ( const TSmartPtr<Type> &p2 ) const { return p > p2.p; };
|
||||
|
||||
friend bool operator == ( const TSmartPtr<Type> &p1,int null );
|
||||
friend bool operator != ( const TSmartPtr<Type> &p1,int null );
|
||||
friend bool operator == ( int null,const TSmartPtr<Type> &p1 );
|
||||
friend bool operator != ( int null,const TSmartPtr<Type> &p1 );
|
||||
};
|
||||
#endif //WIN64
|
||||
|
||||
#ifndef WIN64
|
||||
template <class T>
|
||||
inline bool operator == ( const TSmartPtr<T> &p1,int null ) {
|
||||
return p1.p == 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator != ( const TSmartPtr<T> &p1,int null ) {
|
||||
return p1.p != 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator == ( int null,const TSmartPtr<T> &p1 ) {
|
||||
return p1.p == 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator != ( int null,const TSmartPtr<T> &p1 ) {
|
||||
return p1.p != 0;
|
||||
}
|
||||
#endif //WIN64
|
||||
|
||||
/** Use this to define smart pointers of classes.
|
||||
For example:
|
||||
class CNode : public CRefCountBase {};
|
||||
SMARTPTRTypeYPEDEF( CNode );
|
||||
{
|
||||
CNodePtr node; // Smart pointer.
|
||||
}
|
||||
*/
|
||||
|
||||
#define SMARTPTR_TYPEDEF(Class) typedef TSmartPtr<Class> Class##Ptr
|
||||
|
||||
#endif // __smartptr_h__
|
||||
Reference in New Issue
Block a user