mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-19 16:39:26 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
229
plugins/archivepak/archive.cpp
Normal file
229
plugins/archivepak/archive.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
#include "idatastream.h"
|
||||
#include "cmdlib.h"
|
||||
#include "bytestreamutils.h"
|
||||
#include <algorithm>
|
||||
#include "stream/filestream.h"
|
||||
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "archivelib.h"
|
||||
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include <map>
|
||||
#include "string/string.h"
|
||||
#include "fs_filesystem.h"
|
||||
|
||||
inline void buffer_findreplace(char* buffer, char find, char replace)
|
||||
{
|
||||
while(*buffer != '\0')
|
||||
{
|
||||
if(*buffer == find)
|
||||
*buffer = replace;
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
|
||||
#include "pak.h"
|
||||
|
||||
class PakArchive : public Archive
|
||||
{
|
||||
class PakRecord
|
||||
{
|
||||
public:
|
||||
PakRecord(unsigned int position, unsigned int stream_size)
|
||||
: m_position(position), m_stream_size(stream_size)
|
||||
{
|
||||
}
|
||||
unsigned int m_position;
|
||||
unsigned int m_stream_size;
|
||||
};
|
||||
typedef GenericFileSystem<PakRecord> PakFileSystem;
|
||||
PakFileSystem m_filesystem;
|
||||
FileInputStream m_pakfile;
|
||||
CopiedString m_name;
|
||||
|
||||
public:
|
||||
|
||||
PakArchive(const char* name)
|
||||
: m_pakfile(name), m_name(name)
|
||||
{
|
||||
if(!m_pakfile.failed())
|
||||
{
|
||||
pakheader_t header;
|
||||
|
||||
m_pakfile.read(reinterpret_cast<FileInputStream::byte_type*>(header.magic), 4);
|
||||
header.diroffset = istream_read_uint32_le(m_pakfile);
|
||||
header.dirsize = istream_read_uint32_le(m_pakfile);
|
||||
|
||||
if(strncmp (header.magic, "PACK", 4) == 0)
|
||||
{
|
||||
m_pakfile.seek(header.diroffset);
|
||||
|
||||
for(unsigned int i = 0; i < header.dirsize; i += sizeof(pakentry_t))
|
||||
{
|
||||
pakentry_t entry;
|
||||
|
||||
m_pakfile.read(reinterpret_cast<FileInputStream::byte_type*>(entry.filename), 0x38);
|
||||
entry.offset = istream_read_uint32_le(m_pakfile);
|
||||
entry.size = istream_read_uint32_le(m_pakfile);
|
||||
|
||||
buffer_findreplace(entry.filename, '\\', '/');
|
||||
|
||||
PakFileSystem::entry_type& file = m_filesystem[entry.filename];
|
||||
if(!file.is_directory())
|
||||
{
|
||||
globalOutputStream() << "Warning: pak archive " << makeQuoted(m_name.c_str()) << " contains duplicated file: " << makeQuoted(entry.filename) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
file = new PakRecord(entry.offset, entry.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~PakArchive()
|
||||
{
|
||||
for(PakFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i)
|
||||
delete i->second.file();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
ArchiveFile* openFile(const char* name)
|
||||
{
|
||||
PakFileSystem::iterator i = m_filesystem.find(name);
|
||||
if(i != m_filesystem.end() && !i->second.is_directory())
|
||||
{
|
||||
PakRecord* file = i->second.file();
|
||||
return StoredArchiveFile::create(name, m_name.c_str(), file->m_position, file->m_stream_size, file->m_stream_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
virtual ArchiveTextFile* openTextFile(const char* name)
|
||||
{
|
||||
PakFileSystem::iterator i = m_filesystem.find(name);
|
||||
if(i != m_filesystem.end() && !i->second.is_directory())
|
||||
{
|
||||
PakRecord* file = i->second.file();
|
||||
return StoredArchiveTextFile::create(name, m_name.c_str(), file->m_position, file->m_stream_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool containsFile(const char* name)
|
||||
{
|
||||
PakFileSystem::iterator i = m_filesystem.find(name);
|
||||
return i != m_filesystem.end() && !i->second.is_directory();
|
||||
}
|
||||
void forEachFile(VisitorFunc visitor, const char* root)
|
||||
{
|
||||
m_filesystem.traverse(visitor, root);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Archive* OpenArchive(const char* name)
|
||||
{
|
||||
return new PakArchive(name);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
class TestArchive
|
||||
{
|
||||
public:
|
||||
TestArchive()
|
||||
{
|
||||
Archive* archive = OpenArchive("c:/quake3/baseq3/pak0.pak");
|
||||
ArchiveFile* file = archive->openFile("gfx/palette.lmp");
|
||||
if(file != 0)
|
||||
{
|
||||
char buffer[1024];
|
||||
file->getInputStream().read((InputStream::byte_type*)buffer, 1024);
|
||||
file->release();
|
||||
}
|
||||
archive->release();
|
||||
}
|
||||
};
|
||||
|
||||
TestArchive g_test;
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
class TestArchive
|
||||
{
|
||||
class TestVisitor : public Archive::IVisitor
|
||||
{
|
||||
public:
|
||||
void visit(const char* name)
|
||||
{
|
||||
int bleh = 0;
|
||||
}
|
||||
};
|
||||
public:
|
||||
TestArchive()
|
||||
{
|
||||
{
|
||||
Archive* archive = OpenArchive("");
|
||||
archive->release();
|
||||
}
|
||||
{
|
||||
Archive* archive = OpenArchive("NONEXISTANTFILE");
|
||||
archive->release();
|
||||
}
|
||||
{
|
||||
Archive* archive = OpenArchive("c:/quake/id1/pak0.pak");
|
||||
ArchiveFile* file = archive->openFile("gfx/palette.lmp");
|
||||
if(file != 0)
|
||||
{
|
||||
char buffer[1024];
|
||||
file->getInputStream().read((InputStream::byte_type*)buffer, 1024);
|
||||
file->release();
|
||||
}
|
||||
TestVisitor visitor;
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 0), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFiles, 0), "progs/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFiles, 0), "maps/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFiles, 1), "sound/ambience/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "sound/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eDirectories, 1), "sound/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 2), "sound/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 2), "");
|
||||
archive->release();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestArchive g_test;
|
||||
|
||||
#endif
|
||||
23
plugins/archivepak/archive.h
Normal file
23
plugins/archivepak/archive.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Archive;
|
||||
Archive* OpenArchive(const char* name);
|
||||
7
plugins/archivepak/archivepak.def
Normal file
7
plugins/archivepak/archivepak.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; archivepak.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ARCHIVEPAK"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
150
plugins/archivepak/archivepak.dsp
Normal file
150
plugins/archivepak/archivepak.dsp
Normal file
@@ -0,0 +1,150 @@
|
||||
# Microsoft Developer Studio Project File - Name="archivepak" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=archivepak - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivepak.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivepak.mak" CFG="archivepak - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "archivepak - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "archivepak - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "archivepak"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "archivepak - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEPAK_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEPAK_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib /nologo /dll /machine:I386 /def:".\archivepak.def" /libpath:"..\..\libs\cmdlib\release" /libpath:"..\..\..\gtk2-win32\lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\archivepak.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "archivepak - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEPAK_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEPAK_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib /nologo /dll /debug /machine:I386 /def:".\archivepak.def" /pdbtype:sept /libpath:"..\..\libs\cmdlib\debug" /libpath:"..\..\..\gtk2-win32\lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\archivepak.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "archivepak - Win32 Release"
|
||||
# Name "archivepak - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archivepak.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pak.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
207
plugins/archivepak/archivepak.vcproj
Normal file
207
plugins/archivepak/archivepak.vcproj
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="archivepak"
|
||||
ProjectGUID="{75160E63-E642-4C71-9D4C-B733E152C418}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ARCHIVEPAK_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/archivepak.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/archivepak.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/archivepak.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ARCHIVEPAK_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/archivepak.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/archivepak.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\archive.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pak.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pak.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archivepak.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
23
plugins/archivepak/pak.cpp
Normal file
23
plugins/archivepak/pak.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pak.h"
|
||||
|
||||
40
plugins/archivepak/pak.h
Normal file
40
plugins/archivepak/pak.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PAK_H)
|
||||
#define INCLUDED_PAK_H
|
||||
|
||||
struct pakheader_t
|
||||
{
|
||||
char magic[4]; // Name of the new WAD format ("PACK")
|
||||
unsigned int diroffset;// Position of WAD directory from start of file
|
||||
unsigned int dirsize; // Number of entries * 0x40 (64 char)
|
||||
};
|
||||
|
||||
struct pakentry_t
|
||||
{
|
||||
char filename[0x38]; // Name of the file, Unix style, with extension, 50 chars, padded with '\0'.
|
||||
unsigned int offset; // Position of the entry in PACK file
|
||||
unsigned int size; // Size of the entry in PACK file
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
61
plugins/archivepak/plugin.cpp
Normal file
61
plugins/archivepak/plugin.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
class ArchivePakAPI
|
||||
{
|
||||
_QERArchiveTable m_archivepak;
|
||||
public:
|
||||
typedef _QERArchiveTable Type;
|
||||
STRING_CONSTANT(Name, "pak");
|
||||
|
||||
ArchivePakAPI()
|
||||
{
|
||||
m_archivepak.m_pfnOpenArchive = &OpenArchive;
|
||||
}
|
||||
_QERArchiveTable* getTable()
|
||||
{
|
||||
return &m_archivepak;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ArchivePakAPI> ArchivePakModule;
|
||||
|
||||
ArchivePakModule g_ArchivePakModule;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ArchivePakModule.selfRegister();
|
||||
}
|
||||
25
plugins/archivepak/plugin.h
Normal file
25
plugins/archivepak/plugin.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PLUGIN_H)
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
230
plugins/archivewad/archive.cpp
Normal file
230
plugins/archivewad/archive.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
#include "idatastream.h"
|
||||
#include "cmdlib.h"
|
||||
#include "bytestreamutils.h"
|
||||
#include <algorithm>
|
||||
#include "stream/filestream.h"
|
||||
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "archivelib.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include <map>
|
||||
#include "string/string.h"
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
class WadArchive : public Archive
|
||||
{
|
||||
class wad_record_t
|
||||
{
|
||||
public:
|
||||
wad_record_t(unsigned int position, unsigned int stream_size, unsigned int file_size)
|
||||
: m_position(position), m_stream_size(stream_size), m_file_size(file_size)
|
||||
{}
|
||||
unsigned int m_position;
|
||||
unsigned int m_stream_size;
|
||||
unsigned int m_file_size;
|
||||
};
|
||||
|
||||
enum EWadVersion
|
||||
{
|
||||
eNotValid,
|
||||
eWAD2,
|
||||
eWAD3,
|
||||
};
|
||||
|
||||
typedef std::map<CopiedString, wad_record_t, StringLessNoCase> files_t;
|
||||
files_t m_files;
|
||||
CopiedString m_name;
|
||||
FileInputStream m_wadfile;
|
||||
|
||||
EWadVersion wad_version(const char* identification)
|
||||
{
|
||||
if(strncmp(identification, "WAD2", 4) == 0)
|
||||
return eWAD2;
|
||||
if(strncmp(identification, "WAD3", 4) == 0)
|
||||
return eWAD3;
|
||||
return eNotValid;
|
||||
}
|
||||
|
||||
const char* type_for_version(EWadVersion version)
|
||||
{
|
||||
switch(version)
|
||||
{
|
||||
case eWAD2:
|
||||
return ".mip";
|
||||
case eWAD3:
|
||||
return ".hlw";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int miptex_type_for_version(EWadVersion version)
|
||||
{
|
||||
switch(version)
|
||||
{
|
||||
case eWAD2:
|
||||
return TYP_MIPTEX;
|
||||
case eWAD3:
|
||||
return 67;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
WadArchive(const char* name)
|
||||
: m_name(name), m_wadfile(name)
|
||||
{
|
||||
if(!m_wadfile.failed())
|
||||
{
|
||||
wadinfo_t wadinfo;
|
||||
istream_read_wadinfo(m_wadfile, wadinfo);
|
||||
|
||||
EWadVersion version = wad_version(wadinfo.identification);
|
||||
int miptexType = miptex_type_for_version(version);
|
||||
|
||||
if(version != eNotValid)
|
||||
{
|
||||
m_wadfile.seek(wadinfo.infotableofs);
|
||||
|
||||
for(int i = 0; i < wadinfo.numlumps; ++i)
|
||||
{
|
||||
char buffer[32];
|
||||
lumpinfo_t lumpinfo;
|
||||
istream_read_lumpinfo(m_wadfile, lumpinfo);
|
||||
if(lumpinfo.type == miptexType)
|
||||
{
|
||||
strcpy(buffer, "textures/");
|
||||
strcat(buffer, lumpinfo.name);
|
||||
strcat(buffer, type_for_version(version));
|
||||
m_files.insert(files_t::value_type(buffer, wad_record_t(lumpinfo.filepos, lumpinfo.disksize, lumpinfo.size)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
ArchiveFile* openFile(const char* name)
|
||||
{
|
||||
files_t::iterator i = m_files.find(name);
|
||||
if(i != m_files.end())
|
||||
{
|
||||
return StoredArchiveFile::create(name, m_name.c_str(), i->second.m_position, i->second.m_stream_size, i->second.m_file_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
virtual ArchiveTextFile* openTextFile(const char* name)
|
||||
{
|
||||
files_t::iterator i = m_files.find(name);
|
||||
if(i != m_files.end())
|
||||
{
|
||||
return StoredArchiveTextFile::create(name, m_name.c_str(), i->second.m_position, i->second.m_stream_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool containsFile(const char* name)
|
||||
{
|
||||
return m_files.find(name) != m_files.end();
|
||||
}
|
||||
void forEachFile(VisitorFunc visitor, const char* root)
|
||||
{
|
||||
if(root[0] == '\0')
|
||||
{
|
||||
if(visitor.directory("textures/", 1))
|
||||
return;
|
||||
}
|
||||
else if(strcmp(root, "textures/") != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(files_t::iterator i = m_files.begin(); i != m_files.end(); ++i)
|
||||
visitor.file(i->first.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Archive* OpenArchive(const char* name)
|
||||
{
|
||||
return new WadArchive(name);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
class TestArchive
|
||||
{
|
||||
class TestVisitor : public Archive::IVisitor
|
||||
{
|
||||
public:
|
||||
void visit(const char* name)
|
||||
{
|
||||
int bleh = 0;
|
||||
}
|
||||
};
|
||||
public:
|
||||
TestArchive()
|
||||
{
|
||||
{
|
||||
Archive* archive = OpenArchive("");
|
||||
archive->release();
|
||||
}
|
||||
{
|
||||
Archive* archive = OpenArchive("NONEXISTANTFILE");
|
||||
archive->release();
|
||||
}
|
||||
{
|
||||
Archive* archive = OpenArchive("c:/quake/id1/quake101.wad");
|
||||
ArchiveFile* file = archive->openFile("textures/sky1.mip");
|
||||
if(file != 0)
|
||||
{
|
||||
unsigned char* buffer = new unsigned char[file->size()];
|
||||
file->getInputStream().read((InputStream::byte_type*)buffer, file->size());
|
||||
delete[] buffer;
|
||||
file->release();
|
||||
}
|
||||
TestVisitor visitor;
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 0), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 0), "textures/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "textures/");
|
||||
archive->release();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestArchive g_test;
|
||||
|
||||
#endif
|
||||
23
plugins/archivewad/archive.h
Normal file
23
plugins/archivewad/archive.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
class Archive;
|
||||
Archive* OpenArchive(const char* name);
|
||||
7
plugins/archivewad/archivewad.def
Normal file
7
plugins/archivewad/archivewad.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; archivewad.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ARCHIVEWAD"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
150
plugins/archivewad/archivewad.dsp
Normal file
150
plugins/archivewad/archivewad.dsp
Normal file
@@ -0,0 +1,150 @@
|
||||
# Microsoft Developer Studio Project File - Name="archivewad" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=archivewad - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivewad.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivewad.mak" CFG="archivewad - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "archivewad - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "archivewad - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "archivewad"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "archivewad - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEWAD_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEWAD_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib /nologo /dll /machine:I386 /def:".\archivewad.def" /libpath:"../../libs/cmdlib/release" /libpath:"..\..\..\gtk2-win32\lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\archivewad.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "archivewad - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEWAD_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEWAD_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib /nologo /dll /debug /machine:I386 /def:".\archivewad.def" /pdbtype:sept /libpath:"../../libs/cmdlib/debug" /libpath:"..\..\..\gtk2-win32\lib"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\archivewad.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "archivewad - Win32 Release"
|
||||
# Name "archivewad - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archivewad.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wad.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
207
plugins/archivewad/archivewad.vcproj
Normal file
207
plugins/archivewad/archivewad.vcproj
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="archivewad"
|
||||
ProjectGUID="{9DC47AF9-ACFC-40A5-A4A6-FF3E7F8EFFBE}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ARCHIVEWAD_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/archivewad.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/archivewad.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/archivewad.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ARCHIVEWAD_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/archivewad.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/archivewad.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\archive.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wad.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archivewad.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
61
plugins/archivewad/plugin.cpp
Normal file
61
plugins/archivewad/plugin.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
class ArchiveWadAPI
|
||||
{
|
||||
_QERArchiveTable m_archivewad;
|
||||
public:
|
||||
typedef _QERArchiveTable Type;
|
||||
STRING_CONSTANT(Name, "wad");
|
||||
|
||||
ArchiveWadAPI()
|
||||
{
|
||||
m_archivewad.m_pfnOpenArchive = &OpenArchive;
|
||||
}
|
||||
_QERArchiveTable* getTable()
|
||||
{
|
||||
return &m_archivewad;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ArchiveWadAPI> ArchiveWadModule;
|
||||
|
||||
ArchiveWadModule g_ArchiveWadModule;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ArchiveWadModule.selfRegister();
|
||||
}
|
||||
25
plugins/archivewad/plugin.h
Normal file
25
plugins/archivewad/plugin.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PLUGIN_H)
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
23
plugins/archivewad/wad.cpp
Normal file
23
plugins/archivewad/wad.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
78
plugins/archivewad/wad.h
Normal file
78
plugins/archivewad/wad.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_WAD_H)
|
||||
#define INCLUDED_WAD_H
|
||||
|
||||
#include "bytestreamutils.h"
|
||||
#include "idatastream.h"
|
||||
|
||||
#define CMP_NONE 0
|
||||
#define CMP_LZSS 1
|
||||
|
||||
#define TYP_NONE 0
|
||||
#define TYP_LABEL 1
|
||||
|
||||
#define TYP_LUMPY 64 // 64 + grab command number
|
||||
#define TYP_PALETTE 64
|
||||
#define TYP_QTEX 65
|
||||
#define TYP_QPIC 66
|
||||
#define TYP_SOUND 67
|
||||
#define TYP_MIPTEX 68
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char identification[4]; // should be WAD2 or 2DAW
|
||||
int numlumps;
|
||||
int infotableofs;
|
||||
} wadinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int filepos;
|
||||
int disksize;
|
||||
int size; // uncompressed
|
||||
char type;
|
||||
char compression;
|
||||
char pad1, pad2;
|
||||
char name[16]; // must be null terminated
|
||||
} lumpinfo_t;
|
||||
|
||||
inline void istream_read_wadinfo(InputStream& istream, wadinfo_t& wadinfo)
|
||||
{
|
||||
istream.read(reinterpret_cast<InputStream::byte_type*>(wadinfo.identification), 4);
|
||||
wadinfo.numlumps = istream_read_int32_le(istream);
|
||||
wadinfo.infotableofs = istream_read_int32_le(istream);
|
||||
}
|
||||
|
||||
inline void istream_read_lumpinfo(InputStream& istream, lumpinfo_t& lumpinfo)
|
||||
{
|
||||
lumpinfo.filepos = istream_read_int32_le(istream);
|
||||
lumpinfo.disksize = istream_read_int32_le(istream);
|
||||
lumpinfo.size = istream_read_int32_le(istream);
|
||||
lumpinfo.type = istream_read_byte(istream);
|
||||
lumpinfo.compression = istream_read_byte(istream);
|
||||
lumpinfo.pad1 = istream_read_byte(istream);
|
||||
lumpinfo.pad2 = istream_read_byte(istream);
|
||||
istream.read(reinterpret_cast<InputStream::byte_type*>(lumpinfo.name), 16);
|
||||
}
|
||||
|
||||
#endif
|
||||
353
plugins/archivezip/archive.cpp
Normal file
353
plugins/archivezip/archive.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "idatastream.h"
|
||||
#include "cmdlib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
#include "modulesystem.h"
|
||||
#include "iarchive.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "stream/filestream.h"
|
||||
#include "container/array.h"
|
||||
#include "archivelib.h"
|
||||
#include "zlibstream.h"
|
||||
|
||||
class DeflatedArchiveFile : public ArchiveFile
|
||||
{
|
||||
CopiedString m_name;
|
||||
FileInputStream m_istream;
|
||||
SubFileInputStream m_substream;
|
||||
DeflatedInputStream m_zipstream;
|
||||
FileInputStream::size_type m_size;
|
||||
public:
|
||||
typedef FileInputStream::size_type size_type;
|
||||
typedef FileInputStream::position_type position_type;
|
||||
|
||||
DeflatedArchiveFile(const char* name, const char* archiveName, position_type position, size_type stream_size, size_type file_size)
|
||||
: m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size), m_zipstream(m_substream), m_size(file_size)
|
||||
{
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
size_type size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
const char* getName() const
|
||||
{
|
||||
return m_name.c_str();
|
||||
}
|
||||
InputStream& getInputStream()
|
||||
{
|
||||
return m_zipstream;
|
||||
}
|
||||
};
|
||||
|
||||
class DeflatedArchiveTextFile : public ArchiveTextFile
|
||||
{
|
||||
CopiedString m_name;
|
||||
FileInputStream m_istream;
|
||||
SubFileInputStream m_substream;
|
||||
DeflatedInputStream m_zipstream;
|
||||
BinaryToTextInputStream<DeflatedInputStream> m_textStream;
|
||||
public:
|
||||
typedef FileInputStream::size_type size_type;
|
||||
typedef FileInputStream::position_type position_type;
|
||||
|
||||
DeflatedArchiveTextFile(const char* name, const char* archiveName, position_type position, size_type stream_size)
|
||||
: m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size), m_zipstream(m_substream), m_textStream(m_zipstream)
|
||||
{
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
TextInputStream& getInputStream()
|
||||
{
|
||||
return m_textStream;
|
||||
}
|
||||
};
|
||||
|
||||
#include "pkzip.h"
|
||||
|
||||
#include <map>
|
||||
#include "string/string.h"
|
||||
#include "fs_filesystem.h"
|
||||
|
||||
|
||||
class ZipArchive : public Archive
|
||||
{
|
||||
class ZipRecord
|
||||
{
|
||||
public:
|
||||
enum ECompressionMode
|
||||
{
|
||||
eStored,
|
||||
eDeflated,
|
||||
};
|
||||
ZipRecord(unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, ECompressionMode mode)
|
||||
: m_position(position), m_stream_size(compressed_size), m_file_size(uncompressed_size), m_mode(mode)
|
||||
{
|
||||
}
|
||||
unsigned int m_position;
|
||||
unsigned int m_stream_size;
|
||||
unsigned int m_file_size;
|
||||
ECompressionMode m_mode;
|
||||
};
|
||||
|
||||
typedef GenericFileSystem<ZipRecord> ZipFileSystem;
|
||||
ZipFileSystem m_filesystem;
|
||||
CopiedString m_name;
|
||||
FileInputStream m_istream;
|
||||
|
||||
bool read_record()
|
||||
{
|
||||
zip_magic magic;
|
||||
istream_read_zip_magic(m_istream, magic);
|
||||
if(!(magic == zip_root_dirent_magic))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
zip_version version_encoder;
|
||||
istream_read_zip_version(m_istream, version_encoder);
|
||||
zip_version version_extract;
|
||||
istream_read_zip_version(m_istream, version_extract);
|
||||
//unsigned short flags =
|
||||
istream_read_int16_le(m_istream);
|
||||
unsigned short compression_mode = istream_read_int16_le(m_istream);
|
||||
if(compression_mode != Z_DEFLATED && compression_mode != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
zip_dostime dostime;
|
||||
istream_read_zip_dostime(m_istream, dostime);
|
||||
//unsigned int crc32 =
|
||||
istream_read_int32_le(m_istream);
|
||||
unsigned int compressed_size = istream_read_uint32_le(m_istream);
|
||||
unsigned int uncompressed_size = istream_read_uint32_le(m_istream);
|
||||
unsigned int namelength = istream_read_uint16_le(m_istream);
|
||||
unsigned short extras = istream_read_uint16_le(m_istream);
|
||||
unsigned short comment = istream_read_uint16_le(m_istream);
|
||||
//unsigned short diskstart =
|
||||
istream_read_int16_le(m_istream);
|
||||
//unsigned short filetype =
|
||||
istream_read_int16_le(m_istream);
|
||||
//unsigned int filemode =
|
||||
istream_read_int32_le(m_istream);
|
||||
unsigned int position = istream_read_int32_le(m_istream);
|
||||
|
||||
Array<char> filename(namelength+1);
|
||||
m_istream.read(reinterpret_cast<FileInputStream::byte_type*>(filename.data()), namelength);
|
||||
filename[namelength] = '\0';
|
||||
|
||||
m_istream.seek(extras + comment, FileInputStream::cur);
|
||||
|
||||
if(path_is_directory(filename.data()))
|
||||
{
|
||||
m_filesystem[filename.data()] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZipFileSystem::entry_type& file = m_filesystem[filename.data()];
|
||||
if(!file.is_directory())
|
||||
{
|
||||
globalOutputStream() << "Warning: zip archive " << makeQuoted(m_name.c_str()) << " contains duplicated file: " << makeQuoted(filename.data()) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
file = new ZipRecord(position, compressed_size, uncompressed_size, (compression_mode == Z_DEFLATED) ? ZipRecord::eDeflated : ZipRecord::eStored);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_pkzip()
|
||||
{
|
||||
SeekableStream::position_type pos = pkzip_find_disk_trailer(m_istream);
|
||||
if(pos != 0)
|
||||
{
|
||||
zip_disk_trailer disk_trailer;
|
||||
m_istream.seek(pos);
|
||||
istream_read_zip_disk_trailer(m_istream, disk_trailer);
|
||||
if(!(disk_trailer.z_magic == zip_disk_trailer_magic))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_istream.seek(disk_trailer.z_rootseek);
|
||||
for(unsigned int i = 0; i < disk_trailer.z_entries; ++i)
|
||||
{
|
||||
if(!read_record())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
ZipArchive(const char* name)
|
||||
: m_name(name), m_istream(name)
|
||||
{
|
||||
if(!m_istream.failed())
|
||||
{
|
||||
if(!read_pkzip())
|
||||
{
|
||||
globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted(name) << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
~ZipArchive()
|
||||
{
|
||||
for(ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i)
|
||||
{
|
||||
delete i->second.file();
|
||||
}
|
||||
}
|
||||
|
||||
bool failed()
|
||||
{
|
||||
return m_istream.failed();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
ArchiveFile* openFile(const char* name)
|
||||
{
|
||||
ZipFileSystem::iterator i = m_filesystem.find(name);
|
||||
if(i != m_filesystem.end() && !i->second.is_directory())
|
||||
{
|
||||
ZipRecord* file = i->second.file();
|
||||
|
||||
m_istream.seek(file->m_position);
|
||||
zip_file_header file_header;
|
||||
istream_read_zip_file_header(m_istream, file_header);
|
||||
if(file_header.z_magic != zip_file_header_magic)
|
||||
{
|
||||
globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(file->m_mode)
|
||||
{
|
||||
case ZipRecord::eStored:
|
||||
return StoredArchiveFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size);
|
||||
case ZipRecord::eDeflated:
|
||||
return new DeflatedArchiveFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ArchiveTextFile* openTextFile(const char* name)
|
||||
{
|
||||
ZipFileSystem::iterator i = m_filesystem.find(name);
|
||||
if(i != m_filesystem.end() && !i->second.is_directory())
|
||||
{
|
||||
ZipRecord* file = i->second.file();
|
||||
|
||||
m_istream.seek(file->m_position);
|
||||
zip_file_header file_header;
|
||||
istream_read_zip_file_header(m_istream, file_header);
|
||||
if(file_header.z_magic != zip_file_header_magic)
|
||||
{
|
||||
globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(file->m_mode)
|
||||
{
|
||||
case ZipRecord::eStored:
|
||||
return StoredArchiveTextFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size);
|
||||
case ZipRecord::eDeflated:
|
||||
return new DeflatedArchiveTextFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool containsFile(const char* name)
|
||||
{
|
||||
ZipFileSystem::iterator i = m_filesystem.find(name);
|
||||
return i != m_filesystem.end() && !i->second.is_directory();
|
||||
}
|
||||
void forEachFile(VisitorFunc visitor, const char* root)
|
||||
{
|
||||
m_filesystem.traverse(visitor, root);
|
||||
}
|
||||
};
|
||||
|
||||
Archive* OpenArchive(const char* name)
|
||||
{
|
||||
return new ZipArchive(name);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
class TestZip
|
||||
{
|
||||
class TestVisitor : public Archive::IVisitor
|
||||
{
|
||||
public:
|
||||
void visit(const char* name)
|
||||
{
|
||||
int bleh = 0;
|
||||
}
|
||||
};
|
||||
public:
|
||||
TestZip()
|
||||
{
|
||||
testzip("c:/quake3/baseq3/mapmedia.pk3", "textures/radiant/notex.tga");
|
||||
}
|
||||
|
||||
void testzip(const char* name, const char* filename)
|
||||
{
|
||||
Archive* archive = OpenArchive(name);
|
||||
ArchiveFile* file = archive->openFile(filename);
|
||||
if(file != 0)
|
||||
{
|
||||
unsigned char buffer[4096];
|
||||
std::size_t count = file->getInputStream().read((InputStream::byte_type*)buffer, 4096);
|
||||
file->release();
|
||||
}
|
||||
TestVisitor visitor;
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 0), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFiles, 1), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eDirectories, 1), "");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "textures");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 1), "textures/");
|
||||
archive->forEachFile(Archive::VisitorFunc(&visitor, Archive::eFilesAndDirectories, 2), "");
|
||||
archive->release();
|
||||
}
|
||||
};
|
||||
|
||||
TestZip g_TestZip;
|
||||
|
||||
#endif
|
||||
22
plugins/archivezip/archive.h
Normal file
22
plugins/archivezip/archive.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
Archive* OpenArchive(const char* name);
|
||||
7
plugins/archivezip/archivezip.def
Normal file
7
plugins/archivezip/archivezip.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; archivezip.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ARCHIVEZIP"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
154
plugins/archivezip/archivezip.dsp
Normal file
154
plugins/archivezip/archivezip.dsp
Normal file
@@ -0,0 +1,154 @@
|
||||
# Microsoft Developer Studio Project File - Name="archivezip" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=archivezip - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivezip.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "archivezip.mak" CFG="archivezip - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "archivezip - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "archivezip - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "archivezip"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "archivezip - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEZIP_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /I "..\..\..\zlib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEZIP_EXPORTS" /D "ZLIB_DLL" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib zlib.lib /nologo /dll /machine:I386 /def:".\archivezip.def" /libpath:"..\..\libs\cmdlib\release" /libpath:"..\..\..\gtk2-win32\lib" /libpath:"..\..\..\libpng\projects\msvc\zlib___Win32_Release"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\archivezip.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "archivezip - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEZIP_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /I "..\..\..\zlib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARCHIVEZIP_EXPORTS" /D "ZLIB_DLL" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 cmdlib.lib glib-2.0.lib zlibd.lib /nologo /dll /debug /machine:I386 /def:".\archivezip.def" /pdbtype:sept /libpath:"..\..\libs\cmdlib\debug" /libpath:"..\..\..\gtk2-win32\lib" /libpath:"..\..\..\libpng\projects\msvc\zlib___Win32_Debug"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\archivezip.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "archivezip - Win32 Release"
|
||||
# Name "archivezip - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archivezip.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\archive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pkzip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlibstream.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
218
plugins/archivezip/archivezip.vcproj
Normal file
218
plugins/archivezip/archivezip.vcproj
Normal file
@@ -0,0 +1,218 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="archivezip"
|
||||
ProjectGUID="{A7E0FE03-E9BB-4478-9752-250BBD406C2D}"
|
||||
RootNamespace="archivezip"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";../../../zlib1-1.2/include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ARCHIVEZIP_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="zdll.lib"
|
||||
OutputFile="$(OutDir)/archivezip.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../zlib1-1.2/lib"
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/archivezip.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/archivezip.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";../../../zlib1-1.2/include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ARCHIVEZIP_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="zdll.lib"
|
||||
OutputFile="$(OutDir)/archivezip.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../zlib1-1.2/lib"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/archivezip.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\archive.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archive.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pkzip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pkzip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlibstream.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlibstream.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\archivezip.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
23
plugins/archivezip/pkzip.cpp
Normal file
23
plugins/archivezip/pkzip.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pkzip.h"
|
||||
|
||||
266
plugins/archivezip/pkzip.h
Normal file
266
plugins/archivezip/pkzip.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PKZIP_H)
|
||||
#define INCLUDED_PKZIP_H
|
||||
|
||||
#include "bytestreamutils.h"
|
||||
#include "idatastream.h"
|
||||
#include <algorithm>
|
||||
|
||||
class zip_magic
|
||||
{
|
||||
public:
|
||||
bool operator==(const zip_magic& other) const
|
||||
{
|
||||
return m_value[0] == other.m_value[0]
|
||||
&& m_value[1] == other.m_value[1]
|
||||
&& m_value[2] == other.m_value[2]
|
||||
&& m_value[3] == other.m_value[3];
|
||||
}
|
||||
bool operator!=(const zip_magic& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
char m_value[4];
|
||||
};
|
||||
|
||||
inline void istream_read_zip_magic(InputStream& istream, zip_magic& magic)
|
||||
{
|
||||
istream.read(reinterpret_cast<InputStream::byte_type*>(magic.m_value), 4);
|
||||
}
|
||||
|
||||
struct zip_version
|
||||
{
|
||||
char version;
|
||||
char ostype;
|
||||
};
|
||||
|
||||
inline void istream_read_zip_version(InputStream& istream, zip_version& version)
|
||||
{
|
||||
version.version = istream_read_byte(istream);
|
||||
version.ostype = istream_read_byte(istream);
|
||||
}
|
||||
|
||||
struct zip_dostime
|
||||
{
|
||||
unsigned short time;
|
||||
unsigned short date;
|
||||
};
|
||||
|
||||
inline void istream_read_zip_dostime(InputStream& istream, zip_dostime& dostime)
|
||||
{
|
||||
dostime.time = istream_read_int16_le(istream);
|
||||
dostime.date = istream_read_int16_le(istream);
|
||||
}
|
||||
|
||||
const zip_magic zip_file_header_magic = { 'P', 'K', 0x03, 0x04, };
|
||||
|
||||
/* A. Local file header */
|
||||
struct zip_file_header
|
||||
{
|
||||
zip_magic z_magic; /* local file header signature (0x04034b50) */
|
||||
zip_version z_extract; /* version needed to extract */
|
||||
unsigned short z_flags; /* general purpose bit flag */
|
||||
unsigned short z_compr; /* compression method */
|
||||
zip_dostime z_dostime; /* last mod file time (dos format) */
|
||||
unsigned int z_crc32; /* crc-32 */
|
||||
unsigned int z_csize; /* compressed size */
|
||||
unsigned int z_usize; /* uncompressed size */
|
||||
unsigned short z_namlen; /* filename length (null if stdin) */
|
||||
unsigned short z_extras; /* extra field length */
|
||||
/* followed by filename (of variable size) */
|
||||
/* followed by extra field (of variable size) */
|
||||
};
|
||||
|
||||
inline void istream_read_zip_file_header(SeekableInputStream& istream, zip_file_header& file_header)
|
||||
{
|
||||
istream_read_zip_magic(istream, file_header.z_magic);
|
||||
istream_read_zip_version(istream, file_header.z_extract);
|
||||
file_header.z_flags = istream_read_uint16_le(istream);
|
||||
file_header.z_compr = istream_read_uint16_le(istream);
|
||||
istream_read_zip_dostime(istream, file_header.z_dostime);
|
||||
file_header.z_crc32 = istream_read_uint32_le(istream);
|
||||
file_header.z_csize = istream_read_uint32_le(istream);
|
||||
file_header.z_usize = istream_read_uint32_le(istream);
|
||||
file_header.z_namlen = istream_read_uint16_le(istream);
|
||||
file_header.z_extras = istream_read_uint16_le(istream);
|
||||
istream.seek(file_header.z_namlen + file_header.z_extras, SeekableInputStream::cur);
|
||||
};
|
||||
|
||||
/* B. data descriptor
|
||||
* the data descriptor exists only if bit 3 of z_flags is set. It is byte aligned
|
||||
* and immediately follows the last byte of compressed data. It is only used if
|
||||
* the output media of the compressor was not seekable, eg. standard output.
|
||||
*/
|
||||
const zip_magic zip_file_trailer_magic = { 'P', 'K', 0x07, 0x08, };
|
||||
|
||||
struct zip_file_trailer
|
||||
{
|
||||
zip_magic z_magic;
|
||||
unsigned int z_crc32; /* crc-32 */
|
||||
unsigned int z_csize; /* compressed size */
|
||||
unsigned int z_usize; /* uncompressed size */
|
||||
};
|
||||
|
||||
inline void istream_read_zip_file_trailer(InputStream& istream, zip_file_trailer& file_trailer)
|
||||
{
|
||||
istream_read_zip_magic(istream, file_trailer.z_magic);
|
||||
file_trailer.z_crc32 = istream_read_uint32_le(istream);
|
||||
file_trailer.z_csize = istream_read_uint32_le(istream);
|
||||
file_trailer.z_usize = istream_read_uint32_le(istream);
|
||||
};
|
||||
|
||||
|
||||
/* C. central directory structure:
|
||||
[file header] . . . end of central dir record
|
||||
*/
|
||||
|
||||
/* directory file header
|
||||
* - a single entry including filename, extras and comment may not exceed 64k.
|
||||
*/
|
||||
|
||||
const zip_magic zip_root_dirent_magic = { 'P', 'K', 0x01, 0x02, };
|
||||
|
||||
struct zip_root_dirent
|
||||
{
|
||||
zip_magic z_magic;
|
||||
zip_version z_encoder; /* version made by */
|
||||
zip_version z_extract; /* version need to extract */
|
||||
unsigned short z_flags; /* general purpose bit flag */
|
||||
unsigned short z_compr; /* compression method */
|
||||
zip_dostime z_dostime; /* last mod file time&date (dos format) */
|
||||
unsigned int z_crc32; /* crc-32 */
|
||||
unsigned int z_csize; /* compressed size */
|
||||
unsigned int z_usize; /* uncompressed size */
|
||||
unsigned short z_namlen; /* filename length (null if stdin) */
|
||||
unsigned short z_extras; /* extra field length */
|
||||
unsigned short z_comment; /* file comment length */
|
||||
unsigned short z_diskstart; /* disk number of start (if spanning zip over multiple disks) */
|
||||
unsigned short z_filetype; /* internal file attributes, bit0 = ascii */
|
||||
unsigned int z_filemode; /* extrnal file attributes, eg. msdos attrib byte */
|
||||
unsigned int z_off; /* relative offset of local file header, seekval if singledisk */
|
||||
/* followed by filename (of variable size) */
|
||||
/* followed by extra field (of variable size) */
|
||||
/* followed by file comment (of variable size) */
|
||||
};
|
||||
|
||||
inline void istream_read_zip_root_dirent(SeekableInputStream& istream, zip_root_dirent& root_dirent)
|
||||
{
|
||||
istream_read_zip_magic(istream, root_dirent.z_magic);
|
||||
istream_read_zip_version(istream, root_dirent.z_encoder);
|
||||
istream_read_zip_version(istream, root_dirent.z_extract);
|
||||
root_dirent.z_flags = istream_read_uint16_le(istream);
|
||||
root_dirent.z_compr = istream_read_uint16_le(istream);
|
||||
istream_read_zip_dostime(istream, root_dirent.z_dostime);
|
||||
root_dirent.z_crc32 = istream_read_uint32_le(istream);
|
||||
root_dirent.z_csize = istream_read_uint32_le(istream);
|
||||
root_dirent.z_usize = istream_read_uint32_le(istream);
|
||||
root_dirent.z_namlen = istream_read_uint16_le(istream);
|
||||
root_dirent.z_extras = istream_read_uint16_le(istream);
|
||||
root_dirent.z_comment = istream_read_uint16_le(istream);
|
||||
root_dirent.z_diskstart = istream_read_uint16_le(istream);
|
||||
root_dirent.z_filetype = istream_read_uint16_le(istream);
|
||||
root_dirent.z_filemode = istream_read_uint32_le(istream);
|
||||
root_dirent.z_off = istream_read_uint32_le(istream);
|
||||
istream.seek(root_dirent.z_namlen + root_dirent.z_extras + root_dirent.z_comment, SeekableInputStream::cur);
|
||||
}
|
||||
|
||||
/* end of central dir record */
|
||||
const zip_magic zip_disk_trailer_magic = { 'P', 'K', 0x05, 0x06, };
|
||||
const unsigned int disk_trailer_length = 22;
|
||||
struct zip_disk_trailer
|
||||
{
|
||||
zip_magic z_magic;
|
||||
unsigned short z_disk; /* number of this disk */
|
||||
unsigned short z_finaldisk; /* number of the disk with the start of the central dir */
|
||||
unsigned short z_entries; /* total number of entries in the central dir on this disk */
|
||||
unsigned short z_finalentries; /* total number of entries in the central dir */
|
||||
unsigned int z_rootsize; /* size of the central directory */
|
||||
unsigned int z_rootseek; /* offset of start of central directory with respect to *
|
||||
* the starting disk number */
|
||||
unsigned short z_comment; /* zipfile comment length */
|
||||
/* followed by zipfile comment (of variable size) */
|
||||
};
|
||||
|
||||
inline void istream_read_zip_disk_trailer(SeekableInputStream& istream, zip_disk_trailer& disk_trailer)
|
||||
{
|
||||
istream_read_zip_magic(istream, disk_trailer.z_magic);
|
||||
disk_trailer.z_disk = istream_read_uint16_le(istream);
|
||||
disk_trailer.z_finaldisk = istream_read_uint16_le(istream);
|
||||
disk_trailer.z_entries = istream_read_uint16_le(istream);
|
||||
disk_trailer.z_finalentries = istream_read_uint16_le(istream);
|
||||
disk_trailer.z_rootsize = istream_read_uint32_le(istream);
|
||||
disk_trailer.z_rootseek = istream_read_uint32_le(istream);
|
||||
disk_trailer.z_comment = istream_read_uint16_le(istream);
|
||||
istream.seek(disk_trailer.z_comment, SeekableInputStream::cur);
|
||||
}
|
||||
|
||||
inline SeekableStream::position_type pkzip_find_disk_trailer(SeekableInputStream& istream)
|
||||
{
|
||||
istream.seek(0, SeekableInputStream::end);
|
||||
SeekableStream::position_type start_position = istream.tell();
|
||||
if(start_position < disk_trailer_length)
|
||||
return 0;
|
||||
start_position -= disk_trailer_length;
|
||||
|
||||
zip_magic magic;
|
||||
istream.seek(start_position);
|
||||
istream_read_zip_magic(istream, magic);
|
||||
|
||||
if(magic == zip_disk_trailer_magic)
|
||||
return start_position;
|
||||
else
|
||||
{
|
||||
const SeekableStream::position_type max_comment = 0x10000;
|
||||
const SeekableStream::position_type bufshift = 6;
|
||||
const SeekableStream::position_type bufsize = max_comment >> bufshift;
|
||||
unsigned char buffer[bufsize];
|
||||
|
||||
SeekableStream::position_type search_end = (max_comment < start_position) ? start_position - max_comment : 0;
|
||||
SeekableStream::position_type position = start_position;
|
||||
while(position != search_end)
|
||||
{
|
||||
StreamBase::size_type to_read = std::min(bufsize, position - search_end);
|
||||
position -= to_read;
|
||||
|
||||
istream.seek(position);
|
||||
StreamBase::size_type size = istream.read(buffer, to_read);
|
||||
|
||||
unsigned char* p = buffer + size;
|
||||
while(p != buffer)
|
||||
{
|
||||
--p;
|
||||
magic.m_value[3] = magic.m_value[2];
|
||||
magic.m_value[2] = magic.m_value[1];
|
||||
magic.m_value[1] = magic.m_value[0];
|
||||
magic.m_value[0] = *p;
|
||||
if(magic == zip_disk_trailer_magic)
|
||||
{
|
||||
return position + (p - buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
85
plugins/archivezip/plugin.cpp
Normal file
85
plugins/archivezip/plugin.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
|
||||
class ArchiveZipAPI
|
||||
{
|
||||
_QERArchiveTable m_archivezip;
|
||||
public:
|
||||
typedef _QERArchiveTable Type;
|
||||
STRING_CONSTANT(Name, "pk3");
|
||||
|
||||
ArchiveZipAPI()
|
||||
{
|
||||
m_archivezip.m_pfnOpenArchive = &OpenArchive;
|
||||
}
|
||||
_QERArchiveTable* getTable()
|
||||
{
|
||||
return &m_archivezip;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ArchiveZipAPI> ArchiveZipModule;
|
||||
|
||||
ArchiveZipModule g_ArchiveZipModule;
|
||||
|
||||
|
||||
class ArchivePK4API
|
||||
{
|
||||
_QERArchiveTable m_archivepk4;
|
||||
public:
|
||||
typedef _QERArchiveTable Type;
|
||||
STRING_CONSTANT(Name, "pk4");
|
||||
|
||||
ArchivePK4API()
|
||||
{
|
||||
m_archivepk4.m_pfnOpenArchive = &OpenArchive;
|
||||
}
|
||||
_QERArchiveTable* getTable()
|
||||
{
|
||||
return &m_archivepk4;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ArchivePK4API> ArchivePK4Module;
|
||||
|
||||
ArchivePK4Module g_ArchivePK4Module;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ArchiveZipModule.selfRegister();
|
||||
g_ArchivePK4Module.selfRegister();
|
||||
}
|
||||
25
plugins/archivezip/plugin.h
Normal file
25
plugins/archivezip/plugin.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PLUGIN_H)
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
23
plugins/archivezip/zlibstream.cpp
Normal file
23
plugins/archivezip/zlibstream.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "zlibstream.h"
|
||||
|
||||
75
plugins/archivezip/zlibstream.h
Normal file
75
plugins/archivezip/zlibstream.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ZLIBSTREAM_H)
|
||||
#define INCLUDED_ZLIBSTREAM_H
|
||||
|
||||
#include "zlib.h"
|
||||
#include "idatastream.h"
|
||||
|
||||
/// \brief A wrapper around an InputStream of data compressed with the zlib deflate algorithm.
|
||||
///
|
||||
/// - Uses z_stream to decompress the data stream on the fly.
|
||||
/// - Uses a buffer to reduce the number of times the wrapped stream must be read.
|
||||
class DeflatedInputStream : public InputStream
|
||||
{
|
||||
InputStream& m_istream;
|
||||
z_stream m_zipstream;
|
||||
static const int m_bufsize = 1024;
|
||||
unsigned char m_buffer[m_bufsize];
|
||||
|
||||
public:
|
||||
DeflatedInputStream(InputStream& istream)
|
||||
: m_istream(istream)
|
||||
{
|
||||
m_zipstream.zalloc = 0;
|
||||
m_zipstream.zfree = 0;
|
||||
m_zipstream.opaque = 0;
|
||||
m_zipstream.avail_in = 0;
|
||||
inflateInit2(&m_zipstream, -MAX_WBITS);
|
||||
}
|
||||
~DeflatedInputStream()
|
||||
{
|
||||
inflateEnd(&m_zipstream);
|
||||
}
|
||||
size_type read(byte_type* buffer, size_type length)
|
||||
{
|
||||
m_zipstream.next_out = buffer;
|
||||
m_zipstream.avail_out = static_cast<uInt>(length);
|
||||
while(m_zipstream.avail_out != 0)
|
||||
{
|
||||
if(m_zipstream.avail_in == 0)
|
||||
{
|
||||
m_zipstream.next_in = m_buffer;
|
||||
m_zipstream.avail_in = static_cast<uInt>(m_istream.read(m_buffer, m_bufsize));
|
||||
}
|
||||
if(inflate(&m_zipstream, Z_SYNC_FLUSH) != Z_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return length - m_zipstream.avail_out;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
32
plugins/config.mk
Normal file
32
plugins/config.mk
Normal file
@@ -0,0 +1,32 @@
|
||||
# Common configuration options for all plugins
|
||||
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
CFLAGS+=`gtk-config --cflags` -Wall -g -I../../include
|
||||
CPPFLAGS+=`gtk-config --cflags` -Wall -g -I../../include
|
||||
LDFLAGS+=`gtk-config --libs` -shared
|
||||
OUTDIR=$(RADIANT_DATA)plugins
|
||||
OBJS := $(patsubst %.cpp,%.o,$(filter %.cpp,$(SRC)))
|
||||
OBJS += $(patsubst %.c,%.o,$(filter %.c,$(SRC)))
|
||||
|
||||
all: $(OUTPUT)
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
$(CXX) -o $(OUTPUT) $(OBJS) $(LDFLAGS)
|
||||
@if [ -d $(OUTDIR) ]; then cp $(OUTPUT) $(OUTDIR); fi
|
||||
|
||||
## Other targets
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d $(OUTPUT) core
|
||||
|
||||
## Dependencies
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
%.d: %.cpp
|
||||
@echo -n "$(@) " > $@
|
||||
@if { !(eval $(CXX) -MM $(CPPFLAGS) -w $<) >> $@; }; then \
|
||||
rm -f $@; exit 1; \
|
||||
fi
|
||||
@[ -s $@ ] || rm -f $@
|
||||
23
plugins/entity/angle.cpp
Normal file
23
plugins/entity/angle.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "angle.h"
|
||||
|
||||
101
plugins/entity/angle.h
Normal file
101
plugins/entity/angle.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ANGLE_H)
|
||||
#define INCLUDED_ANGLE_H
|
||||
|
||||
#include "ientity.h"
|
||||
|
||||
#include "math/quaternion.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
const float ANGLEKEY_IDENTITY = 0;
|
||||
|
||||
inline void default_angle(float& angle)
|
||||
{
|
||||
angle = ANGLEKEY_IDENTITY;
|
||||
}
|
||||
inline void normalise_angle(float& angle)
|
||||
{
|
||||
angle = static_cast<float>(float_mod(angle, 360.0));
|
||||
}
|
||||
inline void read_angle(float& angle, const char* value)
|
||||
{
|
||||
if(!string_parse_float(value, angle))
|
||||
{
|
||||
angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
normalise_angle(angle);
|
||||
}
|
||||
}
|
||||
inline void write_angle(float angle, Entity* entity)
|
||||
{
|
||||
if(angle == 0)
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
sprintf(value, "%g", angle);
|
||||
entity->setKeyValue("angle", value);
|
||||
}
|
||||
}
|
||||
|
||||
class AngleKey
|
||||
{
|
||||
Callback m_angleChanged;
|
||||
public:
|
||||
float m_angle;
|
||||
|
||||
|
||||
AngleKey(const Callback& angleChanged)
|
||||
: m_angleChanged(angleChanged), m_angle(ANGLEKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_angle, value);
|
||||
m_angleChanged();
|
||||
}
|
||||
typedef MemberCaller1<AngleKey, const char*, &AngleKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_angle(m_angle, entity);
|
||||
}
|
||||
};
|
||||
|
||||
inline float angle_rotated(float angle, const Quaternion& rotation)
|
||||
{
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_z_degrees(angle),
|
||||
matrix4_rotation_for_quaternion_quantised(rotation)
|
||||
)
|
||||
).z();
|
||||
}
|
||||
|
||||
#endif
|
||||
23
plugins/entity/angles.cpp
Normal file
23
plugins/entity/angles.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "angles.h"
|
||||
|
||||
140
plugins/entity/angles.h
Normal file
140
plugins/entity/angles.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ANGLES_H)
|
||||
#define INCLUDED_ANGLES_H
|
||||
|
||||
#include "ientity.h"
|
||||
|
||||
#include "math/quaternion.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "angle.h"
|
||||
|
||||
const Vector3 ANGLESKEY_IDENTITY = Vector3(0, 0, 0);
|
||||
|
||||
inline void default_angles(Vector3& angles)
|
||||
{
|
||||
angles = ANGLESKEY_IDENTITY;
|
||||
}
|
||||
inline void normalise_angles(Vector3& angles)
|
||||
{
|
||||
angles[0] = static_cast<float>(float_mod(angles[0], 360));
|
||||
angles[1] = static_cast<float>(float_mod(angles[1], 360));
|
||||
angles[2] = static_cast<float>(float_mod(angles[2], 360));
|
||||
}
|
||||
inline void read_angle(Vector3& angles, const char* value)
|
||||
{
|
||||
if(!string_parse_float(value, angles[2]))
|
||||
{
|
||||
default_angles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
angles[0] = 0;
|
||||
angles[1] = 0;
|
||||
normalise_angles(angles);
|
||||
}
|
||||
}
|
||||
inline void read_angles(Vector3& angles, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, angles))
|
||||
{
|
||||
default_angles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
angles = Vector3(angles[2], angles[0], angles[1]);
|
||||
normalise_angles(angles);
|
||||
}
|
||||
}
|
||||
inline void write_angles(const Vector3& angles, Entity* entity)
|
||||
{
|
||||
if(angles[0] == 0
|
||||
&& angles[1] == 0
|
||||
&& angles[2] == 0)
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
entity->setKeyValue("angles", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
|
||||
if(angles[0] == 0 && angles[1] == 0)
|
||||
{
|
||||
entity->setKeyValue("angles", "");
|
||||
write_angle(angles[2], entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(value, "%g %g %g", angles[1], angles[2], angles[0]);
|
||||
entity->setKeyValue("angle", "");
|
||||
entity->setKeyValue("angles", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Vector3 angles_rotated(const Vector3& angles, const Quaternion& rotation)
|
||||
{
|
||||
return matrix4_get_rotation_euler_xyz_degrees(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_rotation_for_euler_xyz_degrees(angles),
|
||||
matrix4_rotation_for_quaternion_quantised(rotation)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
class AnglesKey
|
||||
{
|
||||
Callback m_anglesChanged;
|
||||
public:
|
||||
Vector3 m_angles;
|
||||
|
||||
|
||||
AnglesKey(const Callback& anglesChanged)
|
||||
: m_anglesChanged(anglesChanged), m_angles(ANGLESKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_angles, value);
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void anglesChanged(const char* value)
|
||||
{
|
||||
read_angles(m_angles, value);
|
||||
m_anglesChanged();
|
||||
}
|
||||
typedef MemberCaller1<AnglesKey, const char*, &AnglesKey::anglesChanged> AnglesChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_angles(m_angles, entity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
23
plugins/entity/colour.cpp
Normal file
23
plugins/entity/colour.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "colour.h"
|
||||
|
||||
102
plugins/entity/colour.h
Normal file
102
plugins/entity/colour.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_COLOUR_H)
|
||||
#define INCLUDED_COLOUR_H
|
||||
|
||||
#include "ientity.h"
|
||||
#include "irender.h"
|
||||
|
||||
#include "math/vector.h"
|
||||
#include "eclasslib.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
inline void default_colour(Vector3& colour)
|
||||
{
|
||||
colour = Vector3(1, 1, 1);
|
||||
}
|
||||
inline void read_colour(Vector3& colour, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, colour))
|
||||
{
|
||||
default_colour(colour);
|
||||
}
|
||||
}
|
||||
inline void write_colour(const Vector3& colour, Entity* entity)
|
||||
{
|
||||
char value[64];
|
||||
|
||||
sprintf(value, "%f %f %f", colour[0], colour[1], colour[2]);
|
||||
entity->setKeyValue("_color", value);
|
||||
}
|
||||
|
||||
class Colour
|
||||
{
|
||||
Callback m_colourChanged;
|
||||
Shader* m_state;
|
||||
|
||||
void capture_state()
|
||||
{
|
||||
m_state = colour_capture_state_fill(m_colour);
|
||||
}
|
||||
void release_state()
|
||||
{
|
||||
colour_release_state_fill(m_colour);
|
||||
}
|
||||
|
||||
public:
|
||||
Vector3 m_colour;
|
||||
|
||||
Colour(const Callback& colourChanged)
|
||||
: m_colourChanged(colourChanged)
|
||||
{
|
||||
default_colour(m_colour);
|
||||
capture_state();
|
||||
}
|
||||
~Colour()
|
||||
{
|
||||
release_state();
|
||||
}
|
||||
|
||||
void colourChanged(const char* value)
|
||||
{
|
||||
release_state();
|
||||
read_colour(m_colour, value);
|
||||
capture_state();
|
||||
|
||||
m_colourChanged();
|
||||
}
|
||||
typedef MemberCaller1<Colour, const char*, &Colour::colourChanged> ColourChangedCaller;
|
||||
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_colour(m_colour, entity);
|
||||
}
|
||||
|
||||
Shader* state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
23
plugins/entity/curve.cpp
Normal file
23
plugins/entity/curve.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "curve.h"
|
||||
|
||||
521
plugins/entity/curve.h
Normal file
521
plugins/entity/curve.h
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_CURVE_H)
|
||||
#define INCLUDED_CURVE_H
|
||||
|
||||
#include "ientity.h"
|
||||
#include "selectable.h"
|
||||
#include "renderable.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "math/curve.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "selectionlib.h"
|
||||
#include "render.h"
|
||||
#include "stringio.h"
|
||||
|
||||
class RenderableCurve : public OpenGLRenderable
|
||||
{
|
||||
public:
|
||||
std::vector<PointVertex> m_vertices;
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
pointvertex_gl_array(&m_vertices.front());
|
||||
glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_vertices.size()));
|
||||
}
|
||||
};
|
||||
|
||||
inline void plotBasisFunction(std::size_t numSegments, int point, int degree)
|
||||
{
|
||||
Knots knots;
|
||||
KnotVector_openUniform(knots, 4, degree);
|
||||
|
||||
globalOutputStream() << "plotBasisFunction point " << point << " of 4, knot vector:";
|
||||
for(Knots::iterator i = knots.begin(); i != knots.end(); ++i)
|
||||
{
|
||||
globalOutputStream() << " " << *i;
|
||||
}
|
||||
globalOutputStream() << "\n";
|
||||
globalOutputStream() << "t=0 basis=" << BSpline_basis(knots, point, degree, 0.0) << "\n";
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
double t = (1.0 / double(numSegments)) * double(i);
|
||||
globalOutputStream() << "t=" << t << " basis=" << BSpline_basis(knots, point, degree, t) << "\n";
|
||||
}
|
||||
globalOutputStream() << "t=1 basis=" << BSpline_basis(knots, point, degree, 1.0) << "\n";
|
||||
}
|
||||
|
||||
inline bool ControlPoints_parse(ControlPoints& controlPoints, const char* value)
|
||||
{
|
||||
StringTokeniser tokeniser(value, " ");
|
||||
|
||||
std::size_t size;
|
||||
if(!string_parse_size(tokeniser.getToken(), size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
controlPoints.resize(size);
|
||||
|
||||
if(!string_equal(tokeniser.getToken(), "("))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for(ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
|
||||
{
|
||||
if(!string_parse_float(tokeniser.getToken(), (*i).x())
|
||||
|| !string_parse_float(tokeniser.getToken(), (*i).y())
|
||||
|| !string_parse_float(tokeniser.getToken(), (*i).z()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!string_equal(tokeniser.getToken(), ")"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void ControlPoints_write(const ControlPoints& controlPoints, StringOutputStream& value)
|
||||
{
|
||||
value << Unsigned(controlPoints.size()) << " (";
|
||||
for(ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
|
||||
{
|
||||
value << " " << (*i).x() << " " << (*i).y() << " " << (*i).z() << " ";
|
||||
}
|
||||
value << ")";
|
||||
}
|
||||
|
||||
inline void ControlPoint_testSelect(const Vector3& point, ObservedSelectable& selectable, Selector& selector, SelectionTest& test)
|
||||
{
|
||||
SelectionIntersection best;
|
||||
test.TestPoint(point, best);
|
||||
if(best.valid())
|
||||
{
|
||||
Selector_add(selector, selectable, best);
|
||||
}
|
||||
}
|
||||
|
||||
class ControlPointTransform
|
||||
{
|
||||
const Matrix4& m_matrix;
|
||||
public:
|
||||
ControlPointTransform(const Matrix4& matrix) : m_matrix(matrix)
|
||||
{
|
||||
}
|
||||
void operator()(Vector3& point) const
|
||||
{
|
||||
matrix4_transform_point(m_matrix, point);
|
||||
}
|
||||
};
|
||||
|
||||
class ControlPointSnap
|
||||
{
|
||||
float m_snap;
|
||||
public:
|
||||
ControlPointSnap(float snap) : m_snap(snap)
|
||||
{
|
||||
}
|
||||
void operator()(Vector3& point) const
|
||||
{
|
||||
vector3_snap(point, m_snap);
|
||||
}
|
||||
};
|
||||
|
||||
const Colour4b colour_vertex(0, 255, 0, 255);
|
||||
const Colour4b colour_selected(0, 0, 255, 255);
|
||||
|
||||
class ControlPointAdd
|
||||
{
|
||||
RenderablePointVector& m_points;
|
||||
public:
|
||||
ControlPointAdd(RenderablePointVector& points) : m_points(points)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& point) const
|
||||
{
|
||||
m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_vertex));
|
||||
}
|
||||
};
|
||||
|
||||
class ControlPointAddSelected
|
||||
{
|
||||
RenderablePointVector& m_points;
|
||||
public:
|
||||
ControlPointAddSelected(RenderablePointVector& points) : m_points(points)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& point) const
|
||||
{
|
||||
m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_selected));
|
||||
}
|
||||
};
|
||||
|
||||
class CurveEditType
|
||||
{
|
||||
public:
|
||||
Shader* m_controlsShader;
|
||||
Shader* m_selectedShader;
|
||||
};
|
||||
|
||||
inline void ControlPoints_write(ControlPoints& controlPoints, const char* key, Entity& entity)
|
||||
{
|
||||
StringOutputStream value(256);
|
||||
if(!controlPoints.empty())
|
||||
{
|
||||
ControlPoints_write(controlPoints, value);
|
||||
}
|
||||
entity.setKeyValue(key, value.c_str());
|
||||
}
|
||||
|
||||
class CurveEdit
|
||||
{
|
||||
SelectionChangeCallback m_selectionChanged;
|
||||
ControlPoints& m_controlPoints;
|
||||
typedef Array<ObservedSelectable> Selectables;
|
||||
Selectables m_selectables;
|
||||
|
||||
RenderablePointVector m_controlsRender;
|
||||
mutable RenderablePointVector m_selectedRender;
|
||||
|
||||
public:
|
||||
typedef Static<CurveEditType> Type;
|
||||
|
||||
CurveEdit(ControlPoints& controlPoints, const SelectionChangeCallback& selectionChanged) :
|
||||
m_selectionChanged(selectionChanged),
|
||||
m_controlPoints(controlPoints),
|
||||
m_controlsRender(GL_POINTS),
|
||||
m_selectedRender(GL_POINTS)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected(const Functor& functor)
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::iterator p = m_controlPoints.begin();
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
functor(*p);
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEachSelected(const Functor& functor) const
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for(Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
functor(*p);
|
||||
}
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
template<typename Functor>
|
||||
const Functor& forEach(const Functor& functor) const
|
||||
{
|
||||
for(ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
|
||||
{
|
||||
functor(*i);
|
||||
}
|
||||
return functor;
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
ASSERT_MESSAGE(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
|
||||
ControlPoints::const_iterator p = m_controlPoints.begin();
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
|
||||
{
|
||||
ControlPoint_testSelect(*p, *i, selector, test);
|
||||
}
|
||||
}
|
||||
|
||||
bool isSelected() const
|
||||
{
|
||||
for(Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i)
|
||||
{
|
||||
if((*i).isSelected())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setSelected(bool selected)
|
||||
{
|
||||
for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i)
|
||||
{
|
||||
(*i).setSelected(selected);
|
||||
}
|
||||
}
|
||||
|
||||
void write(const char* key, Entity& entity)
|
||||
{
|
||||
ControlPoints_write(m_controlPoints, key, entity);
|
||||
}
|
||||
|
||||
void transform(const Matrix4& matrix)
|
||||
{
|
||||
forEachSelected(ControlPointTransform(matrix));
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
forEachSelected(ControlPointSnap(snap));
|
||||
}
|
||||
|
||||
void updateSelected() const
|
||||
{
|
||||
m_selectedRender.clear();
|
||||
forEachSelected(ControlPointAddSelected(m_selectedRender));
|
||||
}
|
||||
|
||||
void renderComponents(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(Type::instance().m_controlsShader, Renderer::eWireframeOnly);
|
||||
renderer.SetState(Type::instance().m_controlsShader, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_controlsRender, localToWorld);
|
||||
}
|
||||
|
||||
void renderComponentsSelected(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
updateSelected();
|
||||
if(!m_selectedRender.empty())
|
||||
{
|
||||
renderer.Highlight(Renderer::ePrimitive, false);
|
||||
renderer.SetState(Type::instance().m_selectedShader, Renderer::eWireframeOnly);
|
||||
renderer.SetState(Type::instance().m_selectedShader, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_selectedRender, localToWorld);
|
||||
}
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
m_selectables.resize(m_controlPoints.size(), m_selectionChanged);
|
||||
|
||||
m_controlsRender.clear();
|
||||
m_controlsRender.reserve(m_controlPoints.size());
|
||||
forEach(ControlPointAdd(m_controlsRender));
|
||||
|
||||
m_selectedRender.reserve(m_controlPoints.size());
|
||||
}
|
||||
typedef MemberCaller<CurveEdit, &CurveEdit::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const int NURBS_degree = 3;
|
||||
|
||||
class NURBSCurve
|
||||
{
|
||||
typedef std::set<Callback> Callbacks;
|
||||
Callbacks m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
public:
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
NURBSWeights m_weights;
|
||||
Knots m_knots;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
|
||||
NURBSCurve(const Callback& boundsChanged) : m_boundsChanged(boundsChanged)
|
||||
{
|
||||
}
|
||||
|
||||
void attach(const Callback& curveChanged)
|
||||
{
|
||||
m_curveChanged.insert(curveChanged);
|
||||
curveChanged();
|
||||
}
|
||||
void detach(const Callback& curveChanged)
|
||||
{
|
||||
m_curveChanged.erase(curveChanged);
|
||||
}
|
||||
void notify()
|
||||
{
|
||||
std::for_each(m_curveChanged.begin(), m_curveChanged.end(), CallbackInvoke());
|
||||
}
|
||||
|
||||
void tesselate()
|
||||
{
|
||||
if(!m_controlPointsTransformed.empty())
|
||||
{
|
||||
const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16;
|
||||
m_renderCurve.m_vertices.resize(numSegments + 1);
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]);
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(NURBS_evaluate(m_controlPointsTransformed, m_weights, m_knots, NURBS_degree, (1.0 / double(numSegments)) * double(i)));
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
tesselate();
|
||||
|
||||
m_bounds = AABB();
|
||||
for(ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i)
|
||||
{
|
||||
aabb_extend_by_point_safe(m_bounds, (*i));
|
||||
}
|
||||
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
|
||||
bool parseCurve(const char* value)
|
||||
{
|
||||
if(!ControlPoints_parse(m_controlPoints, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_weights.resize(m_controlPoints.size());
|
||||
for(NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i)
|
||||
{
|
||||
(*i) = 1;
|
||||
}
|
||||
|
||||
KnotVector_openUniform(m_knots, m_controlPoints.size(), NURBS_degree);
|
||||
|
||||
//plotBasisFunction(8, 0, NURBS_degree);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void curveChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value) || !parseCurve(value))
|
||||
{
|
||||
m_controlPoints.resize(0);
|
||||
m_knots.resize(0);
|
||||
m_weights.resize(0);
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<NURBSCurve, const char*, &NURBSCurve::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
class CatmullRomSpline
|
||||
{
|
||||
typedef std::set<Callback> Callbacks;
|
||||
Callbacks m_curveChanged;
|
||||
Callback m_boundsChanged;
|
||||
public:
|
||||
ControlPoints m_controlPoints;
|
||||
ControlPoints m_controlPointsTransformed;
|
||||
RenderableCurve m_renderCurve;
|
||||
AABB m_bounds;
|
||||
|
||||
CatmullRomSpline(const Callback& boundsChanged) : m_boundsChanged(boundsChanged)
|
||||
{
|
||||
}
|
||||
|
||||
void attach(const Callback& curveChanged)
|
||||
{
|
||||
m_curveChanged.insert(curveChanged);
|
||||
curveChanged();
|
||||
}
|
||||
void detach(const Callback& curveChanged)
|
||||
{
|
||||
m_curveChanged.erase(curveChanged);
|
||||
}
|
||||
void notify()
|
||||
{
|
||||
std::for_each(m_curveChanged.begin(), m_curveChanged.end(), CallbackInvoke());
|
||||
}
|
||||
|
||||
void tesselate()
|
||||
{
|
||||
if(!m_controlPointsTransformed.empty())
|
||||
{
|
||||
const std::size_t numSegments = (m_controlPointsTransformed.size() - 1) * 16;
|
||||
m_renderCurve.m_vertices.resize(numSegments + 1);
|
||||
m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPointsTransformed[0]);
|
||||
for(std::size_t i = 1; i < numSegments; ++i)
|
||||
{
|
||||
m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(CatmullRom_evaluate(m_controlPointsTransformed, (1.0 / double(numSegments)) * double(i)));
|
||||
}
|
||||
m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPointsTransformed[m_controlPointsTransformed.size() - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderCurve.m_vertices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool parseCurve(const char* value)
|
||||
{
|
||||
return ControlPoints_parse(m_controlPoints, value);
|
||||
}
|
||||
|
||||
void curveChanged()
|
||||
{
|
||||
tesselate();
|
||||
|
||||
m_bounds = AABB();
|
||||
for(ControlPoints::iterator i = m_controlPointsTransformed.begin(); i != m_controlPointsTransformed.end(); ++i)
|
||||
{
|
||||
aabb_extend_by_point_safe(m_bounds, (*i));
|
||||
}
|
||||
|
||||
m_boundsChanged();
|
||||
notify();
|
||||
}
|
||||
|
||||
void curveChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value) || !parseCurve(value))
|
||||
{
|
||||
m_controlPoints.resize(0);
|
||||
}
|
||||
m_controlPointsTransformed = m_controlPoints;
|
||||
curveChanged();
|
||||
}
|
||||
typedef MemberCaller1<CatmullRomSpline, const char*, &CatmullRomSpline::curveChanged> CurveChangedCaller;
|
||||
};
|
||||
|
||||
const char* const curve_Nurbs = "curve_Nurbs";
|
||||
const char* const curve_CatmullRomSpline = "curve_CatmullRomSpline";
|
||||
|
||||
|
||||
#endif
|
||||
809
plugins/entity/doom3group.cpp
Normal file
809
plugins/entity/doom3group.cpp
Normal file
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any Doom3 entity which does not have a fixed size specified in its entity-definition (e.g. func_static).
|
||||
///
|
||||
/// This entity behaves as a group only when the "model" key is empty or is the same as the "name" key. Otherwise it behaves as a model.
|
||||
/// When behaving as a group, the "origin" key is the translation to be applied to all brushes (not patches) grouped under this entity.
|
||||
/// When behaving as a model, the "origin", "angle" and "rotation" keys directly control the entity's local-to-parent transform.
|
||||
/// When either the "curve_Nurbs" or "curve_CatmullRomSpline" keys define a curve, the curve is rendered and can be edited.
|
||||
|
||||
#include "doom3group.h"
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "editable.h"
|
||||
#include "modelskin.h"
|
||||
|
||||
#include "selectionlib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "traverselib.h"
|
||||
#include "entitylib.h"
|
||||
#include "render.h"
|
||||
#include "eclasslib.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "pivot.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "origin.h"
|
||||
#include "angle.h"
|
||||
#include "rotation.h"
|
||||
#include "model.h"
|
||||
#include "filters.h"
|
||||
#include "namedentity.h"
|
||||
#include "keyobservers.h"
|
||||
#include "namekeys.h"
|
||||
#include "curve.h"
|
||||
#include "modelskinkey.h"
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
inline void PointVertexArray_testSelect(PointVertex* first, std::size_t count, SelectionTest& test, SelectionIntersection& best)
|
||||
{
|
||||
test.TestLineStrip(
|
||||
VertexPointer(
|
||||
reinterpret_cast<VertexPointer::pointer>(&first->vertex),
|
||||
sizeof(PointVertex)
|
||||
),
|
||||
IndexPointer::index_type(count),
|
||||
best
|
||||
);
|
||||
}
|
||||
|
||||
class Doom3Group :
|
||||
public Bounded,
|
||||
public Snappable
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
TraversableNodeSet m_traverse;
|
||||
MatrixTransform m_transform;
|
||||
|
||||
SingletonModel m_model;
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
RotationKey m_rotationKey;
|
||||
Float9 m_rotation;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
TraversableObserverPairRelay m_traverseObservers;
|
||||
Doom3GroupOrigin m_funcStaticOrigin;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
ModelSkinKey m_skin;
|
||||
|
||||
public:
|
||||
NURBSCurve m_curveNURBS;
|
||||
CatmullRomSpline m_curveCatmullRom;
|
||||
private:
|
||||
mutable AABB m_curveBounds;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
CopiedString m_name;
|
||||
CopiedString m_modelKey;
|
||||
bool m_isModel;
|
||||
|
||||
scene::Traversable* m_traversable;
|
||||
|
||||
void construct()
|
||||
{
|
||||
default_rotation(m_rotation);
|
||||
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("model", Doom3Group::ModelChangedCaller(*this));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey));
|
||||
m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey));
|
||||
m_keyObservers.insert("name", NameChangedCaller(*this));
|
||||
m_keyObservers.insert(curve_Nurbs, NURBSCurve::CurveChangedCaller(m_curveNURBS));
|
||||
m_keyObservers.insert(curve_CatmullRomSpline, CatmullRomSpline::CurveChangedCaller(m_curveCatmullRom));
|
||||
m_keyObservers.insert("skin", ModelSkinKey::SkinChangedCaller(m_skin));
|
||||
|
||||
m_traverseObservers.attach(m_funcStaticOrigin);
|
||||
m_isModel = false;
|
||||
m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group);
|
||||
attachTraverse();
|
||||
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
|
||||
if(isModel())
|
||||
{
|
||||
detachModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
detachTraverse();
|
||||
}
|
||||
|
||||
m_traverseObservers.detach(m_funcStaticOrigin);
|
||||
}
|
||||
|
||||
void attachModel()
|
||||
{
|
||||
m_traversable = &m_model.getTraversable();
|
||||
m_model.attach(&m_traverseObservers);
|
||||
}
|
||||
void detachModel()
|
||||
{
|
||||
m_traversable = 0;
|
||||
m_model.detach(&m_traverseObservers);
|
||||
}
|
||||
void attachTraverse()
|
||||
{
|
||||
m_traversable = &m_traverse;
|
||||
m_traverse.attach(&m_traverseObservers);
|
||||
}
|
||||
void detachTraverse()
|
||||
{
|
||||
m_traversable = 0;
|
||||
m_traverse.detach(&m_traverseObservers);
|
||||
}
|
||||
|
||||
bool isModel() const
|
||||
{
|
||||
return m_isModel;
|
||||
}
|
||||
|
||||
void setIsModel(bool newValue)
|
||||
{
|
||||
if(newValue && !m_isModel)
|
||||
{
|
||||
detachTraverse();
|
||||
attachModel();
|
||||
|
||||
m_nameKeys.setKeyIsName(Static<KeyIsName>::instance().m_keyIsName);
|
||||
m_model.modelChanged(m_modelKey.c_str());
|
||||
}
|
||||
else if(!newValue && m_isModel)
|
||||
{
|
||||
detachModel();
|
||||
attachTraverse();
|
||||
|
||||
m_nameKeys.setKeyIsName(keyIsNameDoom3Doom3Group);
|
||||
}
|
||||
m_isModel = newValue;
|
||||
updateTransform();
|
||||
}
|
||||
|
||||
void updateIsModel()
|
||||
{
|
||||
setIsModel(!string_empty(m_modelKey.c_str()) && !string_equal(m_modelKey.c_str(), m_name.c_str()));
|
||||
}
|
||||
|
||||
void nameChanged(const char* value)
|
||||
{
|
||||
m_name = value;
|
||||
updateIsModel();
|
||||
}
|
||||
typedef MemberCaller1<Doom3Group, const char*, &Doom3Group::nameChanged> NameChangedCaller;
|
||||
|
||||
void modelChanged(const char* value)
|
||||
{
|
||||
m_modelKey = value;
|
||||
updateIsModel();
|
||||
if(isModel())
|
||||
{
|
||||
m_model.modelChanged(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model.modelChanged("");
|
||||
}
|
||||
}
|
||||
typedef MemberCaller1<Doom3Group, const char*, &Doom3Group::modelChanged> ModelChangedCaller;
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
if(isModel())
|
||||
{
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_originKey.m_origin);
|
||||
matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotationKey.m_rotation));
|
||||
}
|
||||
m_transformChanged();
|
||||
if(!isModel())
|
||||
{
|
||||
m_funcStaticOrigin.originChanged();
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<Doom3Group, &Doom3Group::updateTransform> UpdateTransformCaller;
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Doom3Group, &Doom3Group::originChanged> OriginChangedCaller;
|
||||
|
||||
void rotationChanged()
|
||||
{
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<Doom3Group, &Doom3Group::rotationChanged> RotationChangedCaller;
|
||||
|
||||
void skinChanged()
|
||||
{
|
||||
if(isModel())
|
||||
{
|
||||
scene::Node* node = m_model.getNode();
|
||||
if(node != 0)
|
||||
{
|
||||
Node_modelSkinChanged(*node);
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<Doom3Group, &Doom3Group::skinChanged> SkinChangedCaller;
|
||||
|
||||
public:
|
||||
Doom3Group(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_funcStaticOrigin(m_traverse, m_origin),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_curveNURBS(boundsChanged),
|
||||
m_curveCatmullRom(boundsChanged),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform),
|
||||
m_traversable(0)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
Doom3Group(const Doom3Group& other, scene::Node& node, const Callback& transformChanged, const Callback& boundsChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_funcStaticOrigin(m_traverse, m_origin),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_curveNURBS(boundsChanged),
|
||||
m_curveCatmullRom(boundsChanged),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform),
|
||||
m_traversable(0)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~Doom3Group()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
|
||||
m_funcStaticOrigin.enable();
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_funcStaticOrigin.disable();
|
||||
|
||||
m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return *m_traversable;
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
ModelSkin& getModelSkin()
|
||||
{
|
||||
return m_skin.get();
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverseObservers.attach(*observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverseObservers.detach(*observer);
|
||||
}
|
||||
|
||||
const AABB& localAABB() const
|
||||
{
|
||||
m_curveBounds = m_curveNURBS.m_bounds;
|
||||
aabb_extend_by_aabb_safe(m_curveBounds, m_curveCatmullRom.m_bounds);
|
||||
return m_curveBounds;
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
if(isModel() && selected)
|
||||
{
|
||||
m_renderOrigin.render(renderer, volume, localToWorld);
|
||||
}
|
||||
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials);
|
||||
|
||||
if(!m_curveNURBS.m_renderCurve.m_vertices.empty())
|
||||
{
|
||||
renderer.addRenderable(m_curveNURBS.m_renderCurve, localToWorld);
|
||||
}
|
||||
if(!m_curveCatmullRom.m_renderCurve.m_vertices.empty())
|
||||
{
|
||||
renderer.addRenderable(m_curveCatmullRom.m_renderCurve, localToWorld);
|
||||
}
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld, selected);
|
||||
if(g_showNames && isModel())
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test, SelectionIntersection& best)
|
||||
{
|
||||
PointVertexArray_testSelect(&m_curveNURBS.m_renderCurve.m_vertices[0], m_curveNURBS.m_renderCurve.m_vertices.size(), test, best);
|
||||
PointVertexArray_testSelect(&m_curveCatmullRom.m_renderCurve.m_vertices[0], m_curveCatmullRom.m_renderCurve.m_vertices.size(), test, best);
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
rotation_rotate(m_rotation, rotation);
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
m_curveNURBS.m_controlPointsTransformed = m_curveNURBS.m_controlPoints;
|
||||
m_curveCatmullRom.m_controlPointsTransformed = m_curveCatmullRom.m_controlPoints;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
rotation_assign(m_rotationKey.m_rotation, m_rotation);
|
||||
m_rotationKey.write(&m_entity);
|
||||
m_curveNURBS.m_controlPoints = m_curveNURBS.m_controlPointsTransformed;
|
||||
ControlPoints_write(m_curveNURBS.m_controlPoints, curve_Nurbs, m_entity);
|
||||
m_curveCatmullRom.m_controlPoints = m_curveCatmullRom.m_controlPointsTransformed;
|
||||
ControlPoints_write(m_curveCatmullRom.m_controlPoints, curve_CatmullRomSpline, m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
m_curveNURBS.curveChanged();
|
||||
m_curveCatmullRom.curveChanged();
|
||||
}
|
||||
typedef MemberCaller<Doom3Group, &Doom3Group::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class ControlPointAddBounds
|
||||
{
|
||||
AABB& m_bounds;
|
||||
public:
|
||||
ControlPointAddBounds(AABB& bounds) : m_bounds(bounds)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& point) const
|
||||
{
|
||||
aabb_extend_by_point_safe(m_bounds, point);
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3GroupInstance :
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
public Renderable,
|
||||
public SelectionTestable,
|
||||
public ComponentSelectionTestable,
|
||||
public ComponentEditable,
|
||||
public ComponentSnappable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceContainedCast<Doom3GroupInstance, Bounded>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, SelectionTestable>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, ComponentSelectionTestable>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, ComponentEditable>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, ComponentSnappable>::install(m_casts);
|
||||
InstanceStaticCast<Doom3GroupInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<Doom3GroupInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
Doom3Group& m_contained;
|
||||
CurveEdit m_curveNURBS;
|
||||
CurveEdit m_curveCatmullRom;
|
||||
mutable AABB m_aabb_component;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
|
||||
Bounded& get(NullType<Bounded>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
|
||||
STRING_CONSTANT(Name, "Doom3GroupInstance");
|
||||
|
||||
Doom3GroupInstance(const scene::Path& path, scene::Instance* parent, Doom3Group& contained) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
|
||||
TransformModifier(Doom3Group::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
|
||||
m_contained(contained),
|
||||
m_curveNURBS(m_contained.m_curveNURBS.m_controlPointsTransformed, SelectionChangedComponentCaller(*this)),
|
||||
m_curveCatmullRom(m_contained.m_curveCatmullRom.m_controlPointsTransformed, SelectionChangedComponentCaller(*this))
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
m_contained.m_curveNURBS.attach(CurveEdit::CurveChangedCaller(m_curveNURBS));
|
||||
m_contained.m_curveCatmullRom.attach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
|
||||
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~Doom3GroupInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
|
||||
m_contained.m_curveCatmullRom.detach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
|
||||
m_contained.m_curveNURBS.detach(CurveEdit::CurveChangedCaller(m_curveNURBS));
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
|
||||
m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld());
|
||||
m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
|
||||
m_curveNURBS.renderComponentsSelected(renderer, volume, localToWorld());
|
||||
m_curveCatmullRom.renderComponentsSelected(renderer, volume, localToWorld());
|
||||
}
|
||||
void renderComponents(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
if(GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex)
|
||||
{
|
||||
m_curveNURBS.renderComponents(renderer, volume, localToWorld());
|
||||
m_curveCatmullRom.renderComponents(renderer, volume, localToWorld());
|
||||
}
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
test.BeginMesh(localToWorld());
|
||||
SelectionIntersection best;
|
||||
|
||||
m_contained.testSelect(selector, test, best);
|
||||
|
||||
if(best.valid())
|
||||
{
|
||||
Selector_add(selector, getSelectable(), best);
|
||||
}
|
||||
}
|
||||
|
||||
bool isSelectedComponents() const
|
||||
{
|
||||
return m_curveNURBS.isSelected() || m_curveCatmullRom.isSelected();
|
||||
}
|
||||
void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode)
|
||||
{
|
||||
if(mode == SelectionSystem::eVertex)
|
||||
{
|
||||
m_curveNURBS.setSelected(selected);
|
||||
m_curveCatmullRom.setSelected(selected);
|
||||
}
|
||||
}
|
||||
void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
|
||||
{
|
||||
if(mode == SelectionSystem::eVertex)
|
||||
{
|
||||
test.BeginMesh(localToWorld());
|
||||
m_curveNURBS.testSelect(selector, test);
|
||||
m_curveCatmullRom.testSelect(selector, test);
|
||||
}
|
||||
}
|
||||
|
||||
void transformComponents(const Matrix4& matrix)
|
||||
{
|
||||
if(m_curveNURBS.isSelected())
|
||||
{
|
||||
m_curveNURBS.transform(matrix);
|
||||
}
|
||||
if(m_curveCatmullRom.isSelected())
|
||||
{
|
||||
m_curveCatmullRom.transform(matrix);
|
||||
}
|
||||
}
|
||||
|
||||
const AABB& getSelectedComponentsBounds() const
|
||||
{
|
||||
m_aabb_component = AABB();
|
||||
m_curveNURBS.forEachSelected(ControlPointAddBounds(m_aabb_component));
|
||||
m_curveCatmullRom.forEachSelected(ControlPointAddBounds(m_aabb_component));
|
||||
return m_aabb_component;
|
||||
}
|
||||
|
||||
void snapComponents(float snap)
|
||||
{
|
||||
if(m_curveNURBS.isSelected())
|
||||
{
|
||||
m_curveNURBS.snapto(snap);
|
||||
m_curveNURBS.write(curve_Nurbs, m_contained.getEntity());
|
||||
}
|
||||
if(m_curveCatmullRom.isSelected())
|
||||
{
|
||||
m_curveCatmullRom.snapto(snap);
|
||||
m_curveCatmullRom.write(curve_CatmullRomSpline, m_contained.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
}
|
||||
else
|
||||
{
|
||||
transformComponents(calculateTransform());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<Doom3GroupInstance, &Doom3GroupInstance::applyTransform> ApplyTransformCaller;
|
||||
|
||||
void selectionChangedComponent(const Selectable& selectable)
|
||||
{
|
||||
GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable);
|
||||
GlobalSelectionSystem().onComponentSelection(*this, selectable);
|
||||
}
|
||||
typedef MemberCaller1<Doom3GroupInstance, const Selectable&, &Doom3GroupInstance::selectionChangedComponent> SelectionChangedComponentCaller;
|
||||
};
|
||||
|
||||
class Doom3GroupNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<Doom3GroupNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<Doom3GroupNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, Namespaced>::install(m_casts);
|
||||
NodeContainedCast<Doom3GroupNode, ModelSkin>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Doom3Group m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
ModelSkin& get(NullType<ModelSkin>)
|
||||
{
|
||||
return m_contained.getModelSkin();
|
||||
}
|
||||
|
||||
Doom3GroupNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSet::BoundsChangedCaller(m_instances), InstanceSetEvaluateTransform<Doom3GroupInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
Doom3GroupNode(const Doom3GroupNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSet::BoundsChangedCaller(m_instances), InstanceSetEvaluateTransform<Doom3GroupInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~Doom3GroupNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new Doom3GroupNode(*this))->node();
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new Doom3GroupInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
void Doom3Group_construct()
|
||||
{
|
||||
CurveEdit::Type::instance().m_controlsShader = GlobalShaderCache().capture("$POINT");
|
||||
CurveEdit::Type::instance().m_selectedShader = GlobalShaderCache().capture("$SELPOINT");
|
||||
}
|
||||
|
||||
void Doom3Group_destroy()
|
||||
{
|
||||
GlobalShaderCache().release("$SELPOINT");
|
||||
GlobalShaderCache().release("$POINT");
|
||||
}
|
||||
|
||||
scene::Node& New_Doom3Group(EntityClass* eclass)
|
||||
{
|
||||
return (new Doom3GroupNode(eclass))->node();
|
||||
}
|
||||
35
plugins/entity/doom3group.h
Normal file
35
plugins/entity/doom3group.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_STATIC_H)
|
||||
#define INCLUDED_STATIC_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
}
|
||||
class EntityClass;
|
||||
|
||||
void Doom3Group_construct();
|
||||
void Doom3Group_destroy();
|
||||
scene::Node& New_Doom3Group(EntityClass* eclass);
|
||||
|
||||
#endif
|
||||
526
plugins/entity/eclassmodel.cpp
Normal file
526
plugins/entity/eclassmodel.cpp
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which has a fixed size specified in its entity-definition and displays a model (e.g. ammo_bfg).
|
||||
///
|
||||
/// This entity displays the model specified in its entity-definition.
|
||||
/// The "origin" and "angle" keys directly control the entity's local-to-parent transform.
|
||||
/// The "rotation" key directly controls the entity's local-to-parent transform for Doom3 only.
|
||||
|
||||
#include "eclassmodel.h"
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "editable.h"
|
||||
|
||||
#include "selectionlib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "traverselib.h"
|
||||
#include "entitylib.h"
|
||||
#include "render.h"
|
||||
#include "eclasslib.h"
|
||||
#include "pivot.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "origin.h"
|
||||
#include "angle.h"
|
||||
#include "rotation.h"
|
||||
#include "model.h"
|
||||
#include "filters.h"
|
||||
#include "namedentity.h"
|
||||
#include "keyobservers.h"
|
||||
#include "namekeys.h"
|
||||
#include "modelskinkey.h"
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
class EclassModel :
|
||||
public Snappable
|
||||
{
|
||||
MatrixTransform m_transform;
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AngleKey m_angleKey;
|
||||
float m_angle;
|
||||
RotationKey m_rotationKey;
|
||||
Float9 m_rotation;
|
||||
SingletonModel m_model;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
ModelSkinKey m_skin;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
default_rotation(m_rotation);
|
||||
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
m_keyObservers.insert("angle", RotationKey::AngleChangedCaller(m_rotationKey));
|
||||
m_keyObservers.insert("rotation", RotationKey::RotationChangedCaller(m_rotationKey));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_keyObservers.insert("angle", AngleKey::AngleChangedCaller(m_angleKey));
|
||||
}
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
}
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
|
||||
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
matrix4_multiply_by_matrix4(m_transform.localToParent(), rotation_toMatrix(m_rotation));
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix4_multiply_by_matrix4(m_transform.localToParent(), matrix4_rotation_for_z_degrees(m_angle));
|
||||
}
|
||||
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::updateTransform> UpdateTransformCaller;
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::originChanged> OriginChangedCaller;
|
||||
void angleChanged()
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::angleChanged> AngleChangedCaller;
|
||||
void rotationChanged()
|
||||
{
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::rotationChanged> RotationChangedCaller;
|
||||
|
||||
void skinChanged()
|
||||
{
|
||||
scene::Node* node = m_model.getNode();
|
||||
if(node != 0)
|
||||
{
|
||||
Node_modelSkinChanged(*node);
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::skinChanged> SkinChangedCaller;
|
||||
|
||||
public:
|
||||
|
||||
EclassModel(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
EclassModel(const EclassModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_rotationKey(RotationChangedCaller(*this)),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_skin(SkinChangedCaller(*this)),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
m_model.modelChanged(m_entity.getEntityClass().modelpath());
|
||||
m_skin.skinChanged(m_entity.getEntityClass().skin());
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_skin.skinChanged("");
|
||||
m_model.modelChanged("");
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
ModelSkin& getModelSkin()
|
||||
{
|
||||
return m_skin.get();
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.detach(observer);
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
if(selected)
|
||||
{
|
||||
m_renderOrigin.render(renderer, volume, localToWorld);
|
||||
}
|
||||
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld, selected);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_rotate(m_rotation, rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = angle_rotated(m_angle, rotation);
|
||||
}
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_assign(m_rotation, m_rotationKey.m_rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
}
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
rotation_assign(m_rotationKey.m_rotation, m_rotation);
|
||||
m_rotationKey.write(&m_entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angleKey.m_angle = m_angle;
|
||||
m_angleKey.write(&m_entity);
|
||||
}
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModel, &EclassModel::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class EclassModelInstance : public TargetableInstance, public TransformModifier, public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<EclassModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<EclassModelInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<EclassModelInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
EclassModel& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
STRING_CONSTANT(Name, "EclassModelInstance");
|
||||
|
||||
EclassModelInstance(const scene::Path& path, scene::Instance* parent, EclassModel& contained) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
|
||||
TransformModifier(EclassModel::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
|
||||
m_contained(contained)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~EclassModelInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<EclassModelInstance, &EclassModelInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class EclassModelNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<EclassModelNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<EclassModelNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, Namespaced>::install(m_casts);
|
||||
NodeContainedCast<EclassModelNode, ModelSkin>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
EclassModel m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
ModelSkin& get(NullType<ModelSkin>)
|
||||
{
|
||||
return m_contained.getModelSkin();
|
||||
}
|
||||
|
||||
EclassModelNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<EclassModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
EclassModelNode(const EclassModelNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<EclassModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~EclassModelNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new EclassModelNode(*this))->node();
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new EclassModelInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_EclassModel(EntityClass* eclass)
|
||||
{
|
||||
return (new EclassModelNode(eclass))->node();
|
||||
}
|
||||
|
||||
35
plugins/entity/eclassmodel.h
Normal file
35
plugins/entity/eclassmodel.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ECLASSMODEL_H)
|
||||
#define INCLUDED_ECLASSMODEL_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
};
|
||||
class EntityClass;
|
||||
|
||||
scene::Node& New_EclassModel(EntityClass* eclass);
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
#endif
|
||||
383
plugins/entity/entity.cpp
Normal file
383
plugins/entity/entity.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
#include "ifilter.h"
|
||||
#include "selectable.h"
|
||||
#include "namespace.h"
|
||||
|
||||
#include "scenelib.h"
|
||||
#include "entitylib.h"
|
||||
#include "eclasslib.h"
|
||||
#include "pivot.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "uniquenames.h"
|
||||
#include "namekeys.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "filters.h"
|
||||
|
||||
|
||||
#include "miscmodel.h"
|
||||
#include "light.h"
|
||||
#include "group.h"
|
||||
#include "eclassmodel.h"
|
||||
#include "generic.h"
|
||||
#include "doom3group.h"
|
||||
|
||||
|
||||
|
||||
EGameType g_gameType;
|
||||
|
||||
inline scene::Node& entity_for_eclass(EntityClass* eclass)
|
||||
{
|
||||
if(classname_equal(eclass->name(), "misc_model")
|
||||
|| classname_equal(eclass->name(), "misc_gamemodel")
|
||||
|| classname_equal(eclass->name(), "model_static"))
|
||||
{
|
||||
return New_MiscModel(eclass);
|
||||
}
|
||||
else if(classname_equal(eclass->name(), "light")
|
||||
|| classname_equal(eclass->name(), "lightJunior"))
|
||||
{
|
||||
return New_Light(eclass);
|
||||
}
|
||||
if(!eclass->fixedsize)
|
||||
{
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
return New_Doom3Group(eclass);
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_Group(eclass);
|
||||
}
|
||||
}
|
||||
else if(!string_empty(eclass->modelpath()))
|
||||
{
|
||||
return New_EclassModel(eclass);
|
||||
}
|
||||
else
|
||||
{
|
||||
return New_GenericEntity(eclass);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity_setName(Entity& entity, const char* name)
|
||||
{
|
||||
entity.setKeyValue("name", name);
|
||||
}
|
||||
typedef ReferenceCaller1<Entity, const char*, Entity_setName> EntitySetNameCaller;
|
||||
|
||||
inline Namespaced* Node_getNamespaced(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<Namespaced>::cast(node);
|
||||
}
|
||||
|
||||
inline scene::Node& node_for_eclass(EntityClass* eclass)
|
||||
{
|
||||
scene::Node& node = entity_for_eclass(eclass);
|
||||
Node_getEntity(node)->setKeyValue("classname", eclass->name());
|
||||
|
||||
if(g_gameType == eGameTypeDoom3
|
||||
&& string_not_empty(eclass->name())
|
||||
&& !string_equal(eclass->name(), "worldspawn")
|
||||
&& !string_equal(eclass->name(), "UNKNOWN_CLASS"))
|
||||
{
|
||||
char buffer[1024];
|
||||
strcpy(buffer, eclass->name());
|
||||
strcat(buffer, "_1");
|
||||
GlobalNamespace().makeUnique(buffer, EntitySetNameCaller(*Node_getEntity(node)));
|
||||
}
|
||||
|
||||
Namespaced* namespaced = Node_getNamespaced(node);
|
||||
if(namespaced != 0)
|
||||
{
|
||||
namespaced->setNamespace(GlobalNamespace());
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
EntityCreator::KeyValueChangedFunc EntityKeyValues::m_entityKeyValueChanged = 0;
|
||||
EntityCreator::KeyValueChangedFunc KeyValue::m_entityKeyValueChanged = 0;
|
||||
Counter* EntityKeyValues::m_counter = 0;
|
||||
|
||||
bool g_showNames = true;
|
||||
bool g_showAngles = true;
|
||||
bool g_newLightDraw = true;
|
||||
bool g_lightRadii = false;
|
||||
|
||||
class ConnectEntities
|
||||
{
|
||||
public:
|
||||
Entity* m_e1;
|
||||
Entity* m_e2;
|
||||
ConnectEntities(Entity* e1, Entity* e2) : m_e1(e1), m_e2(e2)
|
||||
{
|
||||
}
|
||||
void connect(const char* name)
|
||||
{
|
||||
m_e1->setKeyValue("target", name);
|
||||
m_e2->setKeyValue("targetname", name);
|
||||
}
|
||||
typedef MemberCaller1<ConnectEntities, const char*, &ConnectEntities::connect> ConnectCaller;
|
||||
};
|
||||
|
||||
inline Entity* ScenePath_getEntity(const scene::Path& path)
|
||||
{
|
||||
Entity* entity = Node_getEntity(path.top());
|
||||
if(entity == 0)
|
||||
{
|
||||
entity = Node_getEntity(path.parent());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
class Quake3EntityCreator : public EntityCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createEntity(EntityClass* eclass)
|
||||
{
|
||||
return node_for_eclass(eclass);
|
||||
}
|
||||
void setKeyValueChangedFunc(KeyValueChangedFunc func)
|
||||
{
|
||||
EntityKeyValues::setKeyValueChangedFunc(func);
|
||||
}
|
||||
void setCounter(Counter* counter)
|
||||
{
|
||||
EntityKeyValues::setCounter(counter);
|
||||
}
|
||||
void connectEntities(const scene::Path& path, const scene::Path& targetPath)
|
||||
{
|
||||
Entity* e1 = ScenePath_getEntity(path);
|
||||
Entity* e2 = ScenePath_getEntity(targetPath);
|
||||
|
||||
if(e1 == 0 || e2 == 0)
|
||||
{
|
||||
globalErrorStream() << "entityConnectSelected: both of the selected instances must be an entity\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if(e1 == e2)
|
||||
{
|
||||
globalErrorStream() << "entityConnectSelected: the selected instances must not both be from the same entity\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
UndoableCommand undo("entityConnectSelected");
|
||||
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
StringOutputStream key(16);
|
||||
for(unsigned int i = 0; ; ++i)
|
||||
{
|
||||
key << "target";
|
||||
if(i != 0)
|
||||
{
|
||||
key << i;
|
||||
}
|
||||
const char* value = e1->getKeyValue(key.c_str());
|
||||
if(string_empty(value))
|
||||
{
|
||||
e1->setKeyValue(key.c_str(), e2->getKeyValue("name"));
|
||||
break;
|
||||
}
|
||||
key.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectEntities connector(e1, e2);
|
||||
const char* value = e2->getKeyValue("targetname");
|
||||
if(string_empty(value))
|
||||
{
|
||||
value = e1->getKeyValue("target");
|
||||
}
|
||||
if(!string_empty(value))
|
||||
{
|
||||
connector.connect(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* type = e2->getKeyValue("classname");
|
||||
if(string_empty(type))
|
||||
{
|
||||
type = "t";
|
||||
}
|
||||
StringOutputStream key(64);
|
||||
key << type << "1";
|
||||
GlobalNamespace().makeUnique(key.c_str(), ConnectEntities::ConnectCaller(connector));
|
||||
}
|
||||
}
|
||||
|
||||
SceneChangeNotify();
|
||||
}
|
||||
void setLightRadii(bool lightRadii)
|
||||
{
|
||||
g_lightRadii = lightRadii;
|
||||
}
|
||||
bool getLightRadii()
|
||||
{
|
||||
return g_lightRadii;
|
||||
}
|
||||
void setShowNames(bool showNames)
|
||||
{
|
||||
g_showNames = showNames;
|
||||
}
|
||||
bool getShowNames()
|
||||
{
|
||||
return g_showNames;
|
||||
}
|
||||
void setShowAngles(bool showAngles)
|
||||
{
|
||||
g_showAngles = showAngles;
|
||||
}
|
||||
bool getShowAngles()
|
||||
{
|
||||
return g_showAngles;
|
||||
}
|
||||
};
|
||||
|
||||
Quake3EntityCreator g_Quake3EntityCreator;
|
||||
|
||||
EntityCreator& GetEntityCreator()
|
||||
{
|
||||
return g_Quake3EntityCreator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class filter_entity_classname : public EntityFilter
|
||||
{
|
||||
const char* m_classname;
|
||||
public:
|
||||
filter_entity_classname(const char* classname) : m_classname(classname)
|
||||
{
|
||||
}
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal(entity.getKeyValue("classname"), m_classname);
|
||||
}
|
||||
};
|
||||
|
||||
class filter_entity_classgroup : public EntityFilter
|
||||
{
|
||||
const char* m_classgroup;
|
||||
std::size_t m_length;
|
||||
public:
|
||||
filter_entity_classgroup(const char* classgroup) : m_classgroup(classgroup), m_length(string_length(m_classgroup))
|
||||
{
|
||||
}
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal_n(entity.getKeyValue("classname"), m_classgroup, m_length);
|
||||
}
|
||||
};
|
||||
|
||||
filter_entity_classname g_filter_entity_world("worldspawn");
|
||||
filter_entity_classname g_filter_entity_func_group("func_group");
|
||||
filter_entity_classname g_filter_entity_light("light");
|
||||
filter_entity_classname g_filter_entity_misc_model("misc_model");
|
||||
filter_entity_classgroup g_filter_entity_trigger("trigger_");
|
||||
filter_entity_classgroup g_filter_entity_path("path_");
|
||||
|
||||
class filter_entity_doom3model : public EntityFilter
|
||||
{
|
||||
public:
|
||||
bool filter(const Entity& entity) const
|
||||
{
|
||||
return string_equal(entity.getKeyValue("classname"), "func_static")
|
||||
&& !string_equal(entity.getKeyValue("model"), entity.getKeyValue("name"));
|
||||
}
|
||||
};
|
||||
|
||||
filter_entity_doom3model g_filter_entity_doom3model;
|
||||
|
||||
|
||||
void Entity_InitFilters()
|
||||
{
|
||||
add_entity_filter(g_filter_entity_world, EXCLUDE_WORLD);
|
||||
add_entity_filter(g_filter_entity_func_group, EXCLUDE_WORLD);
|
||||
add_entity_filter(g_filter_entity_world, EXCLUDE_ENT, true);
|
||||
add_entity_filter(g_filter_entity_trigger, EXCLUDE_TRIGGERS);
|
||||
add_entity_filter(g_filter_entity_misc_model, EXCLUDE_MODELS);
|
||||
add_entity_filter(g_filter_entity_doom3model, EXCLUDE_MODELS);
|
||||
add_entity_filter(g_filter_entity_light, EXCLUDE_LIGHTS);
|
||||
add_entity_filter(g_filter_entity_path, EXCLUDE_PATHS);
|
||||
}
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
|
||||
void Entity_Construct(EGameType gameType)
|
||||
{
|
||||
g_gameType = gameType;
|
||||
if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
g_targetable_nameKey = "name";
|
||||
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameDoom3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "name";
|
||||
}
|
||||
else
|
||||
{
|
||||
Static<KeyIsName>::instance().m_keyIsName = keyIsNameQuake3;
|
||||
Static<KeyIsName>::instance().m_nameKey = "targetname";
|
||||
}
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("SI_ShowNames", BoolImportStringCaller(g_showNames), BoolExportStringCaller(g_showNames));
|
||||
GlobalPreferenceSystem().registerPreference("SI_ShowAngles", BoolImportStringCaller(g_showAngles), BoolExportStringCaller(g_showAngles));
|
||||
GlobalPreferenceSystem().registerPreference("NewLightStyle", BoolImportStringCaller(g_newLightDraw), BoolExportStringCaller(g_newLightDraw));
|
||||
GlobalPreferenceSystem().registerPreference("LightRadiuses", BoolImportStringCaller(g_lightRadii), BoolExportStringCaller(g_lightRadii));
|
||||
|
||||
Entity_InitFilters();
|
||||
LightType lightType = LIGHTTYPE_DEFAULT;
|
||||
if(g_gameType == eGameTypeRTCW)
|
||||
{
|
||||
lightType = LIGHTTYPE_RTCW;
|
||||
}
|
||||
else if(g_gameType == eGameTypeDoom3)
|
||||
{
|
||||
lightType = LIGHTTYPE_DOOM3;
|
||||
}
|
||||
Light_Construct(lightType);
|
||||
MiscModel_construct();
|
||||
Doom3Group_construct();
|
||||
|
||||
RenderablePivot::StaticShader::instance() = GlobalShaderCache().capture("$PIVOT");
|
||||
|
||||
GlobalShaderCache().attachRenderable(StaticRenderableConnectionLines::instance());
|
||||
}
|
||||
|
||||
void Entity_Destroy()
|
||||
{
|
||||
GlobalShaderCache().detachRenderable(StaticRenderableConnectionLines::instance());
|
||||
|
||||
GlobalShaderCache().release("$PIVOT");
|
||||
|
||||
Doom3Group_destroy();
|
||||
MiscModel_destroy();
|
||||
Light_Destroy();
|
||||
}
|
||||
230
plugins/entity/entity.dsp
Normal file
230
plugins/entity/entity.dsp
Normal file
@@ -0,0 +1,230 @@
|
||||
# Microsoft Developer Studio Project File - Name="entity" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=entity - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "entity.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "entity.mak" CFG="entity - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "entity - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "entity - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "entity"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "entity - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\..\libxml2\include\\" /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\libs\nvtristrip" /I "..\..\..\STLPort\stlport" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 mathlib.lib glib-2.0.lib /nologo /dll /machine:I386 /def:".\entity.def" /libpath:"..\..\libs\mathlib\release" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\entity.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "entity - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\shared" /I "..\..\..\libxml2\include" /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\libs\nvtristrip" /I "..\..\..\STLPort\stlport" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAP_EXPORTS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 mathlib.lib glib-2.0.lib /nologo /dll /debug /machine:I386 /def:".\entity.def" /pdbtype:sept /libpath:"..\..\libs\mathlib\debug" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\entity.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "entity - Win32 Release"
|
||||
# Name "entity - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\eclassmodel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\entity.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\entity.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\generic.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\group.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\light.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\miscmodel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\targetable.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Group "API"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\ifilesystem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\igl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\imodel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\ishaders.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\isurface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\qerplugin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\qertypes.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\angle.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\angles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\colour.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\entity.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\light.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\model.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\origin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\plugin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\scale.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\targetable.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
46
plugins/entity/entity.h
Normal file
46
plugins/entity/entity.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ENTITY_H)
|
||||
#define INCLUDED_ENTITY_H
|
||||
|
||||
class EntityCreator;
|
||||
EntityCreator& GetEntityCreator();
|
||||
|
||||
enum EGameType
|
||||
{
|
||||
eGameTypeQuake3,
|
||||
eGameTypeRTCW,
|
||||
eGameTypeDoom3,
|
||||
};
|
||||
|
||||
extern EGameType g_gameType;
|
||||
|
||||
class FilterSystem;
|
||||
void Entity_Construct(EGameType gameType = eGameTypeQuake3);
|
||||
void Entity_Destroy();
|
||||
|
||||
extern bool g_showNames;
|
||||
extern bool g_showAngles;
|
||||
extern bool g_newLightDraw;
|
||||
extern bool g_lightRadii;
|
||||
|
||||
#endif
|
||||
7
plugins/entity/entityq3.def
Normal file
7
plugins/entity/entityq3.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; entityq3.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ENTITYQ3"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
343
plugins/entity/entityq3.vcproj
Normal file
343
plugins/entity/entityq3.vcproj
Normal file
@@ -0,0 +1,343 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="entityq3"
|
||||
ProjectGUID="{49C5823A-5E50-4029-ACEE-1627EBB79E47}"
|
||||
RootNamespace="entityq3"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ENTITYQ3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/entityq3.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/entityq3.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/entityq3.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules"
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ENTITYQ3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/entityq3.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/entityq3.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules"
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="entities"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\doom3group.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\doom3group.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclassmodel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclassmodel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\generic.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\generic.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\group.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\group.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\light.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\light.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\miscmodel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\miscmodel.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="modules"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\entity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\skincache.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\skincache.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="components"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\angle.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\angle.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\angles.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\angles.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\colour.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\colour.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\curve.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\curve.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filters.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filters.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\keyobservers.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\keyobservers.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\model.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\model.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\modelskinkey.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\modelskinkey.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\namedentity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\namedentity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\namekeys.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\namekeys.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\origin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\origin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rotation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rotation.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\scale.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\scale.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\targetable.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\targetable.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entityq3.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
72
plugins/entity/filters.cpp
Normal file
72
plugins/entity/filters.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "filters.h"
|
||||
|
||||
#include "ifilter.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class EntityFilterWrapper : public Filter
|
||||
{
|
||||
bool m_active;
|
||||
bool m_invert;
|
||||
EntityFilter& m_filter;
|
||||
public:
|
||||
EntityFilterWrapper(EntityFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
|
||||
{
|
||||
}
|
||||
void setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
}
|
||||
bool active()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
bool filter(const Entity& entity)
|
||||
{
|
||||
return m_invert ^ m_filter.filter(entity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::list<EntityFilterWrapper> EntityFilters;
|
||||
EntityFilters g_entityFilters;
|
||||
|
||||
void add_entity_filter(EntityFilter& filter, int mask, bool invert)
|
||||
{
|
||||
g_entityFilters.push_back(EntityFilterWrapper(filter, invert));
|
||||
GlobalFilterSystem().addFilter(g_entityFilters.back(), mask);
|
||||
}
|
||||
|
||||
bool entity_filtered(Entity& entity)
|
||||
{
|
||||
for(EntityFilters::iterator i = g_entityFilters.begin(); i != g_entityFilters.end(); ++i)
|
||||
{
|
||||
if((*i).active() && (*i).filter(entity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
82
plugins/entity/filters.h
Normal file
82
plugins/entity/filters.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_FILTERS_H)
|
||||
#define INCLUDED_FILTERS_H
|
||||
|
||||
#include "ifilter.h"
|
||||
|
||||
#include "generic/callback.h"
|
||||
#include "scenelib.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
class EntityFilter
|
||||
{
|
||||
public:
|
||||
virtual bool filter(const Entity& entity) const = 0;
|
||||
};
|
||||
|
||||
bool entity_filtered(Entity& entity);
|
||||
void add_entity_filter(EntityFilter& filter, int mask, bool invert = false);
|
||||
|
||||
class ClassnameFilter : public Filterable
|
||||
{
|
||||
scene::Node& m_node;
|
||||
public:
|
||||
Entity& m_entity;
|
||||
|
||||
ClassnameFilter(Entity& entity, scene::Node& node) : m_node(node), m_entity(entity)
|
||||
{
|
||||
}
|
||||
~ClassnameFilter()
|
||||
{
|
||||
}
|
||||
|
||||
void instanceAttach()
|
||||
{
|
||||
GlobalFilterSystem().registerFilterable(*this);
|
||||
}
|
||||
void instanceDetach()
|
||||
{
|
||||
GlobalFilterSystem().unregisterFilterable(*this);
|
||||
}
|
||||
|
||||
void updateFiltered()
|
||||
{
|
||||
if(entity_filtered(m_entity))
|
||||
{
|
||||
m_node.enable(scene::Node::eFiltered);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_node.disable(scene::Node::eFiltered);
|
||||
}
|
||||
}
|
||||
|
||||
void classnameChanged(const char* value)
|
||||
{
|
||||
updateFiltered();
|
||||
}
|
||||
typedef MemberCaller1<ClassnameFilter, const char*, &ClassnameFilter::classnameChanged> ClassnameChangedCaller;
|
||||
};
|
||||
|
||||
#endif
|
||||
494
plugins/entity/generic.cpp
Normal file
494
plugins/entity/generic.cpp
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which has a fixed size specified in its entity-definition and does not display a model (e.g. info_player_start).
|
||||
///
|
||||
/// This entity displays an axis-aligned bounding box of the size and colour specified in its entity-definition.
|
||||
/// The "origin" key directly controls the entity's local-to-parent transform.
|
||||
/// An arrow is drawn to visualise the "angle" key.
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "editable.h"
|
||||
|
||||
#include "math/frustum.h"
|
||||
#include "selectionlib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "entitylib.h"
|
||||
#include "render.h"
|
||||
#include "eclasslib.h"
|
||||
#include "math/line.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "origin.h"
|
||||
#include "angle.h"
|
||||
#include "filters.h"
|
||||
#include "namedentity.h"
|
||||
#include "keyobservers.h"
|
||||
#include "namekeys.h"
|
||||
#include "rotation.h"
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
|
||||
class RenderableArrow : public OpenGLRenderable
|
||||
{
|
||||
const Ray& m_ray;
|
||||
|
||||
public:
|
||||
RenderableArrow(const Ray& ray)
|
||||
: m_ray(ray)
|
||||
{
|
||||
}
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
arrow_draw(m_ray.origin, m_ray.direction);
|
||||
}
|
||||
};
|
||||
|
||||
inline void read_aabb(AABB& aabb, const EntityClass& eclass)
|
||||
{
|
||||
aabb = aabb_for_minmax(eclass.mins, eclass.maxs);
|
||||
}
|
||||
|
||||
|
||||
class GenericEntity :
|
||||
public Cullable,
|
||||
public Bounded,
|
||||
public Snappable
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AngleKey m_angleKey;
|
||||
float m_angle;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
|
||||
AABB m_aabb_local;
|
||||
Ray m_ray;
|
||||
|
||||
RenderableArrow m_arrow;
|
||||
RenderableSolidAABB m_aabb_solid;
|
||||
RenderableWireframeAABB m_aabb_wire;
|
||||
RenderableNamedEntity m_renderName;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
read_aabb(m_aabb_local, m_entity.getEntityClass());
|
||||
m_ray.origin = m_aabb_local.origin;
|
||||
m_ray.direction[0] = 1;
|
||||
m_ray.direction[1] = 0;
|
||||
m_ray.direction[2] = 0;
|
||||
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("angle", AngleKey::AngleChangedCaller(m_angleKey));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
}
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_translate_by_vec3(m_transform.localToParent(), m_origin);
|
||||
m_ray.direction = matrix4_transformed_direction(matrix4_rotation_for_z(degrees_to_radians(m_angle)), Vector3(1, 0, 0));
|
||||
m_transformChanged();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::updateTransform> UpdateTransformCaller;
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::originChanged> OriginChangedCaller;
|
||||
void angleChanged()
|
||||
{
|
||||
m_angle = m_angleKey.m_angle;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::angleChanged> AngleChangedCaller;
|
||||
public:
|
||||
|
||||
GenericEntity(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_arrow(m_ray),
|
||||
m_aabb_solid(m_aabb_local),
|
||||
m_aabb_wire(m_aabb_local),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
GenericEntity(const GenericEntity& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_angleKey(AngleChangedCaller(*this)),
|
||||
m_angle(ANGLEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_arrow(m_ray),
|
||||
m_aabb_solid(m_aabb_local),
|
||||
m_aabb_wire(m_aabb_local),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
const AABB& localAABB() const
|
||||
{
|
||||
return m_aabb_local;
|
||||
}
|
||||
|
||||
VolumeIntersectionValue intersectVolume(const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
return volume.TestAABB(localAABB(), localToWorld);
|
||||
}
|
||||
|
||||
void renderArrow(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
if(g_showAngles)
|
||||
{
|
||||
renderer.addRenderable(m_arrow, localToWorld);
|
||||
}
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_fill, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_aabb_solid, localToWorld);
|
||||
renderArrow(renderer, volume, localToWorld);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
renderer.addRenderable(m_aabb_wire, localToWorld);
|
||||
renderArrow(renderer, volume, localToWorld);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test, const Matrix4& localToWorld)
|
||||
{
|
||||
test.BeginMesh(localToWorld);
|
||||
|
||||
SelectionIntersection best;
|
||||
aabb_testselect(m_aabb_local, test, best);
|
||||
if(best.valid())
|
||||
{
|
||||
selector.addIntersection(best);
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
m_angle = angle_rotated(m_angle, rotation);
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angle = m_angleKey.m_angle;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
m_angleKey.m_angle = m_angle;
|
||||
m_angleKey.write(&m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntity, &GenericEntity::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class GenericEntityInstance :
|
||||
public TargetableInstance,
|
||||
public TransformModifier,
|
||||
public Renderable,
|
||||
public SelectionTestable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceContainedCast<GenericEntityInstance, Bounded>::install(m_casts);
|
||||
InstanceContainedCast<GenericEntityInstance, Cullable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, SelectionTestable>::install(m_casts);
|
||||
InstanceStaticCast<GenericEntityInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<GenericEntityInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
GenericEntity& m_contained;
|
||||
mutable AABB m_bounds;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Bounded& get(NullType<Bounded>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
Cullable& get(NullType<Cullable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
|
||||
STRING_CONSTANT(Name, "GenericEntityInstance");
|
||||
|
||||
GenericEntityInstance(const scene::Path& path, scene::Instance* parent, GenericEntity& contained) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
|
||||
TransformModifier(GenericEntity::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
|
||||
m_contained(contained)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~GenericEntityInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
m_contained.testSelect(selector, test, Instance::localToWorld());
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<GenericEntityInstance, &GenericEntityInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class GenericEntityNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<GenericEntityNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<GenericEntityNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<GenericEntityNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
InstanceSet m_instances;
|
||||
|
||||
scene::Node m_node;
|
||||
GenericEntity m_contained;
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
GenericEntityNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
|
||||
{
|
||||
}
|
||||
GenericEntityNode(const GenericEntityNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<GenericEntityInstance>::Caller(m_instances))
|
||||
{
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new GenericEntityNode(*this))->node();
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new GenericEntityInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_GenericEntity(EntityClass* eclass)
|
||||
{
|
||||
return (new GenericEntityNode(eclass))->node();
|
||||
}
|
||||
27
plugins/entity/generic.h
Normal file
27
plugins/entity/generic.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GENERIC_H)
|
||||
#define INCLUDED_GENERIC_H
|
||||
|
||||
scene::Node& New_GenericEntity(EntityClass* eclass);
|
||||
|
||||
#endif
|
||||
444
plugins/entity/group.cpp
Normal file
444
plugins/entity/group.cpp
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents any entity which does not have a fixed size specified in its entity-definition (except misc_model).
|
||||
///
|
||||
/// This entity behaves as a group, i.e. it contains brushes.
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "editable.h"
|
||||
|
||||
#include "selectionlib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "traverselib.h"
|
||||
#include "entitylib.h"
|
||||
#include "render.h"
|
||||
#include "eclasslib.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "origin.h"
|
||||
#include "angles.h"
|
||||
#include "scale.h"
|
||||
#include "filters.h"
|
||||
#include "namedentity.h"
|
||||
#include "keyobservers.h"
|
||||
#include "namekeys.h"
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
class Group
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
TraversableNodeSet m_traverse;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
|
||||
RenderableNamedEntity m_renderName;
|
||||
|
||||
Callback m_transformChanged;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
}
|
||||
|
||||
public:
|
||||
Group(EntityClass* eclass, scene::Node& node, const Callback& transformChanged) :
|
||||
m_entity(eclass),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
Group(const Group& other, scene::Node& node, const Callback& transformChanged) :
|
||||
m_entity(other.m_entity),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_traverse;
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.detach(observer);
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld);
|
||||
#if 0
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, g_matrix4_identity);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
class TransformableSetTranslation
|
||||
{
|
||||
Translation m_value;
|
||||
public:
|
||||
TransformableSetTranslation(const Translation& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setTranslation(m_value);
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetRotation
|
||||
{
|
||||
Rotation m_value;
|
||||
public:
|
||||
TransformableSetRotation(const Rotation& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setRotation(m_value);
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetScale
|
||||
{
|
||||
Scale m_value;
|
||||
public:
|
||||
TransformableSetScale(const Scale& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setScale(m_value);
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableSetType
|
||||
{
|
||||
TransformModifierType m_value;
|
||||
public:
|
||||
TransformableSetType(const TransformModifierType& value) : m_value(value)
|
||||
{
|
||||
}
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.setType(m_value);
|
||||
}
|
||||
};
|
||||
|
||||
class TransformableFreezeTransform
|
||||
{
|
||||
TransformModifierType m_value;
|
||||
public:
|
||||
void operator()(Transformable& transformable) const
|
||||
{
|
||||
transformable.freezeTransform();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Functor>
|
||||
inline void Scene_forEachChildTransformable(const Functor& functor, const scene::Path& path)
|
||||
{
|
||||
GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Transformable, Functor> >(functor), path);
|
||||
}
|
||||
#endif
|
||||
|
||||
class GroupInstance :
|
||||
public TargetableInstance,
|
||||
#if 0
|
||||
public Transformable,
|
||||
#endif
|
||||
public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<GroupInstance, Renderable>::install(m_casts);
|
||||
#if 0
|
||||
InstanceStaticCast<GroupInstance, Transformable>::install(m_casts);
|
||||
#endif
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
Group& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
GroupInstance(const scene::Path& path, scene::Instance* parent, Group& group) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), group.getEntity(), *this),
|
||||
m_contained(group)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~GroupInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
|
||||
#if 0
|
||||
void setType(TransformModifierType type)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetType(type), Instance::path());
|
||||
}
|
||||
void setTranslation(const Translation& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetTranslation(value), Instance::path());
|
||||
}
|
||||
void setRotation(const Rotation& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetRotation(value), Instance::path());
|
||||
}
|
||||
void setScale(const Scale& value)
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableSetScale(value), Instance::path());
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
Scene_forEachChildTransformable(TransformableFreezeTransform(), Instance::path());
|
||||
}
|
||||
|
||||
void evaluateTransform()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class GroupNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<GroupNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<GroupNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<GroupNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Group m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
GroupNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
GroupNode(const GroupNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~GroupNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new GroupNode(*this))->node();
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new GroupInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_Group(EntityClass* eclass)
|
||||
{
|
||||
return (new GroupNode(eclass))->node();
|
||||
}
|
||||
27
plugins/entity/group.h
Normal file
27
plugins/entity/group.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GROUP_H)
|
||||
#define INCLUDED_GROUP_H
|
||||
|
||||
scene::Node& New_Group(EntityClass* eclass);
|
||||
|
||||
#endif
|
||||
23
plugins/entity/keyobservers.cpp
Normal file
23
plugins/entity/keyobservers.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "keyobservers.h"
|
||||
|
||||
53
plugins/entity/keyobservers.h
Normal file
53
plugins/entity/keyobservers.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_KEYOBSERVERS_H)
|
||||
#define INCLUDED_KEYOBSERVERS_H
|
||||
|
||||
#include "entitylib.h"
|
||||
#include <map>
|
||||
|
||||
class KeyObserverMap : public EntityKeyValues::Observer
|
||||
{
|
||||
typedef std::multimap<const char*, KeyObserver, RawStringLess> KeyObservers;
|
||||
KeyObservers m_keyObservers;
|
||||
public:
|
||||
void insert(const char* key, const KeyObserver& observer)
|
||||
{
|
||||
m_keyObservers.insert(KeyObservers::value_type(key, observer));
|
||||
}
|
||||
void insert(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
for(KeyObservers::const_iterator i = m_keyObservers.find(key); i != m_keyObservers.end() && string_equal((*i).first, key); ++i)
|
||||
{
|
||||
value.attach((*i).second);
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
for(KeyObservers::const_iterator i = m_keyObservers.find(key); i != m_keyObservers.end() && string_equal((*i).first, key); ++i)
|
||||
{
|
||||
value.detach((*i).second);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
1839
plugins/entity/light.cpp
Normal file
1839
plugins/entity/light.cpp
Normal file
File diff suppressed because it is too large
Load Diff
41
plugins/entity/light.h
Normal file
41
plugins/entity/light.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_LIGHT_H)
|
||||
#define INCLUDED_LIGHT_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
};
|
||||
class EntityClass;
|
||||
|
||||
scene::Node& New_Light(EntityClass* eclass);
|
||||
enum LightType
|
||||
{
|
||||
LIGHTTYPE_DEFAULT,
|
||||
LIGHTTYPE_RTCW,
|
||||
LIGHTTYPE_DOOM3
|
||||
};
|
||||
void Light_Construct(LightType lightType);
|
||||
void Light_Destroy();
|
||||
|
||||
#endif
|
||||
470
plugins/entity/miscmodel.cpp
Normal file
470
plugins/entity/miscmodel.cpp
Normal file
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
///\file
|
||||
///\brief Represents the Quake3 misc_model entity.
|
||||
///
|
||||
/// This entity displays the model specified in its "model" key.
|
||||
/// The "origin", "angles" and "modelscale*" keys directly control the entity's local-to-parent transform.
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "editable.h"
|
||||
|
||||
#include "selectionlib.h"
|
||||
#include "instancelib.h"
|
||||
#include "transformlib.h"
|
||||
#include "traverselib.h"
|
||||
#include "entitylib.h"
|
||||
#include "eclasslib.h"
|
||||
#include "render.h"
|
||||
#include "pivot.h"
|
||||
|
||||
#include "targetable.h"
|
||||
#include "origin.h"
|
||||
#include "angles.h"
|
||||
#include "scale.h"
|
||||
#include "model.h"
|
||||
#include "filters.h"
|
||||
#include "namedentity.h"
|
||||
#include "keyobservers.h"
|
||||
#include "namekeys.h"
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
class MiscModel :
|
||||
public Snappable
|
||||
{
|
||||
EntityKeyValues m_entity;
|
||||
KeyObserverMap m_keyObservers;
|
||||
MatrixTransform m_transform;
|
||||
|
||||
OriginKey m_originKey;
|
||||
Vector3 m_origin;
|
||||
AnglesKey m_anglesKey;
|
||||
Vector3 m_angles;
|
||||
ScaleKey m_scaleKey;
|
||||
Vector3 m_scale;
|
||||
|
||||
SingletonModel m_model;
|
||||
|
||||
ClassnameFilter m_filter;
|
||||
NamedEntity m_named;
|
||||
NameKeys m_nameKeys;
|
||||
RenderablePivot m_renderOrigin;
|
||||
RenderableNamedEntity m_renderName;
|
||||
|
||||
Callback m_transformChanged;
|
||||
Callback m_evaluateTransform;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_keyObservers.insert("classname", ClassnameFilter::ClassnameChangedCaller(m_filter));
|
||||
m_keyObservers.insert(Static<KeyIsName>::instance().m_nameKey, NamedEntity::IdentifierChangedCaller(m_named));
|
||||
m_keyObservers.insert("model", SingletonModel::ModelChangedCaller(m_model));
|
||||
m_keyObservers.insert("origin", OriginKey::OriginChangedCaller(m_originKey));
|
||||
m_keyObservers.insert("angle", AnglesKey::AngleChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("angles", AnglesKey::AnglesChangedCaller(m_anglesKey));
|
||||
m_keyObservers.insert("modelscale", ScaleKey::UniformScaleChangedCaller(m_scaleKey));
|
||||
m_keyObservers.insert("modelscale_vec", ScaleKey::ScaleChangedCaller(m_scaleKey));
|
||||
}
|
||||
|
||||
void updateTransform()
|
||||
{
|
||||
m_transform.localToParent() = g_matrix4_identity;
|
||||
matrix4_transform_by_euler_xyz_degrees(m_transform.localToParent(), m_origin, m_angles, m_scale);
|
||||
m_transformChanged();
|
||||
}
|
||||
void originChanged()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::originChanged> OriginChangedCaller;
|
||||
void anglesChanged()
|
||||
{
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::anglesChanged> AnglesChangedCaller;
|
||||
void scaleChanged()
|
||||
{
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::scaleChanged> ScaleChangedCaller;
|
||||
public:
|
||||
|
||||
MiscModel(EntityClass* eclass, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(eclass),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_scaleKey(ScaleChangedCaller(*this)),
|
||||
m_scale(SCALEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
MiscModel(const MiscModel& other, scene::Node& node, const Callback& transformChanged, const Callback& evaluateTransform) :
|
||||
m_entity(other.m_entity),
|
||||
m_originKey(OriginChangedCaller(*this)),
|
||||
m_origin(ORIGINKEY_IDENTITY),
|
||||
m_anglesKey(AnglesChangedCaller(*this)),
|
||||
m_angles(ANGLESKEY_IDENTITY),
|
||||
m_scaleKey(ScaleChangedCaller(*this)),
|
||||
m_scale(SCALEKEY_IDENTITY),
|
||||
m_filter(m_entity, node),
|
||||
m_named(m_entity),
|
||||
m_nameKeys(m_entity),
|
||||
m_renderName(m_named, g_vector3_identity),
|
||||
m_transformChanged(transformChanged),
|
||||
m_evaluateTransform(evaluateTransform)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
InstanceCounter m_instanceCounter;
|
||||
void instanceAttach(const scene::Path& path)
|
||||
{
|
||||
if(++m_instanceCounter.m_count == 1)
|
||||
{
|
||||
m_filter.instanceAttach();
|
||||
m_entity.instanceAttach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_entity.attach(m_keyObservers);
|
||||
}
|
||||
}
|
||||
void instanceDetach(const scene::Path& path)
|
||||
{
|
||||
if(--m_instanceCounter.m_count == 0)
|
||||
{
|
||||
m_entity.detach(m_keyObservers);
|
||||
m_entity.instanceDetach(path_find_mapfile(path.begin(), path.end()));
|
||||
m_filter.instanceDetach();
|
||||
}
|
||||
}
|
||||
|
||||
EntityKeyValues& getEntity()
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
const EntityKeyValues& getEntity() const
|
||||
{
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_model.getTraversable();
|
||||
}
|
||||
Namespaced& getNamespaced()
|
||||
{
|
||||
return m_nameKeys;
|
||||
}
|
||||
Nameable& getNameable()
|
||||
{
|
||||
return m_named;
|
||||
}
|
||||
TransformNode& getTransformNode()
|
||||
{
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_model.detach(observer);
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
if(selected)
|
||||
{
|
||||
m_renderOrigin.render(renderer, volume, localToWorld);
|
||||
}
|
||||
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected) const
|
||||
{
|
||||
renderSolid(renderer, volume, localToWorld, selected);
|
||||
if(g_showNames)
|
||||
{
|
||||
renderer.addRenderable(m_renderName, localToWorld);
|
||||
}
|
||||
}
|
||||
|
||||
void translate(const Vector3& translation)
|
||||
{
|
||||
m_origin = origin_translated(m_origin, translation);
|
||||
}
|
||||
void rotate(const Quaternion& rotation)
|
||||
{
|
||||
m_angles = angles_rotated(m_angles, rotation);
|
||||
}
|
||||
void scale(const Vector3& scaling)
|
||||
{
|
||||
m_scale = scale_scaled(m_scale, scaling);
|
||||
}
|
||||
void snapto(float snap)
|
||||
{
|
||||
m_originKey.m_origin = origin_snapped(m_originKey.m_origin, snap);
|
||||
m_originKey.write(&m_entity);
|
||||
}
|
||||
void revertTransform()
|
||||
{
|
||||
m_origin = m_originKey.m_origin;
|
||||
m_angles = m_anglesKey.m_angles;
|
||||
m_scale = m_scaleKey.m_scale;
|
||||
}
|
||||
void freezeTransform()
|
||||
{
|
||||
m_originKey.m_origin = m_origin;
|
||||
m_originKey.write(&m_entity);
|
||||
m_anglesKey.m_angles = m_angles;
|
||||
m_anglesKey.write(&m_entity);
|
||||
m_scaleKey.m_scale = m_scale;
|
||||
m_scaleKey.write(&m_entity);
|
||||
}
|
||||
void transformChanged()
|
||||
{
|
||||
revertTransform();
|
||||
m_evaluateTransform();
|
||||
updateTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModel, &MiscModel::transformChanged> TransformChangedCaller;
|
||||
};
|
||||
|
||||
class MiscModelInstance : public TargetableInstance, public TransformModifier, public Renderable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
m_casts = TargetableInstance::StaticTypeCasts::instance().get();
|
||||
InstanceStaticCast<MiscModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<MiscModelInstance, Transformable>::install(m_casts);
|
||||
InstanceIdentityCast<MiscModelInstance>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
MiscModel& m_contained;
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
STRING_CONSTANT(Name, "MiscModelInstance");
|
||||
|
||||
MiscModelInstance(const scene::Path& path, scene::Instance* parent, MiscModel& miscmodel) :
|
||||
TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), miscmodel.getEntity(), *this),
|
||||
TransformModifier(MiscModel::TransformChangedCaller(miscmodel), ApplyTransformCaller(*this)),
|
||||
m_contained(miscmodel)
|
||||
{
|
||||
m_contained.instanceAttach(Instance::path());
|
||||
StaticRenderableConnectionLines::instance().attach(*this);
|
||||
}
|
||||
~MiscModelInstance()
|
||||
{
|
||||
StaticRenderableConnectionLines::instance().detach(*this);
|
||||
m_contained.instanceDetach(Instance::path());
|
||||
}
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderSolid(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_contained.renderWireframe(renderer, volume, Instance::localToWorld(), getSelectable().isSelected());
|
||||
}
|
||||
void evaluateTransform()
|
||||
{
|
||||
if(getType() == TRANSFORM_PRIMITIVE)
|
||||
{
|
||||
m_contained.translate(getTranslation());
|
||||
m_contained.rotate(getRotation());
|
||||
m_contained.scale(getScale());
|
||||
}
|
||||
}
|
||||
void applyTransform()
|
||||
{
|
||||
m_contained.revertTransform();
|
||||
evaluateTransform();
|
||||
m_contained.freezeTransform();
|
||||
}
|
||||
typedef MemberCaller<MiscModelInstance, &MiscModelInstance::applyTransform> ApplyTransformCaller;
|
||||
};
|
||||
|
||||
class MiscModelNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable,
|
||||
public scene::Traversable::Observer
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<MiscModelNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<MiscModelNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, scene::Traversable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Entity>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<MiscModelNode, Namespaced>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
MiscModel m_contained;
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_contained.attach(this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_contained.detach(this);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
scene::Traversable& get(NullType<scene::Traversable>)
|
||||
{
|
||||
return m_contained.getTraversable();
|
||||
}
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_contained;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_contained.getTransformNode();
|
||||
}
|
||||
Entity& get(NullType<Entity>)
|
||||
{
|
||||
return m_contained.getEntity();
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_contained.getNameable();
|
||||
}
|
||||
Namespaced& get(NullType<Namespaced>)
|
||||
{
|
||||
return m_contained.getNamespaced();
|
||||
}
|
||||
|
||||
MiscModelNode(EntityClass* eclass) :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(eclass, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
MiscModelNode(const MiscModelNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
scene::Traversable::Observer(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_contained(other.m_contained, m_node, InstanceSet::TransformChangedCaller(m_instances), InstanceSetEvaluateTransform<MiscModelInstance>::Caller(m_instances))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~MiscModelNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new MiscModelNode(*this))->node();
|
||||
}
|
||||
|
||||
void insert(scene::Node& child)
|
||||
{
|
||||
m_instances.insert(child);
|
||||
}
|
||||
void erase(scene::Node& child)
|
||||
{
|
||||
m_instances.erase(child);
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new MiscModelInstance(path, parent, m_contained);
|
||||
}
|
||||
void forEachInstance(const scene::Instantiable::Visitor& visitor)
|
||||
{
|
||||
m_instances.forEachInstance(visitor);
|
||||
}
|
||||
void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
|
||||
{
|
||||
m_instances.insert(observer, path, instance);
|
||||
}
|
||||
scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
|
||||
{
|
||||
return m_instances.erase(observer, path);
|
||||
}
|
||||
};
|
||||
|
||||
scene::Node& New_MiscModel(EntityClass* eclass)
|
||||
{
|
||||
return (new MiscModelNode(eclass))->node();
|
||||
}
|
||||
|
||||
void MiscModel_construct()
|
||||
{
|
||||
}
|
||||
void MiscModel_destroy()
|
||||
{
|
||||
}
|
||||
29
plugins/entity/miscmodel.h
Normal file
29
plugins/entity/miscmodel.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MISCMODEL_H)
|
||||
#define INCLUDED_MISCMODEL_H
|
||||
|
||||
scene::Node& New_MiscModel(EntityClass* eclass);
|
||||
void MiscModel_construct();
|
||||
void MiscModel_destroy();
|
||||
|
||||
#endif
|
||||
23
plugins/entity/model.cpp
Normal file
23
plugins/entity/model.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "model.h"
|
||||
|
||||
124
plugins/entity/model.h
Normal file
124
plugins/entity/model.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MODEL_H)
|
||||
#define INCLUDED_MODEL_H
|
||||
|
||||
#include "entitylib.h"
|
||||
#include "traverselib.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "os/path.h"
|
||||
#include "moduleobserver.h"
|
||||
|
||||
class Model : public ModuleObserver
|
||||
{
|
||||
ResourceReference m_resource;
|
||||
scene::Traversable& m_traverse;
|
||||
scene::Node* m_node;
|
||||
Callback m_modelChanged;
|
||||
|
||||
public:
|
||||
Model(scene::Traversable& traversable, const Callback& modelChanged)
|
||||
: m_resource(""), m_traverse(traversable), m_node(0), m_modelChanged(modelChanged)
|
||||
{
|
||||
m_resource.attach(*this);
|
||||
}
|
||||
~Model()
|
||||
{
|
||||
m_resource.detach(*this);
|
||||
}
|
||||
|
||||
void realise()
|
||||
{
|
||||
m_resource.get()->load();
|
||||
m_node = m_resource.get()->getNode();
|
||||
if(m_node != 0)
|
||||
{
|
||||
m_traverse.insert(*m_node);
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
if(m_node != 0)
|
||||
{
|
||||
m_traverse.erase(*m_node);
|
||||
}
|
||||
}
|
||||
|
||||
void modelChanged(const char* value)
|
||||
{
|
||||
StringOutputStream cleaned(string_length(value));
|
||||
cleaned << PathCleaned(value);
|
||||
m_resource.detach(*this);
|
||||
m_resource.setName(cleaned.c_str());
|
||||
m_resource.attach(*this);
|
||||
m_modelChanged();
|
||||
}
|
||||
typedef MemberCaller1<Model, const char*, &Model::modelChanged> ModelChangedCaller;
|
||||
|
||||
const char* getName() const
|
||||
{
|
||||
return m_resource.getName();
|
||||
}
|
||||
scene::Node* getNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
};
|
||||
|
||||
class SingletonModel
|
||||
{
|
||||
TraversableNode m_traverse;
|
||||
Model m_model;
|
||||
public:
|
||||
SingletonModel()
|
||||
: m_model(m_traverse, Callback())
|
||||
{
|
||||
}
|
||||
|
||||
void attach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.attach(observer);
|
||||
}
|
||||
void detach(scene::Traversable::Observer* observer)
|
||||
{
|
||||
m_traverse.detach(observer);
|
||||
}
|
||||
|
||||
scene::Traversable& getTraversable()
|
||||
{
|
||||
return m_traverse;
|
||||
}
|
||||
|
||||
void modelChanged(const char* value)
|
||||
{
|
||||
m_model.modelChanged(value);
|
||||
}
|
||||
typedef MemberCaller1<SingletonModel, const char*, &SingletonModel::modelChanged> ModelChangedCaller;
|
||||
|
||||
scene::Node* getNode() const
|
||||
{
|
||||
return m_model.getNode();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
23
plugins/entity/modelskinkey.cpp
Normal file
23
plugins/entity/modelskinkey.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "modelskinkey.h"
|
||||
|
||||
111
plugins/entity/modelskinkey.h
Normal file
111
plugins/entity/modelskinkey.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_MODELSKINKEY_H)
|
||||
#define INCLUDED_MODELSKINKEY_H
|
||||
|
||||
#include "modelskin.h"
|
||||
|
||||
#include "os/path.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "moduleobserver.h"
|
||||
#include "entitylib.h"
|
||||
#include "traverselib.h"
|
||||
|
||||
inline void parseTextureName(CopiedString& name, const char* token)
|
||||
{
|
||||
StringOutputStream cleaned(256);
|
||||
cleaned << PathCleaned(token);
|
||||
name = CopiedString(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str())); // remove extension
|
||||
}
|
||||
|
||||
class ModelSkinKey : public ModuleObserver
|
||||
{
|
||||
CopiedString m_name;
|
||||
ModelSkin* m_skin;
|
||||
Callback m_skinChangedCallback;
|
||||
|
||||
ModelSkinKey(const ModelSkinKey&);
|
||||
ModelSkinKey operator=(const ModelSkinKey&);
|
||||
|
||||
void construct()
|
||||
{
|
||||
m_skin = &GlobalModelSkinCache().capture(m_name.c_str());
|
||||
m_skin->attach(*this);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
m_skin->detach(*this);
|
||||
GlobalModelSkinCache().release(m_name.c_str());
|
||||
}
|
||||
|
||||
public:
|
||||
ModelSkinKey(const Callback& skinChangedCallback) : m_skinChangedCallback(skinChangedCallback)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~ModelSkinKey()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
ModelSkin& get() const
|
||||
{
|
||||
return *m_skin;
|
||||
}
|
||||
void skinChanged(const char* value)
|
||||
{
|
||||
destroy();
|
||||
parseTextureName(m_name, value);
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<ModelSkinKey, const char*, &ModelSkinKey::skinChanged> SkinChangedCaller;
|
||||
|
||||
void realise()
|
||||
{
|
||||
m_skinChangedCallback();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class InstanceSkinChanged : public scene::Instantiable::Visitor
|
||||
{
|
||||
public:
|
||||
void visit(scene::Instance& instance) const
|
||||
{
|
||||
//\todo don't do this for instances that are not children of the entity setting the skin
|
||||
SkinnedModel* skinned = InstanceTypeCast<SkinnedModel>::cast(instance);
|
||||
if(skinned != 0)
|
||||
{
|
||||
skinned->skinChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void Node_modelSkinChanged(scene::Node& node)
|
||||
{
|
||||
scene::Instantiable* instantiable = Node_getInstantiable(node);
|
||||
ASSERT_NOTNULL(instantiable);
|
||||
instantiable->forEachInstance(InstanceSkinChanged());
|
||||
}
|
||||
|
||||
#endif
|
||||
23
plugins/entity/namedentity.cpp
Normal file
23
plugins/entity/namedentity.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "namedentity.h"
|
||||
|
||||
113
plugins/entity/namedentity.h
Normal file
113
plugins/entity/namedentity.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_NAMEDENTITY_H)
|
||||
#define INCLUDED_NAMEDENTITY_H
|
||||
|
||||
#include "entitylib.h"
|
||||
#include "eclasslib.h"
|
||||
#include "generic/callback.h"
|
||||
#include "nameable.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
class NameCallbackSet
|
||||
{
|
||||
typedef std::set<NameCallback> NameCallbacks;
|
||||
NameCallbacks m_callbacks;
|
||||
public:
|
||||
void insert(const NameCallback& callback)
|
||||
{
|
||||
m_callbacks.insert(callback);
|
||||
}
|
||||
void erase(const NameCallback& callback)
|
||||
{
|
||||
m_callbacks.erase(callback);
|
||||
}
|
||||
void changed(const char* name) const
|
||||
{
|
||||
for(NameCallbacks::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); ++i)
|
||||
{
|
||||
(*i)(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class NamedEntity : public Nameable
|
||||
{
|
||||
EntityKeyValues& m_entity;
|
||||
NameCallbackSet m_changed;
|
||||
CopiedString m_name;
|
||||
public:
|
||||
NamedEntity(EntityKeyValues& entity) : m_entity(entity)
|
||||
{
|
||||
}
|
||||
const char* name() const
|
||||
{
|
||||
if(string_empty(m_name.c_str()))
|
||||
{
|
||||
return m_entity.getEntityClass().name();
|
||||
}
|
||||
return m_name.c_str();
|
||||
}
|
||||
void attach(const NameCallback& callback)
|
||||
{
|
||||
m_changed.insert(callback);
|
||||
}
|
||||
void detach(const NameCallback& callback)
|
||||
{
|
||||
m_changed.erase(callback);
|
||||
}
|
||||
|
||||
void identifierChanged(const char* value)
|
||||
{
|
||||
if(string_empty(value))
|
||||
{
|
||||
m_changed.changed(m_entity.getEntityClass().name());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_changed.changed(value);
|
||||
}
|
||||
m_name = value;
|
||||
}
|
||||
typedef MemberCaller1<NamedEntity, const char*, &NamedEntity::identifierChanged> IdentifierChangedCaller;
|
||||
};
|
||||
|
||||
class RenderableNamedEntity : public OpenGLRenderable
|
||||
{
|
||||
const NamedEntity& m_named;
|
||||
const Vector3& m_position;
|
||||
public:
|
||||
RenderableNamedEntity(const NamedEntity& named, const Vector3& position)
|
||||
: m_named(named), m_position(position)
|
||||
{
|
||||
}
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
glRasterPos3fv(vector3_to_array(m_position));
|
||||
GlobalOpenGL().drawString(m_named.name());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
23
plugins/entity/namekeys.cpp
Normal file
23
plugins/entity/namekeys.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "namekeys.h"
|
||||
|
||||
148
plugins/entity/namekeys.h
Normal file
148
plugins/entity/namekeys.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_NAMEKEYS_H)
|
||||
#define INCLUDED_NAMEKEYS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
#include "generic/static.h"
|
||||
#include "entitylib.h"
|
||||
#include "namespace.h"
|
||||
|
||||
inline bool string_is_integer(const char* string)
|
||||
{
|
||||
strtol(string, const_cast<char**>(&string), 10);
|
||||
return *string == '\0';
|
||||
}
|
||||
|
||||
typedef bool (*KeyIsNameFunc)(const char* key);
|
||||
|
||||
class KeyIsName
|
||||
{
|
||||
public:
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
const char* m_nameKey;
|
||||
|
||||
KeyIsName()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef MemberCaller1<KeyValue, const char*, &KeyValue::assign> KeyValueAssignCaller;
|
||||
typedef MemberCaller1<KeyValue, const KeyObserver&, &KeyValue::attach> KeyValueAttachCaller;
|
||||
typedef MemberCaller1<KeyValue, const KeyObserver&, &KeyValue::detach> KeyValueDetachCaller;
|
||||
|
||||
class NameKeys : public EntityKeyValues::Observer, public Namespaced
|
||||
{
|
||||
Namespace* m_namespace;
|
||||
EntityKeyValues& m_entity;
|
||||
KeyIsNameFunc m_keyIsName;
|
||||
NameKeys(const NameKeys& other);
|
||||
NameKeys& operator=(const NameKeys& other);
|
||||
|
||||
typedef std::map<CopiedString, EntityKeyValues::Value*> KeyValues;
|
||||
KeyValues m_keyValues;
|
||||
|
||||
void insertName(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
if(m_namespace != 0 && m_keyIsName(key))
|
||||
{
|
||||
//globalOutputStream() << "insert " << key << "\n";
|
||||
m_namespace->attach(KeyValueAssignCaller(value), KeyValueAttachCaller(value));
|
||||
}
|
||||
}
|
||||
void eraseName(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
if(m_namespace != 0 && m_keyIsName(key))
|
||||
{
|
||||
//globalOutputStream() << "erase " << key << "\n";
|
||||
m_namespace->detach(KeyValueAssignCaller(value), KeyValueDetachCaller(value));
|
||||
}
|
||||
}
|
||||
void insertAll()
|
||||
{
|
||||
for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
|
||||
{
|
||||
insertName((*i).first.c_str(), *(*i).second);
|
||||
}
|
||||
}
|
||||
void eraseAll()
|
||||
{
|
||||
for(KeyValues::iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i)
|
||||
{
|
||||
eraseName((*i).first.c_str(), *(*i).second);
|
||||
}
|
||||
}
|
||||
public:
|
||||
NameKeys(EntityKeyValues& entity) : m_namespace(0), m_entity(entity), m_keyIsName(Static<KeyIsName>::instance().m_keyIsName)
|
||||
{
|
||||
m_entity.attach(*this);
|
||||
}
|
||||
~NameKeys()
|
||||
{
|
||||
m_entity.detach(*this);
|
||||
}
|
||||
void setNamespace(Namespace& space)
|
||||
{
|
||||
eraseAll();
|
||||
m_namespace = &space;
|
||||
insertAll();
|
||||
}
|
||||
void setKeyIsName(KeyIsNameFunc keyIsName)
|
||||
{
|
||||
eraseAll();
|
||||
m_keyIsName = keyIsName;
|
||||
insertAll();
|
||||
}
|
||||
void insert(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
m_keyValues.insert(KeyValues::value_type(key, &value));
|
||||
insertName(key, value);
|
||||
}
|
||||
void erase(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
eraseName(key, value);
|
||||
m_keyValues.erase(key);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool keyIsNameDoom3(const char* key)
|
||||
{
|
||||
return string_equal(key, "target")
|
||||
|| (string_equal_n(key, "target", 6) && string_is_integer(key + 6))
|
||||
|| string_equal(key, "name");
|
||||
}
|
||||
|
||||
inline bool keyIsNameDoom3Doom3Group(const char* key)
|
||||
{
|
||||
return keyIsNameDoom3(key)
|
||||
|| string_equal(key, "model");
|
||||
}
|
||||
|
||||
inline bool keyIsNameQuake3(const char* key)
|
||||
{
|
||||
return string_equal(key, "target")
|
||||
|| string_equal(key, "targetname");
|
||||
}
|
||||
|
||||
#endif
|
||||
23
plugins/entity/origin.cpp
Normal file
23
plugins/entity/origin.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "origin.h"
|
||||
|
||||
169
plugins/entity/origin.h
Normal file
169
plugins/entity/origin.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ORIGIN_H)
|
||||
#define INCLUDED_ORIGIN_H
|
||||
|
||||
#include "ientity.h"
|
||||
|
||||
#include "math/matrix.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
const Vector3 ORIGINKEY_IDENTITY = Vector3(0, 0, 0);
|
||||
|
||||
inline void default_origin(Vector3& origin)
|
||||
{
|
||||
origin = ORIGINKEY_IDENTITY;
|
||||
}
|
||||
inline void read_origin(Vector3& origin, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, origin))
|
||||
{
|
||||
default_origin(origin);
|
||||
}
|
||||
}
|
||||
inline void write_origin(const Vector3& origin, Entity* entity, const char* key)
|
||||
{
|
||||
char value[64];
|
||||
sprintf(value, "%g %g %g", origin[0], origin[1], origin[2]);
|
||||
entity->setKeyValue(key, value);
|
||||
}
|
||||
|
||||
inline Vector3 origin_translated(const Vector3& origin, const Vector3& translation)
|
||||
{
|
||||
return matrix4_get_translation_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_translation_for_vec3(origin),
|
||||
matrix4_translation_for_vec3(translation)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline Vector3 origin_snapped(const Vector3& origin, float snap)
|
||||
{
|
||||
return vector3_snapped(origin, snap);
|
||||
}
|
||||
|
||||
class OriginKey
|
||||
{
|
||||
Callback m_originChanged;
|
||||
public:
|
||||
Vector3 m_origin;
|
||||
|
||||
|
||||
OriginKey(const Callback& originChanged)
|
||||
: m_originChanged(originChanged), m_origin(ORIGINKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
|
||||
void originChanged(const char* value)
|
||||
{
|
||||
read_origin(m_origin, value);
|
||||
m_originChanged();
|
||||
}
|
||||
typedef MemberCaller1<OriginKey, const char*, &OriginKey::originChanged> OriginChangedCaller;
|
||||
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_origin(m_origin, entity, "origin");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#include "scenelib.h"
|
||||
|
||||
inline BrushDoom3* Node_getBrushDoom3(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<BrushDoom3>::cast(node);
|
||||
}
|
||||
|
||||
inline void BrushDoom3_setDoom3GroupOrigin(scene::Node& node, const Vector3& origin)
|
||||
{
|
||||
BrushDoom3* brush = Node_getBrushDoom3(node);
|
||||
if(brush != 0)
|
||||
{
|
||||
brush->setDoom3GroupOrigin(origin);
|
||||
}
|
||||
}
|
||||
|
||||
class SetDoom3GroupOriginWalker : public scene::Traversable::Walker
|
||||
{
|
||||
const Vector3& m_origin;
|
||||
public:
|
||||
SetDoom3GroupOriginWalker(const Vector3& origin) : m_origin(origin)
|
||||
{
|
||||
}
|
||||
bool pre(scene::Node& node) const
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, m_origin);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3GroupOrigin : public scene::Traversable::Observer
|
||||
{
|
||||
scene::Traversable& m_set;
|
||||
const Vector3& m_origin;
|
||||
bool m_enabled;
|
||||
|
||||
public:
|
||||
Doom3GroupOrigin(scene::Traversable& set, const Vector3& origin) : m_set(set), m_origin(origin), m_enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void enable()
|
||||
{
|
||||
m_enabled = true;
|
||||
originChanged();
|
||||
}
|
||||
void disable()
|
||||
{
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
void originChanged()
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
m_set.traverse(SetDoom3GroupOriginWalker(m_origin));
|
||||
}
|
||||
}
|
||||
|
||||
void insert(scene::Node& node)
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, m_origin);
|
||||
}
|
||||
}
|
||||
void erase(scene::Node& node)
|
||||
{
|
||||
if(m_enabled)
|
||||
{
|
||||
BrushDoom3_setDoom3GroupOrigin(node, Vector3(0, 0, 0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
163
plugins/entity/plugin.cpp
Normal file
163
plugins/entity/plugin.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "iscenegraph.h"
|
||||
#include "irender.h"
|
||||
#include "iselection.h"
|
||||
#include "ientity.h"
|
||||
#include "iundo.h"
|
||||
#include "ieclass.h"
|
||||
#include "igl.h"
|
||||
#include "ireference.h"
|
||||
#include "ifilter.h"
|
||||
#include "preferencesystem.h"
|
||||
#include "qerplugin.h"
|
||||
#include "namespace.h"
|
||||
#include "modelskin.h"
|
||||
|
||||
#include "typesystem.h"
|
||||
|
||||
#include "entity.h"
|
||||
#include "skincache.h"
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class EntityDependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalReferenceModuleRef,
|
||||
public GlobalFilterModuleRef,
|
||||
public GlobalPreferenceSystemModuleRef,
|
||||
public GlobalNamespaceModuleRef,
|
||||
public GlobalModelSkinCacheModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EntityQ3API : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entityq3;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "quake3");
|
||||
|
||||
EntityQ3API()
|
||||
{
|
||||
Entity_Construct();
|
||||
|
||||
m_entityq3 = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entityq3);
|
||||
}
|
||||
~EntityQ3API()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entityq3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityQ3API, EntityDependencies> EntityQ3Module;
|
||||
|
||||
EntityQ3Module g_EntityQ3Module;
|
||||
|
||||
|
||||
class EntityWolfAPI : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entitywolf;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "wolf");
|
||||
|
||||
EntityWolfAPI()
|
||||
{
|
||||
Entity_Construct(eGameTypeRTCW);
|
||||
|
||||
m_entitywolf = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entitywolf);
|
||||
}
|
||||
~EntityWolfAPI()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entitywolf;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityWolfAPI, EntityDependencies> EntityWolfModule;
|
||||
|
||||
EntityWolfModule g_EntityWolfModule;
|
||||
|
||||
|
||||
class EntityDoom3API : public TypeSystemRef
|
||||
{
|
||||
EntityCreator* m_entitydoom3;
|
||||
public:
|
||||
typedef EntityCreator Type;
|
||||
STRING_CONSTANT(Name, "doom3");
|
||||
|
||||
EntityDoom3API()
|
||||
{
|
||||
Entity_Construct(eGameTypeDoom3);
|
||||
|
||||
m_entitydoom3 = &GetEntityCreator();
|
||||
|
||||
GlobalReferenceCache().setEntityCreator(*m_entitydoom3);
|
||||
}
|
||||
~EntityDoom3API()
|
||||
{
|
||||
Entity_Destroy();
|
||||
}
|
||||
EntityCreator* getTable()
|
||||
{
|
||||
return m_entitydoom3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EntityDoom3API, EntityDependencies> EntityDoom3Module;
|
||||
|
||||
EntityDoom3Module g_EntityDoom3Module;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_EntityQ3Module.selfRegister();
|
||||
g_EntityWolfModule.selfRegister();
|
||||
g_EntityDoom3Module.selfRegister();
|
||||
Doom3ModelSkinCacheModule_selfRegister(server);
|
||||
}
|
||||
25
plugins/entity/plugin.h
Normal file
25
plugins/entity/plugin.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PLUGIN_H)
|
||||
#define INCLUDED_PLUGIN_H
|
||||
|
||||
#endif
|
||||
23
plugins/entity/rotation.cpp
Normal file
23
plugins/entity/rotation.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "rotation.h"
|
||||
|
||||
199
plugins/entity/rotation.h
Normal file
199
plugins/entity/rotation.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_ROTATION_H)
|
||||
#define INCLUDED_ROTATION_H
|
||||
|
||||
#include "ientity.h"
|
||||
|
||||
#include "stream/stringstream.h"
|
||||
#include "math/quaternion.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "angle.h"
|
||||
|
||||
typedef float Float9[9];
|
||||
|
||||
inline void default_rotation(Float9 rotation)
|
||||
{
|
||||
rotation[0] = 1;
|
||||
rotation[1] = 0;
|
||||
rotation[2] = 0;
|
||||
rotation[3] = 0;
|
||||
rotation[4] = 1;
|
||||
rotation[5] = 0;
|
||||
rotation[6] = 0;
|
||||
rotation[7] = 0;
|
||||
rotation[8] = 1;
|
||||
}
|
||||
inline void write_rotation(const Float9 rotation, Entity* entity, const char* key = "rotation")
|
||||
{
|
||||
if(rotation[0] == 1
|
||||
&& rotation[1] == 0
|
||||
&& rotation[2] == 0
|
||||
&& rotation[3] == 0
|
||||
&& rotation[4] == 1
|
||||
&& rotation[5] == 0
|
||||
&& rotation[6] == 0
|
||||
&& rotation[7] == 0
|
||||
&& rotation[8] == 1)
|
||||
{
|
||||
entity->setKeyValue(key, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
StringOutputStream value(256);
|
||||
value << rotation[0] << ' '
|
||||
<< rotation[1] << ' '
|
||||
<< rotation[2] << ' '
|
||||
<< rotation[3] << ' '
|
||||
<< rotation[4] << ' '
|
||||
<< rotation[5] << ' '
|
||||
<< rotation[6] << ' '
|
||||
<< rotation[7] << ' '
|
||||
<< rotation[8];
|
||||
entity->setKeyValue(key, value.c_str());
|
||||
}
|
||||
}
|
||||
inline void read_rotation(Float9 rotation, const char* value)
|
||||
{
|
||||
if(!string_parse_vector(value, rotation, rotation + 9))
|
||||
{
|
||||
default_rotation(rotation);
|
||||
}
|
||||
}
|
||||
|
||||
inline Matrix4 rotation_toMatrix(const Float9 rotation)
|
||||
{
|
||||
return Matrix4(
|
||||
rotation[0],
|
||||
rotation[1],
|
||||
rotation[2],
|
||||
0,
|
||||
rotation[3],
|
||||
rotation[4],
|
||||
rotation[5],
|
||||
0,
|
||||
rotation[6],
|
||||
rotation[7],
|
||||
rotation[8],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
inline void rotation_fromMatrix(Float9 rotation, const Matrix4& matrix)
|
||||
{
|
||||
rotation[0] = matrix.xx();
|
||||
rotation[1] = matrix.xy();
|
||||
rotation[2] = matrix.xz();
|
||||
rotation[3] = matrix.yx();
|
||||
rotation[4] = matrix.yy();
|
||||
rotation[5] = matrix.yz();
|
||||
rotation[6] = matrix.zx();
|
||||
rotation[7] = matrix.zy();
|
||||
rotation[8] = matrix.zz();
|
||||
}
|
||||
|
||||
inline void rotation_assign(Float9 rotation, const Float9 other)
|
||||
{
|
||||
rotation[0] = other[0];
|
||||
rotation[1] = other[1];
|
||||
rotation[2] = other[2];
|
||||
rotation[3] = other[3];
|
||||
rotation[4] = other[4];
|
||||
rotation[5] = other[5];
|
||||
rotation[6] = other[6];
|
||||
rotation[7] = other[7];
|
||||
rotation[8] = other[8];
|
||||
}
|
||||
|
||||
inline void rotation_rotate(Float9 rotation, const Quaternion& rotate)
|
||||
{
|
||||
rotation_fromMatrix(rotation,
|
||||
matrix4_multiplied_by_matrix4(
|
||||
rotation_toMatrix(rotation),
|
||||
matrix4_rotation_for_quaternion_quantised(rotate)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline void read_angle(Float9 rotation, const char* value)
|
||||
{
|
||||
float angle;
|
||||
if(!string_parse_float(value, angle))
|
||||
{
|
||||
default_rotation(rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation_fromMatrix(rotation, matrix4_rotation_for_z_degrees(angle));
|
||||
}
|
||||
}
|
||||
|
||||
class RotationKey
|
||||
{
|
||||
Callback m_rotationChanged;
|
||||
public:
|
||||
Float9 m_rotation;
|
||||
|
||||
|
||||
RotationKey(const Callback& rotationChanged)
|
||||
: m_rotationChanged(rotationChanged)
|
||||
{
|
||||
default_rotation(m_rotation);
|
||||
}
|
||||
|
||||
void angleChanged(const char* value)
|
||||
{
|
||||
read_angle(m_rotation, value);
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::angleChanged> AngleChangedCaller;
|
||||
|
||||
void rotationChanged(const char* value)
|
||||
{
|
||||
read_rotation(m_rotation, value);
|
||||
m_rotationChanged();
|
||||
}
|
||||
typedef MemberCaller1<RotationKey, const char*, &RotationKey::rotationChanged> RotationChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
Vector3 euler = matrix4_get_rotation_euler_xyz_degrees(rotation_toMatrix(m_rotation));
|
||||
if(euler[0] == 0 && euler[1] == 0)
|
||||
{
|
||||
entity->setKeyValue("rotation", "");
|
||||
write_angle(euler[2], entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity->setKeyValue("angle", "");
|
||||
write_rotation(m_rotation, entity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
23
plugins/entity/scale.cpp
Normal file
23
plugins/entity/scale.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "scale.h"
|
||||
|
||||
128
plugins/entity/scale.h
Normal file
128
plugins/entity/scale.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_SCALE_H)
|
||||
#define INCLUDED_SCALE_H
|
||||
|
||||
#include "ientity.h"
|
||||
|
||||
#include "math/matrix.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stringio.h"
|
||||
|
||||
const Vector3 SCALEKEY_IDENTITY = Vector3(1, 1, 1);
|
||||
|
||||
inline void default_scale(Vector3& scale)
|
||||
{
|
||||
scale = SCALEKEY_IDENTITY;
|
||||
}
|
||||
inline void read_scale(Vector3& scalevec, const char* value)
|
||||
{
|
||||
float scale;
|
||||
if(!string_parse_float(value, scale)
|
||||
|| scale == 0)
|
||||
{
|
||||
default_scale(scalevec);
|
||||
}
|
||||
else
|
||||
{
|
||||
scalevec = Vector3(scale, scale, scale);
|
||||
}
|
||||
}
|
||||
inline void read_scalevec(Vector3& scale, const char* value)
|
||||
{
|
||||
if(!string_parse_vector3(value, scale)
|
||||
|| scale[0] == 0
|
||||
|| scale[1] == 0
|
||||
|| scale[2] == 0)
|
||||
default_scale(scale);
|
||||
}
|
||||
inline void write_scale(const Vector3& scale, Entity* entity)
|
||||
{
|
||||
if(scale[0] == 1 && scale[1] == 1 && scale[2] == 1)
|
||||
{
|
||||
entity->setKeyValue("modelscale", "");
|
||||
entity->setKeyValue("modelscale_vec", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
char value[64];
|
||||
|
||||
if(scale[0] == scale[1] && scale[0] == scale[2])
|
||||
{
|
||||
sprintf(value, "%g", scale[0]);
|
||||
entity->setKeyValue("modelscale_vec", "");
|
||||
entity->setKeyValue("modelscale", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(value, "%g %g %g", scale[0], scale[1], scale[2]);
|
||||
entity->setKeyValue("modelscale", "");
|
||||
entity->setKeyValue("modelscale_vec", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Vector3 scale_scaled(const Vector3& scale, const Vector3& scaling)
|
||||
{
|
||||
return matrix4_get_scale_vec3(
|
||||
matrix4_multiplied_by_matrix4(
|
||||
matrix4_scale_for_vec3(scale),
|
||||
matrix4_scale_for_vec3(scaling)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class ScaleKey
|
||||
{
|
||||
Callback m_scaleChanged;
|
||||
public:
|
||||
Vector3 m_scale;
|
||||
|
||||
|
||||
ScaleKey(const Callback& scaleChanged)
|
||||
: m_scaleChanged(scaleChanged), m_scale(SCALEKEY_IDENTITY)
|
||||
{
|
||||
}
|
||||
|
||||
void uniformScaleChanged(const char* value)
|
||||
{
|
||||
read_scale(m_scale, value);
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::uniformScaleChanged> UniformScaleChangedCaller;
|
||||
|
||||
void scaleChanged(const char* value)
|
||||
{
|
||||
read_scalevec(m_scale, value);
|
||||
m_scaleChanged();
|
||||
}
|
||||
typedef MemberCaller1<ScaleKey, const char*, &ScaleKey::scaleChanged> ScaleChangedCaller;
|
||||
|
||||
void write(Entity* entity) const
|
||||
{
|
||||
write_scale(m_scale, entity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
348
plugins/entity/skincache.cpp
Normal file
348
plugins/entity/skincache.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "skincache.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iscriplib.h"
|
||||
#include "iarchive.h"
|
||||
#include "modelskin.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "stream/stringstream.h"
|
||||
#include "generic/callback.h"
|
||||
#include "container/cache.h"
|
||||
#include "container/hashfunc.h"
|
||||
#include "os/path.h"
|
||||
#include "moduleobservers.h"
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void parseShaderName(CopiedString& name, const char* token)
|
||||
{
|
||||
StringOutputStream cleaned(256);
|
||||
cleaned << PathCleaned(token);
|
||||
name = cleaned.c_str();
|
||||
}
|
||||
|
||||
class Doom3ModelSkin
|
||||
{
|
||||
typedef std::map<CopiedString, CopiedString> Remaps;
|
||||
Remaps m_remaps;
|
||||
public:
|
||||
bool parseTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{"));
|
||||
tokeniser.nextLine();
|
||||
for(;;)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if(token == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(string_equal(token, "}"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
return true;
|
||||
}
|
||||
else if(string_equal(token, "model"))
|
||||
{
|
||||
//const char* model =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
CopiedString from, to;
|
||||
parseShaderName(from, token);
|
||||
|
||||
tokeniser.nextLine(); // hack to handle badly formed skins
|
||||
|
||||
parseShaderName(to, tokeniser.getToken());
|
||||
|
||||
if(!string_equal(from.c_str(), to.c_str()))
|
||||
{
|
||||
m_remaps.insert(Remaps::value_type(from, to));
|
||||
}
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
const char* getRemap(const char* name) const
|
||||
{
|
||||
Remaps::const_iterator i = m_remaps.find(name);
|
||||
if(i != m_remaps.end())
|
||||
{
|
||||
return (*i).second.c_str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
void forEachRemap(const SkinRemapCallback& callback) const
|
||||
{
|
||||
for(Remaps::const_iterator i = m_remaps.begin(); i != m_remaps.end(); ++i)
|
||||
{
|
||||
callback(SkinRemap((*i).first.c_str(), (*i).second.c_str()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalSkins
|
||||
{
|
||||
public:
|
||||
typedef std::map<CopiedString, Doom3ModelSkin> SkinMap;
|
||||
SkinMap m_skins;
|
||||
Doom3ModelSkin g_nullSkin;
|
||||
|
||||
Doom3ModelSkin& getSkin(const char* name)
|
||||
{
|
||||
SkinMap::iterator i = m_skins.find(name);
|
||||
if(i != m_skins.end())
|
||||
{
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
return g_nullSkin;
|
||||
}
|
||||
|
||||
bool parseTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
for(;;)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if(token == 0)
|
||||
{
|
||||
// end of token stream
|
||||
return true;
|
||||
}
|
||||
if(!string_equal(token, "skin"))
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, token, "skin");
|
||||
return false;
|
||||
}
|
||||
const char* other = tokeniser.getToken();
|
||||
if(other == 0)
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, token, "#string");
|
||||
return false;
|
||||
}
|
||||
CopiedString name;
|
||||
parseShaderName(name, other);
|
||||
Doom3ModelSkin& skin = m_skins[name];
|
||||
RETURN_FALSE_IF_FAIL(skin.parseTokens(tokeniser));
|
||||
}
|
||||
}
|
||||
|
||||
void parseFile(const char* name)
|
||||
{
|
||||
StringOutputStream relativeName(64);
|
||||
relativeName << "skins/" << name;
|
||||
ArchiveTextFile* file = GlobalFileSystem().openTextFile(relativeName.c_str());
|
||||
if(file != 0)
|
||||
{
|
||||
globalOutputStream() << "parsing skins from " << makeQuoted(name) << "\n";
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(file->getInputStream());
|
||||
parseTokens(tokeniser);
|
||||
tokeniser.release();
|
||||
}
|
||||
file->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalErrorStream() << "failed to open " << makeQuoted(name) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
typedef MemberCaller1<GlobalSkins, const char*, &GlobalSkins::parseFile> ParseFileCaller;
|
||||
|
||||
void construct()
|
||||
{
|
||||
GlobalFileSystem().forEachFile("skins/", "skin", ParseFileCaller(*this));
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_skins.clear();
|
||||
}
|
||||
|
||||
void realise()
|
||||
{
|
||||
construct();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
};
|
||||
|
||||
GlobalSkins g_skins;
|
||||
|
||||
|
||||
class Doom3ModelSkinCacheElement : public ModelSkin
|
||||
{
|
||||
ModuleObservers m_observers;
|
||||
Doom3ModelSkin* m_skin;
|
||||
public:
|
||||
Doom3ModelSkinCacheElement() : m_skin(0)
|
||||
{
|
||||
}
|
||||
void attach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.attach(observer);
|
||||
if(realised())
|
||||
{
|
||||
observer.realise();
|
||||
}
|
||||
}
|
||||
void detach(ModuleObserver& observer)
|
||||
{
|
||||
if(realised())
|
||||
{
|
||||
observer.unrealise();
|
||||
}
|
||||
m_observers.detach(observer);
|
||||
}
|
||||
bool realised() const
|
||||
{
|
||||
return m_skin != 0;
|
||||
}
|
||||
void realise(const char* name)
|
||||
{
|
||||
ASSERT_MESSAGE(!realised(), "Doom3ModelSkinCacheElement::realise: already realised");
|
||||
m_skin = &g_skins.getSkin(name);
|
||||
m_observers.realise();
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::unrealise: not realised");
|
||||
m_observers.unrealise();
|
||||
m_skin = 0;
|
||||
}
|
||||
const char* getRemap(const char* name) const
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::getRemap: not realised");
|
||||
return m_skin->getRemap(name);
|
||||
}
|
||||
void forEachRemap(const SkinRemapCallback& callback) const
|
||||
{
|
||||
ASSERT_MESSAGE(realised(), "Doom3ModelSkinCacheElement::forEachRemap: not realised");
|
||||
m_skin->forEachRemap(callback);
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3ModelSkinCache : public ModelSkinCache, public ModuleObserver
|
||||
{
|
||||
class CreateDoom3ModelSkin
|
||||
{
|
||||
Doom3ModelSkinCache& m_cache;
|
||||
public:
|
||||
explicit CreateDoom3ModelSkin(Doom3ModelSkinCache& cache)
|
||||
: m_cache(cache)
|
||||
{
|
||||
}
|
||||
Doom3ModelSkinCacheElement* construct(const CopiedString& name)
|
||||
{
|
||||
Doom3ModelSkinCacheElement* skin = new Doom3ModelSkinCacheElement;
|
||||
if(m_cache.realised())
|
||||
{
|
||||
skin->realise(name.c_str());
|
||||
}
|
||||
return skin;
|
||||
}
|
||||
void destroy(Doom3ModelSkinCacheElement* skin)
|
||||
{
|
||||
if(m_cache.realised())
|
||||
{
|
||||
skin->unrealise();
|
||||
}
|
||||
delete skin;
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashedCache<CopiedString, Doom3ModelSkinCacheElement, HashString, std::equal_to<CopiedString>, CreateDoom3ModelSkin> Cache;
|
||||
Cache m_cache;
|
||||
bool m_realised;
|
||||
|
||||
public:
|
||||
typedef ModelSkinCache Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
ModelSkinCache* getTable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Doom3ModelSkinCache() : m_cache(CreateDoom3ModelSkin(*this)), m_realised(false)
|
||||
{
|
||||
GlobalFileSystem().attach(*this);
|
||||
}
|
||||
~Doom3ModelSkinCache()
|
||||
{
|
||||
GlobalFileSystem().detach(*this);
|
||||
}
|
||||
|
||||
ModelSkin& capture(const char* name)
|
||||
{
|
||||
return *m_cache.capture(name);
|
||||
}
|
||||
void release(const char* name)
|
||||
{
|
||||
m_cache.release(name);
|
||||
}
|
||||
|
||||
bool realised() const
|
||||
{
|
||||
return m_realised;
|
||||
}
|
||||
void realise()
|
||||
{
|
||||
g_skins.realise();
|
||||
m_realised = true;
|
||||
for(Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i)
|
||||
{
|
||||
(*i).value->realise((*i).key.c_str());
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
m_realised = false;
|
||||
for(Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i)
|
||||
{
|
||||
(*i).value->unrealise();
|
||||
}
|
||||
g_skins.unrealise();
|
||||
}
|
||||
};
|
||||
|
||||
class Doom3ModelSkinCacheDependencies : public GlobalFileSystemModuleRef, public GlobalScripLibModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
typedef SingletonModule<Doom3ModelSkinCache, Doom3ModelSkinCacheDependencies> Doom3ModelSkinCacheModule;
|
||||
|
||||
Doom3ModelSkinCacheModule g_Doom3ModelSkinCacheModule;
|
||||
|
||||
void Doom3ModelSkinCacheModule_selfRegister(ModuleServer& server)
|
||||
{
|
||||
g_Doom3ModelSkinCacheModule.selfRegister();
|
||||
}
|
||||
|
||||
28
plugins/entity/skincache.h
Normal file
28
plugins/entity/skincache.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_SKINCACHE_H)
|
||||
#define INCLUDED_SKINCACHE_H
|
||||
|
||||
class ModuleServer;
|
||||
void Doom3ModelSkinCacheModule_selfRegister(ModuleServer& server);
|
||||
|
||||
#endif
|
||||
37
plugins/entity/targetable.cpp
Normal file
37
plugins/entity/targetable.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "targetable.h"
|
||||
|
||||
typedef std::map<CopiedString, targetables_t> targetnames_t;
|
||||
|
||||
const char* g_targetable_nameKey = "targetname";
|
||||
|
||||
targetnames_t g_targetnames;
|
||||
|
||||
targetables_t* getTargetables(const char* targetname)
|
||||
{
|
||||
if(targetname[0] == '\0')
|
||||
return 0;
|
||||
return &g_targetnames[targetname];
|
||||
}
|
||||
|
||||
Shader* RenderableTargetingEntity::m_state;
|
||||
452
plugins/entity/targetable.h
Normal file
452
plugins/entity/targetable.h
Normal file
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_TARGETABLE_H)
|
||||
#define INCLUDED_TARGETABLE_H
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
|
||||
#include "math/line.h"
|
||||
#include "render.h"
|
||||
#include "generic/callback.h"
|
||||
#include "selectionlib.h"
|
||||
#include "entitylib.h"
|
||||
#include "eclasslib.h"
|
||||
#include "stringio.h"
|
||||
|
||||
class Targetable
|
||||
{
|
||||
public:
|
||||
virtual const Vector3& world_position() const = 0;
|
||||
};
|
||||
|
||||
typedef std::set<Targetable*> targetables_t;
|
||||
|
||||
extern const char* g_targetable_nameKey;
|
||||
|
||||
targetables_t* getTargetables(const char* targetname);
|
||||
|
||||
class EntityConnectionLine : public OpenGLRenderable
|
||||
{
|
||||
public:
|
||||
Vector3 start;
|
||||
Vector3 end;
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
float s1[2], s2[2];
|
||||
Vector3 dir(vector3_subtracted(end, start));
|
||||
double len = vector3_length(dir);
|
||||
vector3_scale(dir, 8.0 * (1.0 / len));
|
||||
s1[0] = dir[0] - dir[1];
|
||||
s1[1] = dir[0] + dir[1];
|
||||
s2[0] = dir[0] + dir[1];
|
||||
s2[1] = -dir[0] + dir[1];
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
glVertex3fv(vector3_to_array(start));
|
||||
glVertex3fv(vector3_to_array(end));
|
||||
|
||||
len*=0.0625; // half / 8
|
||||
|
||||
Vector3 arrow(start);
|
||||
for (unsigned int i = 0, count = (len<32)? 1 : static_cast<unsigned int>(len*0.0625); i < count; i++)
|
||||
{
|
||||
vector3_add(arrow, vector3_scaled(dir, (len<32)?len:32));
|
||||
glVertex3fv(vector3_to_array(arrow));
|
||||
glVertex3f(arrow[0]+s1[0], arrow[1]+s1[1], arrow[2]+dir[2]);
|
||||
glVertex3fv(vector3_to_array(arrow));
|
||||
glVertex3f(arrow[0]+s2[0], arrow[1]+s2[1], arrow[2]+dir[2]);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
};
|
||||
|
||||
class TargetedEntity
|
||||
{
|
||||
Targetable& m_targetable;
|
||||
targetables_t* m_targets;
|
||||
|
||||
void construct()
|
||||
{
|
||||
if(m_targets != 0)
|
||||
m_targets->insert(&m_targetable);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
if(m_targets != 0)
|
||||
m_targets->erase(&m_targetable);
|
||||
}
|
||||
public:
|
||||
TargetedEntity(Targetable& targetable)
|
||||
: m_targetable(targetable), m_targets(getTargetables(""))
|
||||
{
|
||||
construct();
|
||||
}
|
||||
~TargetedEntity()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void targetnameChanged(const char* name)
|
||||
{
|
||||
destroy();
|
||||
m_targets = getTargetables(name);
|
||||
construct();
|
||||
}
|
||||
typedef MemberCaller1<TargetedEntity, const char*, &TargetedEntity::targetnameChanged> TargetnameChangedCaller;
|
||||
};
|
||||
|
||||
|
||||
class TargetingEntity
|
||||
{
|
||||
targetables_t* m_targets;
|
||||
public:
|
||||
TargetingEntity() :
|
||||
m_targets(getTargetables(""))
|
||||
{
|
||||
}
|
||||
void targetChanged(const char* target)
|
||||
{
|
||||
m_targets = getTargetables(target);
|
||||
}
|
||||
typedef MemberCaller1<TargetingEntity, const char*, &TargetingEntity::targetChanged> TargetChangedCaller;
|
||||
|
||||
typedef targetables_t::iterator iterator;
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->begin();
|
||||
}
|
||||
iterator end() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
return m_targets->end();
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
if(m_targets == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_targets->size();
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return m_targets == 0 || m_targets->empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Functor>
|
||||
void TargetingEntity_forEach(const TargetingEntity& targets, const Functor& functor)
|
||||
{
|
||||
for(TargetingEntity::iterator i = targets.begin(); i != targets.end(); ++i)
|
||||
{
|
||||
functor((*i)->world_position());
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<std::size_t, TargetingEntity> TargetingEntities;
|
||||
|
||||
template<typename Functor>
|
||||
void TargetingEntities_forEach(const TargetingEntities& targetingEntities, const Functor& functor)
|
||||
{
|
||||
for(TargetingEntities::const_iterator i = targetingEntities.begin(); i != targetingEntities.end(); ++i)
|
||||
{
|
||||
TargetingEntity_forEach((*i).second, functor);
|
||||
}
|
||||
}
|
||||
|
||||
class TargetLinesPushBack
|
||||
{
|
||||
RenderablePointVector& m_targetLines;
|
||||
const Vector3& m_worldPosition;
|
||||
const VolumeTest& m_volume;
|
||||
public:
|
||||
TargetLinesPushBack(RenderablePointVector& targetLines, const Vector3& worldPosition, const VolumeTest& volume) :
|
||||
m_targetLines(targetLines), m_worldPosition(worldPosition), m_volume(volume)
|
||||
{
|
||||
}
|
||||
void operator()(const Vector3& worldPosition) const
|
||||
{
|
||||
if(m_volume.TestLine(segment_for_startend(m_worldPosition, worldPosition)))
|
||||
{
|
||||
m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(m_worldPosition)));
|
||||
m_targetLines.push_back(PointVertex(reinterpret_cast<const Vertex3f&>(worldPosition)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TargetKeys : public EntityKeyValues::Observer
|
||||
{
|
||||
TargetingEntities m_targetingEntities;
|
||||
Callback m_targetsChanged;
|
||||
|
||||
bool readTargetKey(const char* key, std::size_t& index)
|
||||
{
|
||||
if(string_equal_n(key, "target", 6))
|
||||
{
|
||||
index = 0;
|
||||
if(string_empty(key + 6) || string_parse_size(key + 6, index))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
void setTargetsChanged(const Callback& targetsChanged)
|
||||
{
|
||||
m_targetsChanged = targetsChanged;
|
||||
}
|
||||
void targetsChanged()
|
||||
{
|
||||
m_targetsChanged();
|
||||
}
|
||||
|
||||
void insert(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
std::size_t index;
|
||||
if(readTargetKey(key, index))
|
||||
{
|
||||
TargetingEntities::iterator i = m_targetingEntities.insert(TargetingEntities::value_type(index, TargetingEntity())).first;
|
||||
value.attach(TargetingEntity::TargetChangedCaller((*i).second));
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
std::size_t index;
|
||||
if(readTargetKey(key, index))
|
||||
{
|
||||
TargetingEntities::iterator i = m_targetingEntities.find(index);
|
||||
value.detach(TargetingEntity::TargetChangedCaller((*i).second));
|
||||
m_targetingEntities.erase(i);
|
||||
targetsChanged();
|
||||
}
|
||||
}
|
||||
const TargetingEntities& get() const
|
||||
{
|
||||
return m_targetingEntities;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RenderableTargetingEntity
|
||||
{
|
||||
TargetingEntity& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
public:
|
||||
static Shader* m_state;
|
||||
|
||||
RenderableTargetingEntity(TargetingEntity& targets)
|
||||
: m_targets(targets), m_target_lines(GL_LINES)
|
||||
{
|
||||
}
|
||||
void compile(const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
m_target_lines.clear();
|
||||
m_target_lines.reserve(m_targets.size() * 2);
|
||||
TargetingEntity_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
|
||||
}
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
if(!m_targets.empty())
|
||||
{
|
||||
compile(volume, world_position);
|
||||
if(!m_target_lines.empty())
|
||||
{
|
||||
renderer.addRenderable(m_target_lines, g_matrix4_identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RenderableTargetingEntities
|
||||
{
|
||||
const TargetingEntities& m_targets;
|
||||
mutable RenderablePointVector m_target_lines;
|
||||
public:
|
||||
static Shader* m_state;
|
||||
|
||||
RenderableTargetingEntities(const TargetingEntities& targets)
|
||||
: m_targets(targets), m_target_lines(GL_LINES)
|
||||
{
|
||||
}
|
||||
void compile(const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
m_target_lines.clear();
|
||||
TargetingEntities_forEach(m_targets, TargetLinesPushBack(m_target_lines, world_position, volume));
|
||||
}
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Vector3& world_position) const
|
||||
{
|
||||
if(!m_targets.empty())
|
||||
{
|
||||
compile(volume, world_position);
|
||||
if(!m_target_lines.empty())
|
||||
{
|
||||
renderer.addRenderable(m_target_lines, g_matrix4_identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TargetableInstance :
|
||||
public SelectableInstance,
|
||||
public Targetable,
|
||||
public EntityKeyValues::Observer
|
||||
{
|
||||
mutable Vertex3f m_position;
|
||||
EntityKeyValues& m_entity;
|
||||
TargetKeys m_targeting;
|
||||
TargetedEntity m_targeted;
|
||||
RenderableTargetingEntities m_renderable;
|
||||
public:
|
||||
|
||||
TargetableInstance(
|
||||
const scene::Path& path,
|
||||
scene::Instance* parent,
|
||||
void* instance,
|
||||
InstanceTypeCastTable& casts,
|
||||
EntityKeyValues& entity,
|
||||
Targetable& targetable
|
||||
) :
|
||||
SelectableInstance(path, parent, instance, casts),
|
||||
m_entity(entity),
|
||||
m_targeted(targetable),
|
||||
m_renderable(m_targeting.get())
|
||||
{
|
||||
m_entity.attach(*this);
|
||||
m_entity.attach(m_targeting);
|
||||
}
|
||||
~TargetableInstance()
|
||||
{
|
||||
m_entity.detach(m_targeting);
|
||||
m_entity.detach(*this);
|
||||
}
|
||||
|
||||
void setTargetsChanged(const Callback& targetsChanged)
|
||||
{
|
||||
m_targeting.setTargetsChanged(targetsChanged);
|
||||
}
|
||||
void targetsChanged()
|
||||
{
|
||||
m_targeting.targetsChanged();
|
||||
}
|
||||
|
||||
void insert(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
if(string_equal(key, g_targetable_nameKey))
|
||||
{
|
||||
value.attach(TargetedEntity::TargetnameChangedCaller(m_targeted));
|
||||
}
|
||||
}
|
||||
void erase(const char* key, EntityKeyValues::Value& value)
|
||||
{
|
||||
if(string_equal(key, g_targetable_nameKey))
|
||||
{
|
||||
value.detach(TargetedEntity::TargetnameChangedCaller(m_targeted));
|
||||
}
|
||||
}
|
||||
|
||||
const Vector3& world_position() const
|
||||
{
|
||||
#if 1
|
||||
const AABB& bounds = Instance::worldAABB();
|
||||
if(aabb_valid(bounds))
|
||||
{
|
||||
return bounds.origin;
|
||||
}
|
||||
#else
|
||||
const AABB& childBounds = Instance::childBounds();
|
||||
if(aabb_valid(childBounds))
|
||||
{
|
||||
return childBounds.origin;
|
||||
}
|
||||
#endif
|
||||
return localToWorld().t();
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly);
|
||||
renderer.SetState(m_entity.getEntityClass().m_state_wire, Renderer::eFullMaterials);
|
||||
m_renderable.render(renderer, volume, world_position());
|
||||
}
|
||||
|
||||
const TargetingEntities& getTargeting() const
|
||||
{
|
||||
return m_targeting.get();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RenderableConnectionLines : public Renderable
|
||||
{
|
||||
typedef std::set<TargetableInstance*> TargetableInstances;
|
||||
TargetableInstances m_instances;
|
||||
public:
|
||||
void attach(TargetableInstance& instance)
|
||||
{
|
||||
ASSERT_MESSAGE(m_instances.find(&instance) == m_instances.end(), "cannot attach instance");
|
||||
m_instances.insert(&instance);
|
||||
}
|
||||
void detach(TargetableInstance& instance)
|
||||
{
|
||||
ASSERT_MESSAGE(m_instances.find(&instance) != m_instances.end(), "cannot detach instance");
|
||||
m_instances.erase(&instance);
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
for(TargetableInstances::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i)
|
||||
{
|
||||
if((*i)->path().top().get().visible())
|
||||
{
|
||||
(*i)->render(renderer, volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
renderSolid(renderer, volume);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Static<RenderableConnectionLines> StaticRenderableConnectionLines;
|
||||
|
||||
#endif
|
||||
8
plugins/image/.cvsignore
Normal file
8
plugins/image/.cvsignore
Normal file
@@ -0,0 +1,8 @@
|
||||
Debug
|
||||
Release
|
||||
*.d
|
||||
*.plg
|
||||
*.BAK
|
||||
*.mak
|
||||
*.ncb
|
||||
*.opt
|
||||
207
plugins/image/bmp.cpp
Normal file
207
plugins/image/bmp.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
|
||||
typedef unsigned char PaletteEntry[4];
|
||||
typedef struct
|
||||
{
|
||||
char id[2];
|
||||
unsigned long fileSize;
|
||||
unsigned long reserved0;
|
||||
unsigned long bitmapDataOffset;
|
||||
unsigned long bitmapHeaderSize;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
unsigned short planes;
|
||||
unsigned short bitsPerPixel;
|
||||
unsigned long compression;
|
||||
unsigned long bitmapDataSize;
|
||||
unsigned long hRes;
|
||||
unsigned long vRes;
|
||||
unsigned long colors;
|
||||
unsigned long importantColors;
|
||||
PaletteEntry palette[256];
|
||||
} BMPHeader_t;
|
||||
|
||||
class ReadPixel8
|
||||
{
|
||||
PaletteEntry* m_palette;
|
||||
public:
|
||||
ReadPixel8(PaletteEntry* palette) : m_palette(palette)
|
||||
{
|
||||
}
|
||||
void operator()(PointerInputStream& inputStream, byte*& pixbuf) const
|
||||
{
|
||||
byte palIndex;
|
||||
inputStream.read(&palIndex, 1);
|
||||
*pixbuf++ = m_palette[palIndex][2];
|
||||
*pixbuf++ = m_palette[palIndex][1];
|
||||
*pixbuf++ = m_palette[palIndex][0];
|
||||
*pixbuf++ = 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
class ReadPixel16
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& inputStream, byte*& pixbuf) const
|
||||
{
|
||||
unsigned short shortPixel;
|
||||
inputStream.read(reinterpret_cast<byte*>(&shortPixel), sizeof(unsigned short)); //!\todo Is this endian safe?
|
||||
*pixbuf++ = static_cast<byte>(shortPixel & (31 << 10)) >> 7;
|
||||
*pixbuf++ = static_cast<byte>(shortPixel & (31 << 5)) >> 2;
|
||||
*pixbuf++ = static_cast<byte>(shortPixel & (31)) << 3;
|
||||
*pixbuf++ = 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
class ReadPixel24
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& inputStream, byte*& pixbuf) const
|
||||
{
|
||||
byte bgr[3];
|
||||
inputStream.read(bgr, 3);
|
||||
*pixbuf++ = bgr[2];
|
||||
*pixbuf++ = bgr[1];
|
||||
*pixbuf++ = bgr[0];
|
||||
*pixbuf++ = 255;
|
||||
}
|
||||
};
|
||||
|
||||
class ReadPixel32
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& inputStream, byte*& pixbuf) const
|
||||
{
|
||||
byte bgra[4];
|
||||
inputStream.read(bgra, 4);
|
||||
*pixbuf++ = bgra[2];
|
||||
*pixbuf++ = bgra[1];
|
||||
*pixbuf++ = bgra[0];
|
||||
*pixbuf++ = bgra[3];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ReadPixel>
|
||||
void ReadBMP(PointerInputStream& inputStream, byte* bmpRGBA, int rows, int columns, ReadPixel readPixel)
|
||||
{
|
||||
for (int row = rows - 1; row >= 0; row--)
|
||||
{
|
||||
byte* pixbuf = bmpRGBA + row * columns * 4;
|
||||
|
||||
for (int column = 0; column < columns; column++)
|
||||
{
|
||||
readPixel(inputStream, pixbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image* LoadBMPBuff(PointerInputStream& inputStream, std::size_t length)
|
||||
{
|
||||
BMPHeader_t bmpHeader;
|
||||
inputStream.read(reinterpret_cast<byte*>(bmpHeader.id), 2);
|
||||
bmpHeader.fileSize = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.reserved0 = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.bitmapDataOffset = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.bitmapHeaderSize = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.width = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.height = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.planes = istream_read_uint16_le(inputStream);
|
||||
bmpHeader.bitsPerPixel = istream_read_uint16_le(inputStream);
|
||||
bmpHeader.compression = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.bitmapDataSize = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.hRes = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.vRes = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.colors = istream_read_uint32_le(inputStream);
|
||||
bmpHeader.importantColors = istream_read_uint32_le(inputStream);
|
||||
|
||||
if (bmpHeader.bitsPerPixel == 8)
|
||||
{
|
||||
int paletteSize = bmpHeader.colors * 4;
|
||||
inputStream.read(reinterpret_cast<byte*>(bmpHeader.palette), paletteSize);
|
||||
}
|
||||
|
||||
if (bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M')
|
||||
{
|
||||
globalErrorStream() << "LoadBMP: only Windows-style BMP files supported\n";
|
||||
return 0;
|
||||
}
|
||||
if (bmpHeader.fileSize != length)
|
||||
{
|
||||
globalErrorStream() << "LoadBMP: header size does not match file size (" << Unsigned(bmpHeader.fileSize) << " vs. " << Unsigned(length) << ")\n";
|
||||
return 0;
|
||||
}
|
||||
if (bmpHeader.compression != 0)
|
||||
{
|
||||
globalErrorStream() << "LoadBMP: only uncompressed BMP files supported\n";
|
||||
return 0;
|
||||
}
|
||||
if (bmpHeader.bitsPerPixel < 8)
|
||||
{
|
||||
globalErrorStream() << "LoadBMP: monochrome and 4-bit BMP files not supported\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int columns = bmpHeader.width;
|
||||
int rows = bmpHeader.height;
|
||||
if (rows < 0)
|
||||
rows = -rows;
|
||||
|
||||
RGBAImage* image = new RGBAImage(columns, rows);
|
||||
|
||||
switch(bmpHeader.bitsPerPixel)
|
||||
{
|
||||
case 8:
|
||||
ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel8(bmpHeader.palette));
|
||||
break;
|
||||
case 16:
|
||||
ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel16());
|
||||
break;
|
||||
case 24:
|
||||
ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel24());
|
||||
break;
|
||||
case 32:
|
||||
ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel32());
|
||||
break;
|
||||
default:
|
||||
globalErrorStream() << "LoadBMP: illegal pixel_size '" << bmpHeader.bitsPerPixel << "'\n";
|
||||
image->release();
|
||||
return 0;
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadBMP(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
PointerInputStream inputStream(buffer.buffer);
|
||||
return LoadBMPBuff(inputStream, buffer.length);
|
||||
}
|
||||
31
plugins/image/bmp.h
Normal file
31
plugins/image/bmp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_BMP_H)
|
||||
#define INCLUDED_BMP_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadBMP(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
|
||||
56
plugins/image/dds.cpp
Normal file
56
plugins/image/dds.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "dds.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
#include "idatastream.h"
|
||||
|
||||
#include "ddslib.h"
|
||||
#include "imagelib.h"
|
||||
|
||||
Image* LoadDDSBuff(const byte* buffer)
|
||||
{
|
||||
int width, height;
|
||||
ddsPF_t pixelFormat;
|
||||
if(DDSGetInfo(reinterpret_cast<ddsBuffer_t*>(const_cast<byte*>(buffer)), &width, &height, &pixelFormat) == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
RGBAImage* image = new RGBAImage(width, height);
|
||||
|
||||
if(DDSDecompress(reinterpret_cast<ddsBuffer_t*>(const_cast<byte*>(buffer)), image->getRGBAPixels()) == -1)
|
||||
{
|
||||
image->release();
|
||||
return 0;
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadDDS(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadDDSBuff(buffer.buffer);
|
||||
}
|
||||
30
plugins/image/dds.h
Normal file
30
plugins/image/dds.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_DDS_H)
|
||||
#define INCLUDED_DDS_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadDDS(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
162
plugins/image/image.cpp
Normal file
162
plugins/image/image.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iimage.h"
|
||||
|
||||
#include "jpeg.h"
|
||||
#include "tga.h"
|
||||
#include "bmp.h"
|
||||
#include "pcx.h"
|
||||
#include "dds.h"
|
||||
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class ImageDependencies : public GlobalFileSystemModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class ImageTGAAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagetga;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "tga");
|
||||
|
||||
ImageTGAAPI()
|
||||
{
|
||||
m_imagetga.loadImage = LoadTGA;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagetga;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageTGAAPI> ImageTGAModule;
|
||||
|
||||
ImageTGAModule g_ImageTGAModule;
|
||||
|
||||
|
||||
class ImageJPGAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagejpg;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "jpg");
|
||||
|
||||
ImageJPGAPI()
|
||||
{
|
||||
m_imagejpg.loadImage = LoadJPG;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagejpg;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageJPGAPI, ImageDependencies> ImageJPGModule;
|
||||
|
||||
ImageJPGModule g_ImageJPGModule;
|
||||
|
||||
|
||||
class ImageBMPAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagebmp;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "bmp");
|
||||
|
||||
ImageBMPAPI()
|
||||
{
|
||||
m_imagebmp.loadImage = LoadBMP;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagebmp;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageBMPAPI, ImageDependencies> ImageBMPModule;
|
||||
|
||||
ImageBMPModule g_ImageBMPModule;
|
||||
|
||||
|
||||
class ImagePCXAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagepcx;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "pcx");
|
||||
|
||||
ImagePCXAPI()
|
||||
{
|
||||
m_imagepcx.loadImage = LoadPCX32;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagepcx;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImagePCXAPI, ImageDependencies> ImagePCXModule;
|
||||
|
||||
ImagePCXModule g_ImagePCXModule;
|
||||
|
||||
|
||||
class ImageDDSAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagedds;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "dds");
|
||||
|
||||
ImageDDSAPI()
|
||||
{
|
||||
m_imagedds.loadImage = LoadDDS;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagedds;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageDDSAPI, ImageDependencies> ImageDDSModule;
|
||||
|
||||
ImageDDSModule g_ImageDDSModule;
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ImageTGAModule.selfRegister();
|
||||
g_ImageJPGModule.selfRegister();
|
||||
g_ImageBMPModule.selfRegister();
|
||||
g_ImagePCXModule.selfRegister();
|
||||
g_ImageDDSModule.selfRegister();
|
||||
}
|
||||
166
plugins/image/image.dsp
Normal file
166
plugins/image/image.dsp
Normal file
@@ -0,0 +1,166 @@
|
||||
# Microsoft Developer Studio Project File - Name="image" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=image - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "image.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "image.mak" CFG="image - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "image - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "image - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "image"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "image - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\libs\jpeg6" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 glib-2.0.lib jpeg6.lib /nologo /dll /machine:I386 /def:".\image.def" /libpath:"../../libs/jpeg6/release" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\image.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "image - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\libs\jpeg6" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 glib-2.0.lib jpeg6.lib /nologo /dll /debug /machine:I386 /def:".\image.def" /pdbtype:sept /libpath:"../../libs/jpeg6/debug" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\image.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "image - Win32 Release"
|
||||
# Name "image - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bmp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\image.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\image.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jpeg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pcx.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tga.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bmp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\image.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jpeg.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pcx.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tga.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
25
plugins/image/image.h
Normal file
25
plugins/image/image.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_IMAGE_H)
|
||||
#define INCLUDED_IMAGE_H
|
||||
|
||||
#endif
|
||||
7
plugins/image/imageq3.def
Normal file
7
plugins/image/imageq3.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; imageq3.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ImageQ3"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
231
plugins/image/imageq3.vcproj
Normal file
231
plugins/image/imageq3.vcproj
Normal file
@@ -0,0 +1,231 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="imageq3"
|
||||
ProjectGUID="{0A0D3519-2ADD-4B47-A890-746170B2CCD8}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/glib-2.0/include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IMAGEQ3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/imageq3.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/imageq3.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/imageq3.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="../../include;../../libs;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/glib-2.0/include""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IMAGEQ3_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/imageq3.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
ModuleDefinitionFile="$(ProjectName).def"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/imageq3.lib"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install\modules"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install\modules""/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\image.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\image.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="modules"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\bmp.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\bmp.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dds.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dds.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\jpeg.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\jpeg.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pcx.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pcx.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tga.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tga.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py""
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imageq3.def">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py" "$(TargetPath)"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\modules\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
406
plugins/image/jpeg.cpp
Normal file
406
plugins/image/jpeg.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//
|
||||
// Functions to load JPEG files from a buffer, based on jdatasrc.c
|
||||
//
|
||||
// Leonardo Zide (leo@lokigames.com)
|
||||
//
|
||||
|
||||
#include "jpeg.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "radiant_jpeglib.h"
|
||||
#include "jpeg6/jerror.h"
|
||||
}
|
||||
|
||||
#include "ifilesystem.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* Expanded data source object for stdio input */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
int src_size;
|
||||
JOCTET * src_buffer;
|
||||
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
boolean start_of_file; /* have we gotten any data yet? */
|
||||
} my_source_mgr;
|
||||
|
||||
typedef my_source_mgr * my_src_ptr;
|
||||
|
||||
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
|
||||
static void my_init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
/* We reset the empty-input-file flag for each image,
|
||||
* but we don't clear the input buffer.
|
||||
* This is correct behavior for reading a series of images from one source.
|
||||
*/
|
||||
src->start_of_file = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
*
|
||||
* In typical applications, this should read fresh data into the buffer
|
||||
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
||||
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||
* indicating that the buffer has been reloaded. It is not necessary to
|
||||
* fill the buffer entirely, only to obtain at least one more byte.
|
||||
*
|
||||
* There is no such thing as an EOF return. If the end of the file has been
|
||||
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
||||
* the buffer. In most cases, generating a warning message and inserting a
|
||||
* fake EOI marker is the best course of action --- this will allow the
|
||||
* decompressor to output however much of the image is there. However,
|
||||
* the resulting error message is misleading if the real problem is an empty
|
||||
* input file, so we handle that case specially.
|
||||
*
|
||||
* In applications that need to be able to suspend compression due to input
|
||||
* not being available yet, a FALSE return indicates that no more data can be
|
||||
* obtained right now, but more may be forthcoming later. In this situation,
|
||||
* the decompressor will return to its caller (with an indication of the
|
||||
* number of scanlines it has read, if any). The application should resume
|
||||
* decompression after it has loaded more data into the input buffer. Note
|
||||
* that there are substantial restrictions on the use of suspension --- see
|
||||
* the documentation.
|
||||
*
|
||||
* When suspending, the decompressor will back up to a convenient restart point
|
||||
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
|
||||
* indicate where the restart point will be if the current call returns FALSE.
|
||||
* Data beyond this point must be rescanned after resumption, so move it to
|
||||
* the front of the buffer rather than discarding it.
|
||||
*/
|
||||
|
||||
static boolean my_fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
size_t nbytes;
|
||||
|
||||
if (src->src_size > INPUT_BUF_SIZE)
|
||||
nbytes = INPUT_BUF_SIZE;
|
||||
else
|
||||
nbytes = src->src_size;
|
||||
|
||||
memcpy (src->buffer, src->src_buffer, nbytes);
|
||||
src->src_buffer += nbytes;
|
||||
src->src_size -= nbytes;
|
||||
|
||||
if (nbytes <= 0) {
|
||||
if (src->start_of_file) /* Treat empty input file as fatal error */
|
||||
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||
WARNMS(cinfo, JWRN_JPEG_EOF);
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (JOCTET) 0xFF;
|
||||
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->start_of_file = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*
|
||||
* Writers of suspendable-input applications must note that skip_input_data
|
||||
* is not granted the right to give a suspension return. If the skip extends
|
||||
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||
* Arranging for additional bytes to be discarded before reloading the input
|
||||
* buffer is the application writer's problem.
|
||||
*/
|
||||
|
||||
static void my_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
/* Just a dumb implementation for now. Could use fseek() except
|
||||
* it doesn't work on pipes. Not clear that being smart is worth
|
||||
* any trouble anyway --- large skips are infrequent.
|
||||
*/
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) my_fill_input_buffer(cinfo);
|
||||
/* note we assume that fill_input_buffer will never return FALSE,
|
||||
* so suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* An additional method that can be provided by data source modules is the
|
||||
* resync_to_restart method for error recovery in the presence of RST markers.
|
||||
* For the moment, this source module just uses the default resync method
|
||||
* provided by the JPEG library. That method assumes that no backtracking
|
||||
* is possible.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read. Often a no-op.
|
||||
*
|
||||
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||
* application must deal with any cleanup that should happen even
|
||||
* for error exit.
|
||||
*/
|
||||
|
||||
static void my_term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no work necessary here */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for input from a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
|
||||
static void jpeg_buffer_src (j_decompress_ptr cinfo, void* buffer, int bufsize)
|
||||
{
|
||||
my_src_ptr src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof (my_source_mgr));
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->buffer = (JOCTET *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
INPUT_BUF_SIZE * sizeof (JOCTET));
|
||||
}
|
||||
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->pub.init_source = my_init_source;
|
||||
src->pub.fill_input_buffer = my_fill_input_buffer;
|
||||
src->pub.skip_input_data = my_skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = my_term_source;
|
||||
src->src_buffer = (JOCTET *)buffer;
|
||||
src->src_size = bufsize;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
static char errormsg[JMSG_LENGTH_MAX];
|
||||
|
||||
typedef struct my_jpeg_error_mgr
|
||||
{
|
||||
struct jpeg_error_mgr pub; // "public" fields
|
||||
jmp_buf setjmp_buffer; // for return to caller
|
||||
} bt_jpeg_error_mgr;
|
||||
|
||||
static void my_jpeg_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
my_jpeg_error_mgr* myerr = (bt_jpeg_error_mgr*) cinfo->err;
|
||||
|
||||
(*cinfo->err->format_message) (cinfo, errormsg);
|
||||
|
||||
longjmp (myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
// stash a scanline
|
||||
static void j_putRGBScanline (unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row)
|
||||
{
|
||||
int offset = row * widthPix * 4;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < widthPix; count++)
|
||||
{
|
||||
unsigned char iRed, iBlu, iGrn;
|
||||
unsigned char *oRed, *oBlu, *oGrn, *oAlp;
|
||||
|
||||
iRed = *(jpegline + count * 3 + 0);
|
||||
iGrn = *(jpegline + count * 3 + 1);
|
||||
iBlu = *(jpegline + count * 3 + 2);
|
||||
|
||||
oRed = outBuf + offset + count * 4 + 0;
|
||||
oGrn = outBuf + offset + count * 4 + 1;
|
||||
oBlu = outBuf + offset + count * 4 + 2;
|
||||
oAlp = outBuf + offset + count * 4 + 3;
|
||||
|
||||
*oRed = iRed;
|
||||
*oGrn = iGrn;
|
||||
*oBlu = iBlu;
|
||||
*oAlp = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// stash a scanline
|
||||
static void j_putRGBAScanline (unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row)
|
||||
{
|
||||
int offset = row * widthPix * 4;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < widthPix; count++)
|
||||
{
|
||||
unsigned char iRed, iBlu, iGrn, iAlp;
|
||||
unsigned char *oRed, *oBlu, *oGrn, *oAlp;
|
||||
|
||||
iRed = *(jpegline + count * 4 + 0);
|
||||
iGrn = *(jpegline + count * 4 + 1);
|
||||
iBlu = *(jpegline + count * 4 + 2);
|
||||
iAlp = *(jpegline + count * 4 + 3);
|
||||
|
||||
oRed = outBuf + offset + count * 4 + 0;
|
||||
oGrn = outBuf + offset + count * 4 + 1;
|
||||
oBlu = outBuf + offset + count * 4 + 2;
|
||||
oAlp = outBuf + offset + count * 4 + 3;
|
||||
|
||||
*oRed = iRed;
|
||||
*oGrn = iGrn;
|
||||
*oBlu = iBlu;
|
||||
|
||||
//!\todo fix jpeglib, it leaves alpha channel uninitialised
|
||||
#if 1
|
||||
*oAlp = 255;
|
||||
#else
|
||||
*oAlp = iAlp;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// stash a gray scanline
|
||||
static void j_putGrayScanlineToRGB (unsigned char* jpegline, int widthPix, unsigned char* outBuf, int row)
|
||||
{
|
||||
int offset = row * widthPix * 4;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < widthPix; count++)
|
||||
{
|
||||
unsigned char iGray;
|
||||
unsigned char *oRed, *oBlu, *oGrn, *oAlp;
|
||||
|
||||
// get our grayscale value
|
||||
iGray = *(jpegline + count);
|
||||
|
||||
oRed = outBuf + offset + count * 4;
|
||||
oGrn = outBuf + offset + count * 4 + 1;
|
||||
oBlu = outBuf + offset + count * 4 + 2;
|
||||
oAlp = outBuf + offset + count * 4 + 3;
|
||||
|
||||
*oRed = iGray;
|
||||
*oGrn = iGray;
|
||||
*oBlu = iGray;
|
||||
*oAlp = 255;
|
||||
}
|
||||
}
|
||||
|
||||
static Image* LoadJPGBuff_(const void *src_buffer, int src_size)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_jpeg_error_mgr jerr;
|
||||
|
||||
cinfo.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = my_jpeg_error_exit;
|
||||
|
||||
if (setjmp (jerr.setjmp_buffer)) //< TODO: use c++ exceptions instead of setjmp/longjmp to handle errors
|
||||
{
|
||||
globalErrorStream() << "WARNING: JPEG library error: " << errormsg << "\n";
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jpeg_create_decompress (&cinfo);
|
||||
jpeg_buffer_src (&cinfo, const_cast<void*>(src_buffer), src_size);
|
||||
jpeg_read_header (&cinfo, TRUE);
|
||||
jpeg_start_decompress (&cinfo);
|
||||
|
||||
int row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
RGBAImage* image = new RGBAImage(cinfo.output_width, cinfo.output_height);
|
||||
|
||||
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height)
|
||||
{
|
||||
jpeg_read_scanlines (&cinfo, buffer, 1);
|
||||
|
||||
if (cinfo.out_color_components == 4)
|
||||
j_putRGBAScanline (buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline-1);
|
||||
else if (cinfo.out_color_components == 3)
|
||||
j_putRGBScanline (buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline-1);
|
||||
else if (cinfo.out_color_components == 1)
|
||||
j_putGrayScanlineToRGB (buffer[0], cinfo.output_width, image->getRGBAPixels(), cinfo.output_scanline-1);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress (&cinfo);
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadJPG(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadJPGBuff_(buffer.buffer, static_cast<int>(buffer.length));
|
||||
}
|
||||
|
||||
40
plugins/image/jpeg.h
Normal file
40
plugins/image/jpeg.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_JPEG_H)
|
||||
#define INCLUDED_JPEG_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadJPG(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
|
||||
222
plugins/image/pcx.cpp
Normal file
222
plugins/image/pcx.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pcx.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
PCX LOADING
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char manufacturer;
|
||||
unsigned char version;
|
||||
unsigned char encoding;
|
||||
unsigned char bits_per_pixel;
|
||||
unsigned short xmin, ymin, xmax, ymax;
|
||||
unsigned short hres, vres;
|
||||
unsigned char palette[48];
|
||||
unsigned char reserved;
|
||||
unsigned char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
unsigned char filler[58];
|
||||
unsigned char data; // unbounded
|
||||
} pcx_t;
|
||||
|
||||
/*
|
||||
==============
|
||||
LoadPCX
|
||||
==============
|
||||
*/
|
||||
|
||||
struct PCXRLEPacket
|
||||
{
|
||||
byte data;
|
||||
int length;
|
||||
};
|
||||
|
||||
inline void ByteStream_readPCXRLEPacket(PointerInputStream& inputStream, PCXRLEPacket& packet)
|
||||
{
|
||||
byte d;
|
||||
inputStream.read(&d, 1);
|
||||
if((d & 0xC0) == 0xC0)
|
||||
{
|
||||
packet.length = d & 0x3F;
|
||||
inputStream.read(&packet.data, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.length = 1;
|
||||
packet.data = d;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadPCXBuff(byte* buffer, std::size_t len, byte **pic, byte **palette, int *width, int *height )
|
||||
{
|
||||
*pic = 0;
|
||||
|
||||
pcx_t pcx;
|
||||
int x, y, lsize;
|
||||
byte *out, *pix;
|
||||
|
||||
/* parse the PCX file */
|
||||
|
||||
PointerInputStream inputStream(buffer);
|
||||
|
||||
pcx.manufacturer = istream_read_byte(inputStream);
|
||||
pcx.version = istream_read_byte(inputStream);
|
||||
pcx.encoding = istream_read_byte(inputStream);
|
||||
pcx.bits_per_pixel = istream_read_byte(inputStream);
|
||||
pcx.xmin = istream_read_int16_le(inputStream);
|
||||
pcx.ymin = istream_read_int16_le(inputStream);
|
||||
pcx.xmax = istream_read_int16_le(inputStream);
|
||||
pcx.ymax = istream_read_int16_le(inputStream);
|
||||
pcx.hres = istream_read_int16_le(inputStream);
|
||||
pcx.vres = istream_read_int16_le(inputStream);
|
||||
inputStream.read(pcx.palette, 48);
|
||||
pcx.reserved = istream_read_byte(inputStream);
|
||||
pcx.color_planes = istream_read_byte(inputStream);
|
||||
pcx.bytes_per_line = istream_read_int16_le(inputStream);
|
||||
pcx.palette_type = istream_read_int16_le(inputStream);
|
||||
inputStream.read(pcx.filler, 58);
|
||||
|
||||
|
||||
if (pcx.manufacturer != 0x0a
|
||||
|| pcx.version != 5
|
||||
|| pcx.encoding != 1
|
||||
|| pcx.bits_per_pixel != 8)
|
||||
return;
|
||||
|
||||
if (width)
|
||||
*width = pcx.xmax+1;
|
||||
if (height)
|
||||
*height = pcx.ymax+1;
|
||||
|
||||
if (!pic)
|
||||
return;
|
||||
|
||||
out = (byte *)malloc ( (pcx.ymax+1) * (pcx.xmax+1) );
|
||||
|
||||
*pic = out;
|
||||
pix = out;
|
||||
|
||||
/* RR2DO2: pcx fix */
|
||||
lsize = pcx.color_planes * pcx.bytes_per_line;
|
||||
|
||||
/* go scanline by scanline */
|
||||
for( y = 0; y <= pcx.ymax; y++, pix += pcx.xmax + 1 )
|
||||
{
|
||||
/* do a scanline */
|
||||
for( x=0; x <= pcx.xmax; )
|
||||
{
|
||||
/* RR2DO2 */
|
||||
PCXRLEPacket packet;
|
||||
ByteStream_readPCXRLEPacket(inputStream, packet);
|
||||
|
||||
while(packet.length-- > 0)
|
||||
{
|
||||
pix[ x++ ] = packet.data;
|
||||
}
|
||||
}
|
||||
|
||||
/* RR2DO2: discard any other data */
|
||||
PCXRLEPacket packet;
|
||||
while( x < lsize )
|
||||
{
|
||||
ByteStream_readPCXRLEPacket(inputStream, packet);
|
||||
x++;
|
||||
}
|
||||
while( packet.length-- > 0 )
|
||||
{
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
/* validity check */
|
||||
if( std::size_t(inputStream.get() - buffer) > len)
|
||||
{
|
||||
*pic = 0;
|
||||
}
|
||||
|
||||
if (palette)
|
||||
{
|
||||
*palette = (byte *)malloc(768);
|
||||
memcpy (*palette, buffer + len - 768, 768);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
LoadPCX32
|
||||
==============
|
||||
*/
|
||||
Image* LoadPCX32Buff(byte* buffer, std::size_t length)
|
||||
{
|
||||
byte *palette;
|
||||
byte *pic8;
|
||||
int i, c, p, width, height;
|
||||
byte *pic32;
|
||||
|
||||
LoadPCXBuff(buffer, length, &pic8, &palette, &width, &height);
|
||||
if (!pic8)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
RGBAImage* image = new RGBAImage(width, height);
|
||||
c = (width) * (height);
|
||||
pic32 = image->getRGBAPixels();
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
p = pic8[i];
|
||||
pic32[0] = palette[p * 3];
|
||||
pic32[1] = palette[p * 3 + 1];
|
||||
pic32[2] = palette[p * 3 + 2];
|
||||
pic32[3] = 255;
|
||||
pic32 += 4;
|
||||
}
|
||||
|
||||
free (pic8);
|
||||
free (palette);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadPCX32(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadPCX32Buff(buffer.buffer, buffer.length);
|
||||
}
|
||||
|
||||
30
plugins/image/pcx.h
Normal file
30
plugins/image/pcx.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_PCX_H)
|
||||
#define INCLUDED_PCX_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadPCX32(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
420
plugins/image/tga.cpp
Normal file
420
plugins/image/tga.cpp
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "tga.h"
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
#include "idatastream.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "generic/bitfield.h"
|
||||
#include "imagelib.h"
|
||||
#include "bytestreamutils.h"
|
||||
|
||||
// represents x,y origin of tga image being decoded
|
||||
class Flip00 {}; // no flip
|
||||
class Flip01 {}; // vertical flip only
|
||||
class Flip10 {}; // horizontal flip only
|
||||
class Flip11 {}; // both
|
||||
|
||||
template<typename PixelDecoder>
|
||||
void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip00&)
|
||||
{
|
||||
RGBAPixel* end = image.pixels + (image.height * image.width);
|
||||
for(RGBAPixel* row = end; row != image.pixels; row -= image.width)
|
||||
{
|
||||
for(RGBAPixel* pixel = row - image.width; pixel != row; ++pixel)
|
||||
{
|
||||
decode(istream, *pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelDecoder>
|
||||
void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip01&)
|
||||
{
|
||||
RGBAPixel* end = image.pixels + (image.height * image.width);
|
||||
for(RGBAPixel* row = image.pixels; row != end; row += image.width)
|
||||
{
|
||||
for(RGBAPixel* pixel = row; pixel != row + image.width; ++pixel)
|
||||
{
|
||||
decode(istream, *pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelDecoder>
|
||||
void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip10&)
|
||||
{
|
||||
RGBAPixel* end = image.pixels + (image.height * image.width);
|
||||
for(RGBAPixel* row = end; row != image.pixels; row -= image.width)
|
||||
{
|
||||
for(RGBAPixel* pixel = row; pixel != row - image.width;)
|
||||
{
|
||||
decode(istream, *--pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PixelDecoder>
|
||||
void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip11&)
|
||||
{
|
||||
RGBAPixel* end = image.pixels + (image.height * image.width);
|
||||
for(RGBAPixel* row = image.pixels; row != end; row += image.width)
|
||||
{
|
||||
for(RGBAPixel* pixel = row + image.width; pixel != row;)
|
||||
{
|
||||
decode(istream, *--pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void istream_read_gray(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream.read(&pixel.blue, 1);
|
||||
pixel.red = pixel.green = pixel.blue;
|
||||
pixel.alpha = 0xff;
|
||||
}
|
||||
|
||||
inline void istream_read_rgb(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream.read(&pixel.blue, 1);
|
||||
istream.read(&pixel.green, 1);
|
||||
istream.read(&pixel.red, 1);
|
||||
pixel.alpha = 0xff;
|
||||
}
|
||||
|
||||
inline void istream_read_rgba(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream.read(&pixel.blue, 1);
|
||||
istream.read(&pixel.green, 1);
|
||||
istream.read(&pixel.red, 1);
|
||||
istream.read(&pixel.alpha, 1);
|
||||
}
|
||||
|
||||
class TargaDecodeGrayPixel
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream_read_gray(istream, pixel);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
void targa_decode_grayscale(PointerInputStream& istream, RGBAImage& image, const Flip& flip)
|
||||
{
|
||||
TargaDecodeGrayPixel decode;
|
||||
image_decode(istream, decode, image, flip);
|
||||
}
|
||||
|
||||
class TargaDecodeRGBPixel
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream_read_rgb(istream, pixel);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
void targa_decode_rgb(PointerInputStream& istream, RGBAImage& image, const Flip& flip)
|
||||
{
|
||||
TargaDecodeRGBPixel decode;
|
||||
image_decode(istream, decode, image, flip);
|
||||
}
|
||||
|
||||
class TargaDecodeRGBAPixel
|
||||
{
|
||||
public:
|
||||
void operator()(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
istream_read_rgba(istream, pixel);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
void targa_decode_rgba(PointerInputStream& istream, RGBAImage& image, const Flip& flip)
|
||||
{
|
||||
TargaDecodeRGBAPixel decode;
|
||||
image_decode(istream, decode, image, flip);
|
||||
}
|
||||
|
||||
typedef byte TargaPacket;
|
||||
typedef byte TargaPacketSize;
|
||||
|
||||
inline void targa_packet_read_istream(TargaPacket& packet, PointerInputStream& istream)
|
||||
{
|
||||
istream.read(&packet, 1);
|
||||
}
|
||||
|
||||
inline bool targa_packet_is_rle(const TargaPacket& packet)
|
||||
{
|
||||
return (packet & 0x80) != 0;
|
||||
}
|
||||
|
||||
inline TargaPacketSize targa_packet_size(const TargaPacket& packet)
|
||||
{
|
||||
return 1 + (packet & 0x7f);
|
||||
}
|
||||
|
||||
|
||||
class TargaDecodeRGBPixelRLE
|
||||
{
|
||||
TargaPacketSize m_packetSize;
|
||||
RGBAPixel m_pixel;
|
||||
TargaPacket m_packet;
|
||||
public:
|
||||
TargaDecodeRGBPixelRLE() : m_packetSize(0)
|
||||
{
|
||||
}
|
||||
void operator()(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
if(m_packetSize == 0)
|
||||
{
|
||||
targa_packet_read_istream(m_packet, istream);
|
||||
m_packetSize = targa_packet_size(m_packet);
|
||||
|
||||
if(targa_packet_is_rle(m_packet))
|
||||
{
|
||||
istream_read_rgb(istream, m_pixel);
|
||||
}
|
||||
}
|
||||
|
||||
if(targa_packet_is_rle(m_packet))
|
||||
{
|
||||
pixel = m_pixel;
|
||||
}
|
||||
else
|
||||
{
|
||||
istream_read_rgb(istream, pixel);
|
||||
}
|
||||
|
||||
--m_packetSize;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
void targa_decode_rle_rgb(PointerInputStream& istream, RGBAImage& image, const Flip& flip)
|
||||
{
|
||||
TargaDecodeRGBPixelRLE decode;
|
||||
image_decode(istream, decode, image, flip);
|
||||
}
|
||||
|
||||
class TargaDecodeRGBAPixelRLE
|
||||
{
|
||||
TargaPacketSize m_packetSize;
|
||||
RGBAPixel m_pixel;
|
||||
TargaPacket m_packet;
|
||||
public:
|
||||
TargaDecodeRGBAPixelRLE() : m_packetSize(0)
|
||||
{
|
||||
}
|
||||
void operator()(PointerInputStream& istream, RGBAPixel& pixel)
|
||||
{
|
||||
if(m_packetSize == 0)
|
||||
{
|
||||
targa_packet_read_istream(m_packet, istream);
|
||||
m_packetSize = targa_packet_size(m_packet);
|
||||
|
||||
if(targa_packet_is_rle(m_packet))
|
||||
{
|
||||
istream_read_rgba(istream, m_pixel);
|
||||
}
|
||||
}
|
||||
|
||||
if(targa_packet_is_rle(m_packet))
|
||||
{
|
||||
pixel = m_pixel;
|
||||
}
|
||||
else
|
||||
{
|
||||
istream_read_rgba(istream, pixel);
|
||||
}
|
||||
|
||||
--m_packetSize;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
void targa_decode_rle_rgba(PointerInputStream& istream, RGBAImage& image, const Flip& flip)
|
||||
{
|
||||
TargaDecodeRGBAPixelRLE decode;
|
||||
image_decode(istream, decode, image, flip);
|
||||
}
|
||||
|
||||
struct TargaHeader
|
||||
{
|
||||
unsigned char id_length, colormap_type, image_type;
|
||||
unsigned short colormap_index, colormap_length;
|
||||
unsigned char colormap_size;
|
||||
unsigned short x_origin, y_origin, width, height;
|
||||
unsigned char pixel_size, attributes;
|
||||
};
|
||||
|
||||
inline void targa_header_read_istream(TargaHeader& targa_header, PointerInputStream& istream)
|
||||
{
|
||||
targa_header.id_length = istream_read_byte(istream);
|
||||
targa_header.colormap_type = istream_read_byte(istream);
|
||||
targa_header.image_type = istream_read_byte(istream);
|
||||
|
||||
targa_header.colormap_index = istream_read_int16_le(istream);
|
||||
targa_header.colormap_length = istream_read_int16_le(istream);
|
||||
targa_header.colormap_size = istream_read_byte(istream);
|
||||
targa_header.x_origin = istream_read_int16_le(istream);
|
||||
targa_header.y_origin = istream_read_int16_le(istream);
|
||||
targa_header.width = istream_read_int16_le(istream);
|
||||
targa_header.height = istream_read_int16_le(istream);
|
||||
targa_header.pixel_size = istream_read_byte(istream);
|
||||
targa_header.attributes = istream_read_byte(istream);
|
||||
|
||||
if (targa_header.id_length != 0)
|
||||
istream.seek(targa_header.id_length); // skip TARGA image comment
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
class ScopeDelete
|
||||
{
|
||||
Type* m_value;
|
||||
ScopeDelete(const ScopeDelete&);
|
||||
ScopeDelete& operator=(const ScopeDelete&);
|
||||
public:
|
||||
ScopeDelete(Type* value) : m_value(value)
|
||||
{
|
||||
}
|
||||
~ScopeDelete()
|
||||
{
|
||||
delete m_value;
|
||||
}
|
||||
Type* get_pointer() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Flip>
|
||||
Image* Targa_decodeImageData(const TargaHeader& targa_header, PointerInputStream& istream, const Flip& flip)
|
||||
{
|
||||
RGBAImage* image = new RGBAImage(targa_header.width, targa_header.height);
|
||||
|
||||
if (targa_header.image_type == 2 || targa_header.image_type == 3)
|
||||
{
|
||||
switch (targa_header.pixel_size)
|
||||
{
|
||||
case 8:
|
||||
targa_decode_grayscale(istream, *image, flip);
|
||||
break;
|
||||
case 24:
|
||||
targa_decode_rgb(istream, *image, flip);
|
||||
break;
|
||||
case 32:
|
||||
targa_decode_rgba(istream, *image, flip);
|
||||
break;
|
||||
default:
|
||||
globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n";
|
||||
image->release();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (targa_header.image_type == 10)
|
||||
{
|
||||
switch (targa_header.pixel_size)
|
||||
{
|
||||
case 24:
|
||||
targa_decode_rle_rgb(istream, *image, flip);
|
||||
break;
|
||||
case 32:
|
||||
targa_decode_rle_rgba(istream, *image, flip);
|
||||
break;
|
||||
default:
|
||||
globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n";
|
||||
image->release();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
const unsigned int TGA_FLIP_HORIZONTAL = 0x10;
|
||||
const unsigned int TGA_FLIP_VERTICAL = 0x20;
|
||||
|
||||
Image* LoadTGABuff(const byte* buffer)
|
||||
{
|
||||
PointerInputStream istream(buffer);
|
||||
TargaHeader targa_header;
|
||||
|
||||
targa_header_read_istream(targa_header, istream);
|
||||
|
||||
if (targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3)
|
||||
{
|
||||
globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n";
|
||||
globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (targa_header.colormap_type != 0)
|
||||
{
|
||||
globalErrorStream() << "LoadTGA: colormaps not supported\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((targa_header.pixel_size != 32 && targa_header.pixel_size != 24)
|
||||
&& targa_header.image_type != 3)
|
||||
{
|
||||
globalErrorStream() << "LoadTGA: Only 32 or 24 bit images supported\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL)
|
||||
&& !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL))
|
||||
{
|
||||
return Targa_decodeImageData(targa_header, istream, Flip00());
|
||||
}
|
||||
if(!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL)
|
||||
&& bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL))
|
||||
{
|
||||
return Targa_decodeImageData(targa_header, istream, Flip01());
|
||||
}
|
||||
if(bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL)
|
||||
&& !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL))
|
||||
{
|
||||
return Targa_decodeImageData(targa_header, istream, Flip10());
|
||||
}
|
||||
if(bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL)
|
||||
&& bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL))
|
||||
{
|
||||
return Targa_decodeImageData(targa_header, istream, Flip11());
|
||||
}
|
||||
|
||||
// unreachable
|
||||
return 0;
|
||||
}
|
||||
|
||||
Image* LoadTGA(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadTGABuff(buffer.buffer);
|
||||
}
|
||||
31
plugins/image/tga.h
Normal file
31
plugins/image/tga.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_TGA_H)
|
||||
#define INCLUDED_TGA_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadTGA(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
|
||||
157
plugins/imagehl/hlw.cpp
Normal file
157
plugins/imagehl/hlw.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// by Hydra - hydra@hydras-world.com
|
||||
//
|
||||
// HLW = Half-Life-WAD, I don't know if the actual in data in the WAD files
|
||||
// has it's own name, so I'm just calling the individal textures .HLW files :)
|
||||
//
|
||||
// Thanks to the guys that made Wally for releasing an example WAD loader.
|
||||
// without it this would not have been possible.
|
||||
|
||||
#include "hlw.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#include "ifilesystem.h"
|
||||
|
||||
#include "imagelib.h"
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
HLW IMAGE
|
||||
|
||||
HalfLife WAD files contain files that look like this:
|
||||
|
||||
Mip section
|
||||
First mip
|
||||
Mip header
|
||||
First mip (width * height)
|
||||
Second mip (width * height / 4)
|
||||
Third mip (width * height / 16)
|
||||
Fourth mip (width * height / 64)
|
||||
Palette size (WORD)
|
||||
Palette (Palette size * 3)
|
||||
Padding (WORD)
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define GET_MIP_DATA_SIZE(WIDTH, HEIGHT) (sizeof(WAD3_MIP) + (WIDTH * HEIGHT) + (WIDTH * HEIGHT / 4) + (WIDTH * HEIGHT / 16) + (WIDTH * HEIGHT / 64))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[16];
|
||||
unsigned int width, height;
|
||||
unsigned int offsets[4]; // four mip maps stored
|
||||
} WAD3_MIP, *LPWAD3_MIP;
|
||||
|
||||
/*
|
||||
=========================================================
|
||||
|
||||
HLW LOADING
|
||||
|
||||
Hydra: this code isn't bullet proof and probably won't
|
||||
like corrupt WAD files, but it works for now.
|
||||
|
||||
TODO: make it more robust.
|
||||
=========================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
LoadHLW
|
||||
=============
|
||||
*/
|
||||
|
||||
Image* LoadHLWBuff(byte* buffer)
|
||||
{
|
||||
byte *buf_p;
|
||||
unsigned long mipdatasize;
|
||||
int columns, rows, numPixels;
|
||||
byte *pixbuf;
|
||||
int row, column;
|
||||
byte *palette;
|
||||
LPWAD3_MIP lpMip;
|
||||
unsigned char red, green, blue, alphabyte;
|
||||
|
||||
lpMip = (LPWAD3_MIP)buffer; //!\todo Make endian-safe.
|
||||
|
||||
mipdatasize = GET_MIP_DATA_SIZE(lpMip->width,lpMip->height);
|
||||
|
||||
palette = buffer+mipdatasize+2;
|
||||
|
||||
buf_p = buffer+lpMip->offsets[0];
|
||||
|
||||
columns = lpMip->width;
|
||||
rows = lpMip->height;
|
||||
numPixels = columns * rows;
|
||||
|
||||
RGBAImage* image = new RGBAImage(columns, rows);
|
||||
|
||||
for (row = 0; row < rows; row++)
|
||||
{
|
||||
pixbuf = image->getRGBAPixels() + row * columns * 4;
|
||||
|
||||
for (column = 0; column < columns; column++)
|
||||
{
|
||||
int palIndex;
|
||||
|
||||
palIndex = *buf_p++;
|
||||
|
||||
red = *(palette+(palIndex*3));
|
||||
green = *(palette+(palIndex*3)+1);
|
||||
blue = *(palette+(palIndex*3)+2);
|
||||
|
||||
// HalfLife engine makes pixels that are BLUE transparent.
|
||||
// So show them that way in the editor.
|
||||
if (blue == 0xff && red == 0x00 && green == 0x00)
|
||||
{
|
||||
alphabyte = 0x00;
|
||||
blue = 0x00; // don't set the resulting pixel to blue
|
||||
}
|
||||
else
|
||||
{
|
||||
alphabyte = 0xff;
|
||||
}
|
||||
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
|
||||
*pixbuf++ = alphabyte;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
Image* LoadHLW(ArchiveFile& file)
|
||||
{
|
||||
ScopedArchiveBuffer buffer(file);
|
||||
return LoadHLWBuff(buffer.buffer );
|
||||
}
|
||||
31
plugins/imagehl/hlw.h
Normal file
31
plugins/imagehl/hlw.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_HLW_H)
|
||||
#define INCLUDED_HLW_H
|
||||
|
||||
class Image;
|
||||
class ArchiveFile;
|
||||
|
||||
Image* LoadHLW(ArchiveFile& file);
|
||||
|
||||
#endif
|
||||
|
||||
116
plugins/imagehl/imagehl.cpp
Normal file
116
plugins/imagehl/imagehl.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "imagehl.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iimage.h"
|
||||
|
||||
#include "hlw.h"
|
||||
#include "mip.h"
|
||||
#include "sprite.h"
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
|
||||
class ImageDependencies : public GlobalFileSystemModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class ImageHLWAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagehlw;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "hlw");
|
||||
|
||||
ImageHLWAPI()
|
||||
{
|
||||
m_imagehlw.loadImage = LoadHLW;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagehlw;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageHLWAPI, ImageDependencies> ImageHLWModule;
|
||||
|
||||
ImageHLWModule g_ImageHLWModule;
|
||||
|
||||
|
||||
class ImageMipAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagemip;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "mip");
|
||||
|
||||
ImageMipAPI()
|
||||
{
|
||||
m_imagemip.loadImage = LoadMIP;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagemip;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageMipAPI, ImageDependencies> ImageMipModule;
|
||||
|
||||
ImageMipModule g_ImageMipModule;
|
||||
|
||||
|
||||
class ImageSpriteAPI
|
||||
{
|
||||
_QERPlugImageTable m_imagesprite;
|
||||
public:
|
||||
typedef _QERPlugImageTable Type;
|
||||
STRING_CONSTANT(Name, "spr");
|
||||
|
||||
ImageSpriteAPI()
|
||||
{
|
||||
m_imagesprite.loadImage = LoadIDSP;
|
||||
}
|
||||
_QERPlugImageTable* getTable()
|
||||
{
|
||||
return &m_imagesprite;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<ImageSpriteAPI, ImageDependencies> ImageSpriteModule;
|
||||
|
||||
ImageSpriteModule g_ImageSpriteModule;
|
||||
|
||||
|
||||
|
||||
extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer& server)
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
|
||||
GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
|
||||
GlobalModuleServer::instance().set(server);
|
||||
|
||||
g_ImageHLWModule.selfRegister();
|
||||
g_ImageMipModule.selfRegister();
|
||||
g_ImageSpriteModule.selfRegister();
|
||||
}
|
||||
7
plugins/imagehl/imagehl.def
Normal file
7
plugins/imagehl/imagehl.def
Normal file
@@ -0,0 +1,7 @@
|
||||
; imagehl.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "ImageHL"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Radiant_RegisterModules @1
|
||||
174
plugins/imagehl/imagehl.dsp
Normal file
174
plugins/imagehl/imagehl.dsp
Normal file
@@ -0,0 +1,174 @@
|
||||
# Microsoft Developer Studio Project File - Name="imagehl" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=imagehl - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "imagehl.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "imagehl.mak" CFG="imagehl - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "imagehl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "imagehl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "imagehl"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "imagehl - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD F90 /compile_only /include:"Release/" /libs:dll /nologo /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 glib-2.0.lib /nologo /dll /machine:I386 /def:".\imagehl.def" /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Release\imagehl.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "imagehl - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
F90=df.exe
|
||||
# ADD BASE F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD F90 /check:bounds /compile_only /debug:full /include:"Debug/" /libs:dll /nologo /warn:argument_checking /warn:nofileopt /dll
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\include" /I "..\..\..\gtk2-win32\include\glib-2.0" /I "..\..\..\gtk2-win32\lib\glib-2.0\include" /I "..\common" /I "..\..\libs" /I "..\..\..\STLPort\stlport" /I "..\..\..\libxml2\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IMAGE_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 glib-2.0.lib /nologo /dll /debug /machine:I386 /def:".\imagehl.def" /pdbtype:sept /libpath:"..\..\..\gtk2-win32\lib\\"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Copy to dir...
|
||||
PostBuild_Cmds=copy Debug\imagehl.dll "../../install/modules"
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "imagehl - Win32 Release"
|
||||
# Name "imagehl - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;f90;for;f;fpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hlw.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imagehl.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imagehl.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mip.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sprite.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wal.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hlw.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imagehl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sprite.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wal.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;txt"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\imagehl.txt
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Conscript
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user