This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View 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
View 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_)

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__

View 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];
}
}
}

View 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_)

View 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
View 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__

View 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;
}

View 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
View 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
View 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
View 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
View 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__

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

85
Editor/Util/Image.cpp Normal file
View 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
View 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
View 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
View 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__

View 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);
}
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

126
Editor/Util/smartptr.h Normal file
View 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__