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:
16
radiant/.cvsignore
Normal file
16
radiant/.cvsignore
Normal file
@@ -0,0 +1,16 @@
|
||||
Debug
|
||||
Release
|
||||
radiant
|
||||
*.d
|
||||
*.o
|
||||
*.opt
|
||||
*.ncb
|
||||
*.BAK
|
||||
*.00*
|
||||
*.plg
|
||||
radiant
|
||||
q3map
|
||||
unnamed.map
|
||||
.snprj
|
||||
tools
|
||||
*.gcse
|
||||
1082
radiant/GtkRadiant.dsp
Normal file
1082
radiant/GtkRadiant.dsp
Normal file
File diff suppressed because it is too large
Load Diff
712
radiant/GtkRadiant.vcproj
Normal file
712
radiant/GtkRadiant.vcproj
Normal file
@@ -0,0 +1,712 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="GtkRadiant"
|
||||
ProjectGUID="{8E70385C-223A-4DD1-9B99-28FF2331A2B5}"
|
||||
RootNamespace="GtkRadiant"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="0">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../include;../libs;"../../STLPort-4.6/stlport";"../../libxml2-2.6/include";"../../gtk2-2.4/lib/glib-2.0/include";"../../gtk2-2.4/include/glib-2.0";"../../gtk2-2.4/lib/gtk-2.0/include";"../../gtk2-2.4/include/gtk-2.0";"../../gtk2-2.4/include/gtk-2.0/gdk";"../../gtk2-2.4/include/pango-1.0";"../../gtk2-2.4/include/atk-1.0";"../../gtk2-2.4/lib/gtkglext-1.0/include";"../../gtk2-2.4/include/gtkglext-1.0""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
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="msvcrtd.lib oldnames.lib winmm.lib kernel32.lib user32.lib gdi32.lib shfolder.lib wsock32.lib dbghelp.lib glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gdk_pixbuf-2.0.lib gtk-win32-2.0.lib pango-1.0.lib gtkglext-win32-1.0.lib gdkglext-win32-1.0.lib opengl32.lib libxml2.lib profile.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""../../gtk2-2.4/lib";"../../libxml2-2.6/win32/lib";"../libs/profile/debug/""
|
||||
IgnoreAllDefaultLibraries="TRUE"
|
||||
IgnoreDefaultLibraryNames="msvcprtd.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
StripPrivateSymbols="$(OutDir)/$(ProjectName)_stripped.pdb"
|
||||
GenerateMapFile="FALSE"
|
||||
SubSystem="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install"
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<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="1"
|
||||
CharacterSet="0"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OptimizeForWindowsApplication="TRUE"
|
||||
AdditionalIncludeDirectories="../include;../libs;"../../STLPort-4.6/stlport";"../../libxml2-2.6/include";"../../gtk2-2.4/lib/glib-2.0/include";"../../gtk2-2.4/include/glib-2.0";"../../gtk2-2.4/lib/gtk-2.0/include";"../../gtk2-2.4/include/gtk-2.0";"../../gtk2-2.4/include/gtk-2.0/gdk";"../../gtk2-2.4/include/pango-1.0";"../../gtk2-2.4/include/atk-1.0";"../../gtk2-2.4/lib/gtkglext-1.0/include";"../../gtk2-2.4/include/gtkglext-1.0""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
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="msvcrt.lib oldnames.lib winmm.lib kernel32.lib user32.lib gdi32.lib shfolder.lib wsock32.lib dbghelp.lib glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gdk_pixbuf-2.0.lib gtk-win32-2.0.lib pango-1.0.lib gtkglext-win32-1.0.lib gdkglext-win32-1.0.lib opengl32.lib libxml2.lib profile.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""../../gtk2-2.4/lib";"../../libxml2-2.6/win32/lib";"../libs/profile/release/""
|
||||
IgnoreAllDefaultLibraries="TRUE"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
StripPrivateSymbols="$(OutDir)/$(ProjectName)_stripped.pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="0"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy "$(TargetPath)" "$(SolutionDir)install"
|
||||
copy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)install"
|
||||
"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
Culture="1033"/>
|
||||
<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=".\autosave.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\autosave.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\brush.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\brush.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\brush_primit.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\brush_primit.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushmanip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushmanip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushmodule.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushmodule.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushnode.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushnode.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushtokens.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushtokens.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushxml.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\brushxml.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\build.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\build.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\camwindow.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\camwindow.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clippertool.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clippertool.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\commands.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\commands.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\console.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\console.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\csg.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\csg.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\dialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\dialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\eclass.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\eclass.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\eclass_def.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\eclass_def.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_doom3.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_doom3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_fgd.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_fgd.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_xml.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\eclass_xml.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\entityinspector.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\entityinspector.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entitylist.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entitylist.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\environment.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\environment.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\error.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\error.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\feedback.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\feedback.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\filetypes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\filetypes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\filters.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\filters.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\findtexturedialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\findtexturedialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\glwidget.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\glwidget.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\grid.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\grid.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\groupdialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\groupdialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\gtkdlgs.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\gtkdlgs.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\gtkmisc.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\gtkmisc.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\help.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\help.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\image.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\image.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\main.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\main.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\mainframe.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\mainframe.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\map.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\map.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mru.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mru.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\multimon.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\multimon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\nullmodel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\nullmodel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\parse.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\parse.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patch.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patch.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patchdialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patchdialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patchmanip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\patchmanip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\patchmodule.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\patchmodule.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\plugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\plugin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\pluginapi.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\pluginapi.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\pluginmanager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\pluginmanager.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pluginmenu.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pluginmenu.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugintoolbar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugintoolbar.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\points.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\points.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\preferencedictionary.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\preferencedictionary.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\preferences.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\preferences.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\qe3.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\qe3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\qgl.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\qgl.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\referencecache.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\referencecache.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\renderer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\renderer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\renderstate.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\renderstate.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\scenegraph.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\scenegraph.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\select.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\select.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\selection.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\selection.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\server.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\server.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\shaders.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\shaders.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stacktrace.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stacktrace.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\surfacedialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\surfacedialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\texmanip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\texmanip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\textureentry.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\textureentry.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\textures.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\textures.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\texwindow.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\texwindow.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\timer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\timer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\treemodel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\treemodel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\undo.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\undo.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\url.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\url.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\view.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\view.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\watchbsp.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\watchbsp.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\winding.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\winding.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\windowobservers.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\windowobservers.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\xmlstuff.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\xmlstuff.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\xywindow.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\xywindow.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\docs\developer\Changes">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\debug.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)debug.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetName).pdb""
|
||||
Outputs=""$(TargetDir)$(TargetName).pdb""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\radiant.ico">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\radiant.rc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\radiant\resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\SConscript">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\SConstruct">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\docs\developer\Todo">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\touch.py">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="python "$(SolutionDir)touch.py"
|
||||
"
|
||||
AdditionalDependencies=""$(SolutionDir)install\$(TargetFileName)""
|
||||
Outputs=""$(TargetPath)""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
224
radiant/autosave.cpp
Normal file
224
radiant/autosave.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
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 "autosave.h"
|
||||
|
||||
#include "os/file.h"
|
||||
#include "os/path.h"
|
||||
#include "cmdlib.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "gtkutil/messagebox.h"
|
||||
#include "scenelib.h"
|
||||
#include "mapfile.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "mainframe.h"
|
||||
#include "qe3.h"
|
||||
#include "preferences.h"
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
#define PATH_MAX 260
|
||||
#endif
|
||||
|
||||
|
||||
bool DoesFileExist(const char* name, std::size_t& size)
|
||||
{
|
||||
if(file_exists(name))
|
||||
{
|
||||
size += file_size(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Map_Snapshot()
|
||||
{
|
||||
// we need to do the following
|
||||
// 1. make sure the snapshot directory exists (create it if it doesn't)
|
||||
// 2. find out what the lastest save is based on number
|
||||
// 3. inc that and save the map
|
||||
const char* path = Map_Name(g_map);
|
||||
const char* name = path_get_filename_start(path);
|
||||
|
||||
StringOutputStream snapshotsDir(256);
|
||||
snapshotsDir << StringRange(path, name) << "snapshots";
|
||||
|
||||
if(file_exists(snapshotsDir.c_str()) || Q_mkdir(snapshotsDir.c_str()))
|
||||
{
|
||||
std::size_t lSize = 0;
|
||||
StringOutputStream strNewPath(256);
|
||||
strNewPath << snapshotsDir.c_str() << '/' << name;
|
||||
|
||||
StringOutputStream snapshotFilename(256);
|
||||
|
||||
for(int nCount = 0; ; ++nCount)
|
||||
{
|
||||
// The original map's filename is "<path>/<name>.<ext>"
|
||||
// The snapshot's filename will be "<path>/snapshots/<name>.<count>.<ext>"
|
||||
const char* end = path_get_filename_base_end(strNewPath.c_str());
|
||||
snapshotFilename << StringRange(strNewPath.c_str(), end) << '.' << nCount << end;
|
||||
|
||||
if(!DoesFileExist(snapshotFilename.c_str(), lSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
snapshotFilename.clear();
|
||||
}
|
||||
|
||||
// save in the next available slot
|
||||
Map_SaveFile(snapshotFilename.c_str());
|
||||
|
||||
if (lSize > 50 * 1024 * 1024) // total size of saves > 50 mb
|
||||
{
|
||||
globalOutputStream() << "The snapshot files in " << snapshotsDir.c_str() << " total more than 50 megabytes. You might consider cleaning up.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StringOutputStream strMsg(256);
|
||||
strMsg << "Snapshot save failed.. unabled to create directory\n" << snapshotsDir.c_str();
|
||||
gtk_MessageBox(GTK_WIDGET(MainFrame_getWindow()), strMsg.c_str());
|
||||
}
|
||||
}
|
||||
/*
|
||||
===============
|
||||
QE_CheckAutoSave
|
||||
|
||||
If five minutes have passed since making a change
|
||||
and the map hasn't been saved, save it out.
|
||||
===============
|
||||
*/
|
||||
|
||||
bool g_AutoSave_Enabled = true;
|
||||
int m_AutoSave_Frequency = 5;
|
||||
bool g_SnapShots_Enabled = false;
|
||||
|
||||
namespace
|
||||
{
|
||||
time_t s_start = 0;
|
||||
std::size_t s_changes = 0;
|
||||
}
|
||||
|
||||
void AutoSave_clear()
|
||||
{
|
||||
s_changes = 0;
|
||||
}
|
||||
|
||||
scene::Node& Map_Node()
|
||||
{
|
||||
return GlobalSceneGraph().root();
|
||||
}
|
||||
|
||||
void QE_CheckAutoSave( void )
|
||||
{
|
||||
if(!Map_Valid(g_map) || !ScreenUpdates_Enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
if(s_start == 0 || s_changes == Node_getMapFile(Map_Node())->changes())
|
||||
{
|
||||
s_start = now;
|
||||
}
|
||||
|
||||
if((now - s_start) > (60 * m_AutoSave_Frequency))
|
||||
{
|
||||
s_start = now;
|
||||
s_changes = Node_getMapFile(Map_Node())->changes();
|
||||
|
||||
if (g_AutoSave_Enabled)
|
||||
{
|
||||
const char* strMsg = g_SnapShots_Enabled ? "Autosaving snapshot..." : "Autosaving...";
|
||||
globalOutputStream() << strMsg << "\n";
|
||||
//Sys_Status(strMsg);
|
||||
|
||||
// only snapshot if not working on a default map
|
||||
if (g_SnapShots_Enabled && !Map_Unnamed(g_map))
|
||||
{
|
||||
Map_Snapshot();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Map_Unnamed(g_map))
|
||||
{
|
||||
StringOutputStream autosave(256);
|
||||
autosave << g_qeglobals.m_userGamePath.c_str() << "maps/";
|
||||
Q_mkdir(autosave.c_str());
|
||||
autosave << "autosave.map";
|
||||
Map_SaveFile(autosave.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* name = Map_Name(g_map);
|
||||
const char* extension = path_get_filename_base_end(name);
|
||||
StringOutputStream autosave(256);
|
||||
autosave << StringRange(name, extension) << ".autosave" << extension;
|
||||
Map_SaveFile(autosave.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "Autosave skipped...\n";
|
||||
//Sys_Status ("Autosave skipped...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Autosave_constructPreferences(PreferencesPage& page)
|
||||
{
|
||||
GtkWidget* autosave_enabled = page.appendCheckBox("Autosave", "Enable Autosave", g_AutoSave_Enabled);
|
||||
GtkWidget* autosave_frequency = page.appendSpinner("Autosave Frequency (minutes)", m_AutoSave_Frequency, 1, 1, 60);
|
||||
Widget_connectToggleDependency(autosave_frequency, autosave_enabled);
|
||||
page.appendCheckBox("", "Save Snapshots", g_SnapShots_Enabled);
|
||||
}
|
||||
void Autosave_constructPage(PreferenceGroup& group)
|
||||
{
|
||||
PreferencesPage page(group.createPage("Autosave", "Autosave Preferences"));
|
||||
Autosave_constructPreferences(page);
|
||||
}
|
||||
void Autosave_registerPreferencesPage()
|
||||
{
|
||||
PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, Autosave_constructPage>());
|
||||
}
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void Autosave_Construct()
|
||||
{
|
||||
GlobalPreferenceSystem().registerPreference("Autosave", BoolImportStringCaller(g_AutoSave_Enabled), BoolExportStringCaller(g_AutoSave_Enabled));
|
||||
GlobalPreferenceSystem().registerPreference("AutosaveMinutes", IntImportStringCaller(m_AutoSave_Frequency), IntExportStringCaller(m_AutoSave_Frequency));
|
||||
GlobalPreferenceSystem().registerPreference("Snapshots", BoolImportStringCaller(g_SnapShots_Enabled), BoolExportStringCaller(g_SnapShots_Enabled));
|
||||
|
||||
Autosave_registerPreferencesPage();
|
||||
}
|
||||
|
||||
void Autosave_Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
35
radiant/autosave.h
Normal file
35
radiant/autosave.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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_AUTOSAVE_H)
|
||||
#define INCLUDED_AUTOSAVE_H
|
||||
|
||||
extern bool g_SnapShots_Enabled;
|
||||
|
||||
void AutoSave_clear();
|
||||
void QE_CheckAutoSave( void );
|
||||
void Map_Snapshot();
|
||||
|
||||
void Autosave_Construct();
|
||||
void Autosave_Destroy();
|
||||
|
||||
|
||||
#endif
|
||||
415
radiant/brush.cpp
Normal file
415
radiant/brush.cpp
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
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 "brush.h"
|
||||
|
||||
std::set<Callback> g_brushTextureChangedCallbacks;
|
||||
|
||||
void Brush_addTextureChangedCallback(const Callback& callback)
|
||||
{
|
||||
g_brushTextureChangedCallbacks.insert(callback);
|
||||
}
|
||||
|
||||
void Brush_textureChanged()
|
||||
{
|
||||
std::for_each(g_brushTextureChangedCallbacks.begin(), g_brushTextureChangedCallbacks.end(), CallbackInvoke());
|
||||
}
|
||||
|
||||
QuantiseFunc Face::m_quantise;
|
||||
EBrushType Face::m_type;
|
||||
EBrushType FacePlane::m_type;
|
||||
bool g_brush_texturelock_enabled = false;
|
||||
|
||||
EBrushType Brush::m_type;
|
||||
double Brush::m_maxWorldCoord = 0;
|
||||
Shader* Brush::m_state_point;
|
||||
Shader* BrushClipPlane::m_state = 0;
|
||||
Shader* BrushInstance::m_state_selpoint;
|
||||
Counter* BrushInstance::m_counter = 0;
|
||||
|
||||
FaceInstanceSet g_SelectedFaceInstances;
|
||||
|
||||
|
||||
struct SListNode
|
||||
{
|
||||
SListNode* m_next;
|
||||
};
|
||||
|
||||
class ProximalVertex
|
||||
{
|
||||
public:
|
||||
const SListNode* m_vertices;
|
||||
|
||||
ProximalVertex(const SListNode* next)
|
||||
: m_vertices(next)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const ProximalVertex& other) const
|
||||
{
|
||||
if(!(operator==(other)))
|
||||
{
|
||||
return m_vertices < other.m_vertices;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator==(const ProximalVertex& other) const
|
||||
{
|
||||
const SListNode* v = m_vertices;
|
||||
std::size_t DEBUG_LOOP = 0;
|
||||
do
|
||||
{
|
||||
if(v == other.m_vertices)
|
||||
return true;
|
||||
v = v->m_next;
|
||||
//ASSERT_MESSAGE(DEBUG_LOOP < c_brush_maxFaces, "infinite loop");
|
||||
if(!(DEBUG_LOOP < c_brush_maxFaces))
|
||||
{
|
||||
break;
|
||||
}
|
||||
++DEBUG_LOOP;
|
||||
}
|
||||
while(v != m_vertices);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Array<SListNode> ProximalVertexArray;
|
||||
std::size_t ProximalVertexArray_index(const ProximalVertexArray& array, const ProximalVertex& vertex)
|
||||
{
|
||||
return vertex.m_vertices - array.data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Brush_isBounded(const Brush& brush)
|
||||
{
|
||||
for(Brush::const_iterator i = brush.begin(); i != brush.end(); ++i)
|
||||
{
|
||||
if(!(*i)->is_bounded())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Brush::buildBRep()
|
||||
{
|
||||
bool degenerate = buildWindings();
|
||||
|
||||
std::size_t faces_size = 0;
|
||||
std::size_t faceVerticesCount = 0;
|
||||
for(Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes())
|
||||
{
|
||||
++faces_size;
|
||||
}
|
||||
faceVerticesCount += (*i)->getWinding().numpoints;
|
||||
}
|
||||
|
||||
if(degenerate || faces_size < 4 || faceVerticesCount != (faceVerticesCount>>1)<<1) // sum of vertices for each face of a valid polyhedron is always even
|
||||
{
|
||||
m_uniqueVertexPoints.resize(0);
|
||||
|
||||
vertex_clear();
|
||||
edge_clear();
|
||||
|
||||
m_edge_indices.resize(0);
|
||||
m_edge_faces.resize(0);
|
||||
|
||||
m_faceCentroidPoints.resize(0);
|
||||
m_uniqueEdgePoints.resize(0);
|
||||
m_uniqueVertexPoints.resize(0);
|
||||
|
||||
for(Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i)
|
||||
{
|
||||
(*i)->getWinding().resize(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
typedef std::vector<FaceVertexId> FaceVertices;
|
||||
FaceVertices faceVertices;
|
||||
faceVertices.reserve(faceVerticesCount);
|
||||
|
||||
{
|
||||
for(std::size_t i = 0; i != m_faces.size(); ++i)
|
||||
{
|
||||
for(std::size_t j = 0; j < m_faces[i]->getWinding().numpoints; ++j)
|
||||
{
|
||||
faceVertices.push_back(FaceVertexId(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IndexBuffer uniqueEdgeIndices;
|
||||
typedef VertexBuffer<ProximalVertex> UniqueEdges;
|
||||
UniqueEdges uniqueEdges;
|
||||
|
||||
uniqueEdgeIndices.reserve(faceVertices.size());
|
||||
uniqueEdges.reserve(faceVertices.size());
|
||||
|
||||
{
|
||||
ProximalVertexArray edgePairs;
|
||||
edgePairs.resize(faceVertices.size());
|
||||
|
||||
{
|
||||
for(std::size_t i=0; i<faceVertices.size(); ++i)
|
||||
{
|
||||
edgePairs[i].m_next = edgePairs.data() + absoluteIndex(next_edge(m_faces, faceVertices[i]));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UniqueVertexBuffer<ProximalVertex> inserter(uniqueEdges);
|
||||
for(ProximalVertexArray::iterator i = edgePairs.begin(); i != edgePairs.end(); ++i)
|
||||
{
|
||||
uniqueEdgeIndices.insert(inserter.insert(ProximalVertex(&(*i))));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
edge_clear();
|
||||
m_select_edges.reserve(uniqueEdges.size());
|
||||
for(UniqueEdges::iterator i = uniqueEdges.begin(); i != uniqueEdges.end(); ++i)
|
||||
{
|
||||
edge_push_back(faceVertices[ProximalVertexArray_index(edgePairs, *i)]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
m_edge_faces.resize(uniqueEdges.size());
|
||||
for(std::size_t i=0; i<uniqueEdges.size(); ++i)
|
||||
{
|
||||
FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
|
||||
m_edge_faces[i] = EdgeFaces(faceVertex.getFace(), m_faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
m_uniqueEdgePoints.resize(uniqueEdges.size());
|
||||
for(std::size_t i=0; i<uniqueEdges.size(); ++i)
|
||||
{
|
||||
FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(edgePairs, uniqueEdges[i])];
|
||||
|
||||
const Winding& w = m_faces[faceVertex.getFace()]->getWinding();
|
||||
Vector3 edge = vector3_mid(w[faceVertex.getVertex()].vertex, w[Winding_next(w, faceVertex.getVertex())].vertex);
|
||||
m_uniqueEdgePoints[i] = pointvertex_for_windingpoint(edge, colour_vertex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
IndexBuffer uniqueVertexIndices;
|
||||
typedef VertexBuffer<ProximalVertex> UniqueVertices;
|
||||
UniqueVertices uniqueVertices;
|
||||
|
||||
uniqueVertexIndices.reserve(faceVertices.size());
|
||||
uniqueVertices.reserve(faceVertices.size());
|
||||
|
||||
{
|
||||
ProximalVertexArray vertexRings;
|
||||
vertexRings.resize(faceVertices.size());
|
||||
|
||||
{
|
||||
for(std::size_t i=0; i<faceVertices.size(); ++i)
|
||||
{
|
||||
vertexRings[i].m_next = vertexRings.data() + absoluteIndex(next_vertex(m_faces, faceVertices[i]));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UniqueVertexBuffer<ProximalVertex> inserter(uniqueVertices);
|
||||
for(ProximalVertexArray::iterator i = vertexRings.begin(); i != vertexRings.end(); ++i)
|
||||
{
|
||||
uniqueVertexIndices.insert(inserter.insert(ProximalVertex(&(*i))));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
vertex_clear();
|
||||
m_select_vertices.reserve(uniqueVertices.size());
|
||||
for(UniqueVertices::iterator i = uniqueVertices.begin(); i != uniqueVertices.end(); ++i)
|
||||
{
|
||||
vertex_push_back(faceVertices[ProximalVertexArray_index(vertexRings, (*i))]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
m_uniqueVertexPoints.resize(uniqueVertices.size());
|
||||
for(std::size_t i=0; i<uniqueVertices.size(); ++i)
|
||||
{
|
||||
FaceVertexId faceVertex = faceVertices[ProximalVertexArray_index(vertexRings, uniqueVertices[i])];
|
||||
|
||||
const Winding& winding = m_faces[faceVertex.getFace()]->getWinding();
|
||||
m_uniqueVertexPoints[i] = pointvertex_for_windingpoint(winding[faceVertex.getVertex()].vertex, colour_vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_MESSAGE((uniqueVertices.size() + faces_size) - uniqueEdges.size() == 2, "Final B-Rep: inconsistent vertex count");
|
||||
|
||||
#if BRUSH_CONNECTIVITY_DEBUG
|
||||
if((uniqueVertices.size() + faces_size) - uniqueEdges.size() != 2)
|
||||
{
|
||||
for(Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i)
|
||||
{
|
||||
std::size_t faceIndex = std::distance(m_faces.begin(), i);
|
||||
|
||||
if(!(*i)->contributes())
|
||||
{
|
||||
globalOutputStream() << "face: " << Unsigned(faceIndex) << " does not contribute\n";
|
||||
}
|
||||
|
||||
Winding_printConnectivity((*i)->getWinding());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// edge-index list for wireframe rendering
|
||||
{
|
||||
m_edge_indices.resize(uniqueEdgeIndices.size());
|
||||
|
||||
for(std::size_t i=0, count=0; i<m_faces.size(); ++i)
|
||||
{
|
||||
const Winding& winding = m_faces[i]->getWinding();
|
||||
for(std::size_t j = 0; j < winding.numpoints; ++j)
|
||||
{
|
||||
const RenderIndex edge_index = uniqueEdgeIndices[count+j];
|
||||
|
||||
m_edge_indices[edge_index].first = uniqueVertexIndices[count + j];
|
||||
m_edge_indices[edge_index].second = uniqueVertexIndices[count + Winding_next(winding, j)];
|
||||
}
|
||||
count += winding.numpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
m_faceCentroidPoints.resize(m_faces.size());
|
||||
for(std::size_t i=0; i<m_faces.size(); ++i)
|
||||
{
|
||||
m_faces[i]->construct_centroid();
|
||||
m_faceCentroidPoints[i] = pointvertex_for_windingpoint(m_faces[i]->centroid(), colour_vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FaceFilterWrapper : public Filter
|
||||
{
|
||||
FaceFilter& m_filter;
|
||||
bool m_active;
|
||||
bool m_invert;
|
||||
public:
|
||||
FaceFilterWrapper(FaceFilter& filter, bool invert) :
|
||||
m_filter(filter),
|
||||
m_invert(invert)
|
||||
{
|
||||
}
|
||||
void setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
}
|
||||
bool active()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
bool filter(const Face& face)
|
||||
{
|
||||
return m_invert ^ m_filter.filter(face);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::list<FaceFilterWrapper> FaceFilters;
|
||||
FaceFilters g_faceFilters;
|
||||
|
||||
void add_face_filter(FaceFilter& filter, int mask, bool invert)
|
||||
{
|
||||
g_faceFilters.push_back(FaceFilterWrapper(filter, invert));
|
||||
GlobalFilterSystem().addFilter(g_faceFilters.back(), mask);
|
||||
}
|
||||
|
||||
bool face_filtered(Face& face)
|
||||
{
|
||||
for(FaceFilters::iterator i = g_faceFilters.begin(); i != g_faceFilters.end(); ++i)
|
||||
{
|
||||
if((*i).active() && (*i).filter(face))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class BrushFilterWrapper : public Filter
|
||||
{
|
||||
bool m_active;
|
||||
bool m_invert;
|
||||
BrushFilter& m_filter;
|
||||
public:
|
||||
BrushFilterWrapper(BrushFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
|
||||
{
|
||||
}
|
||||
void setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
}
|
||||
bool active()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
bool filter(const Brush& brush)
|
||||
{
|
||||
return m_invert ^ m_filter.filter(brush);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::list<BrushFilterWrapper> BrushFilters;
|
||||
BrushFilters g_brushFilters;
|
||||
|
||||
void add_brush_filter(BrushFilter& filter, int mask, bool invert)
|
||||
{
|
||||
g_brushFilters.push_back(BrushFilterWrapper(filter, invert));
|
||||
GlobalFilterSystem().addFilter(g_brushFilters.back(), mask);
|
||||
}
|
||||
|
||||
bool brush_filtered(Brush& brush)
|
||||
{
|
||||
for(BrushFilters::iterator i = g_brushFilters.begin(); i != g_brushFilters.end(); ++i)
|
||||
{
|
||||
if((*i).active() && (*i).filter(brush))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
4018
radiant/brush.h
Normal file
4018
radiant/brush.h
Normal file
File diff suppressed because it is too large
Load Diff
1600
radiant/brush_primit.cpp
Normal file
1600
radiant/brush_primit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
radiant/brush_primit.h
Normal file
137
radiant/brush_primit.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
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_BRUSH_PRIMIT_H)
|
||||
#define INCLUDED_BRUSH_PRIMIT_H
|
||||
|
||||
#include "math/vector.h"
|
||||
#include "itexdef.h"
|
||||
// Timo
|
||||
// new brush primitive texdef
|
||||
struct brushprimit_texdef_t
|
||||
{
|
||||
brushprimit_texdef_t()
|
||||
{
|
||||
coords[0][0] = 2.0f;
|
||||
coords[0][1] = 0.f;
|
||||
coords[0][2] = 0.f;
|
||||
coords[1][0] = 0.f;
|
||||
coords[1][1] = 2.0f;
|
||||
coords[1][2] = 0.f;
|
||||
}
|
||||
void removeScale(std::size_t width, std::size_t height)
|
||||
{
|
||||
#if 1
|
||||
coords[0][0] *= width;
|
||||
coords[0][1] *= width;
|
||||
coords[0][2] *= width;
|
||||
coords[1][0] *= height;
|
||||
coords[1][1] *= height;
|
||||
coords[1][2] *= height;
|
||||
#endif
|
||||
}
|
||||
void addScale(std::size_t width, std::size_t height)
|
||||
{
|
||||
#if 1
|
||||
coords[0][0] /= width;
|
||||
coords[0][1] /= width;
|
||||
coords[0][2] /= width;
|
||||
coords[1][0] /= height;
|
||||
coords[1][1] /= height;
|
||||
coords[1][2] /= height;
|
||||
#endif
|
||||
}
|
||||
float coords[2][3];
|
||||
};
|
||||
|
||||
class TextureProjection
|
||||
{
|
||||
public:
|
||||
texdef_t m_texdef;
|
||||
brushprimit_texdef_t m_brushprimit_texdef;
|
||||
Vector3 m_basis_s;
|
||||
Vector3 m_basis_t;
|
||||
|
||||
TextureProjection()
|
||||
{
|
||||
}
|
||||
TextureProjection(
|
||||
const texdef_t& texdef,
|
||||
const brushprimit_texdef_t& brushprimit_texdef,
|
||||
const Vector3& basis_s,
|
||||
const Vector3& basis_t
|
||||
) :
|
||||
m_texdef(texdef),
|
||||
m_brushprimit_texdef(brushprimit_texdef),
|
||||
m_basis_s(basis_s),
|
||||
m_basis_t(basis_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
float Texdef_getDefaultTextureScale();
|
||||
|
||||
class texdef_t;
|
||||
struct Winding;
|
||||
template<typename Element> class BasicVector3;
|
||||
typedef BasicVector3<float> Vector3;
|
||||
template<typename Element> class BasicVector4;
|
||||
typedef BasicVector4<float> Vector4;
|
||||
typedef Vector4 Quaternion;
|
||||
class Matrix4;
|
||||
class Plane3;
|
||||
|
||||
void Normal_GetTransform(const Vector3& normal, Matrix4& transform);
|
||||
|
||||
void TexDef_Construct_Default(TextureProjection& projection);
|
||||
|
||||
void Texdef_Assign(TextureProjection& projection, const TextureProjection& other);
|
||||
void Texdef_Shift(TextureProjection& projection, float s, float t);
|
||||
void Texdef_Scale(TextureProjection& projection, float s, float t);
|
||||
void Texdef_Rotate(TextureProjection& projection, float angle);
|
||||
void Texdef_FitTexture(TextureProjection& projection, std::size_t width, std::size_t height, const Vector3& normal, const Winding& w, float s_repeat, float t_repeat);
|
||||
void Texdef_EmitTextureCoordinates(const TextureProjection& projection, std::size_t width, std::size_t height, Winding& w, const Vector3& normal, const Matrix4& localToWorld);
|
||||
|
||||
void ShiftScaleRotate_fromFace(texdef_t& shiftScaleRotate, const TextureProjection& projection);
|
||||
void ShiftScaleRotate_toFace(const texdef_t& shiftScaleRotate, TextureProjection& projection);
|
||||
|
||||
void Texdef_transformLocked(TextureProjection& projection, std::size_t width, std::size_t height, const Plane3& plane, const Matrix4& transform);
|
||||
void Texdef_normalise(TextureProjection& projection, float width, float height);
|
||||
|
||||
enum TexdefTypeId
|
||||
{
|
||||
TEXDEFTYPEID_QUAKE,
|
||||
TEXDEFTYPEID_BRUSHPRIMITIVES,
|
||||
TEXDEFTYPEID_HALFLIFE,
|
||||
};
|
||||
|
||||
struct bp_globals_t
|
||||
{
|
||||
// tells if we are internally using brush primitive (texture coordinates and map format)
|
||||
// this is a shortcut for IntForKey( g_qeglobals.d_project_entity, "brush_primit" )
|
||||
// NOTE: must keep the two ones in sync
|
||||
TexdefTypeId m_texdefTypeId;
|
||||
};
|
||||
|
||||
extern bp_globals_t g_bp_globals;
|
||||
extern float g_texdef_default_scale;
|
||||
|
||||
#endif
|
||||
1756
radiant/brushmanip.cpp
Normal file
1756
radiant/brushmanip.cpp
Normal file
File diff suppressed because it is too large
Load Diff
84
radiant/brushmanip.h
Normal file
84
radiant/brushmanip.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
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_BRUSHWRAPPER_H)
|
||||
#define INCLUDED_BRUSHWRAPPER_H
|
||||
|
||||
#include "string/string.h"
|
||||
|
||||
enum EBrushPrefab
|
||||
{
|
||||
eBrushCuboid,
|
||||
eBrushPrism,
|
||||
eBrushCone,
|
||||
eBrushSphere,
|
||||
};
|
||||
|
||||
class TextureProjection;
|
||||
class ContentsFlagsValue;
|
||||
namespace scene
|
||||
{
|
||||
class Graph;
|
||||
}
|
||||
void Scene_BrushConstructPrefab(scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader);
|
||||
class AABB;
|
||||
void Scene_BrushResize_Selected(scene::Graph& graph, const AABB& bounds, const char* shader);
|
||||
void Scene_BrushSetTexdef_Selected(scene::Graph& graph, const TextureProjection& projection);
|
||||
void Scene_BrushSetTexdef_Component_Selected(scene::Graph& graph, const TextureProjection& projection);
|
||||
void Scene_BrushGetTexdef_Selected(scene::Graph& graph, TextureProjection& projection);
|
||||
void Scene_BrushGetTexdef_Component_Selected(scene::Graph& graph, TextureProjection& projection);
|
||||
void Scene_BrushSetFlags_Selected(scene::Graph& graph, const ContentsFlagsValue& flags);
|
||||
void Scene_BrushSetFlags_Component_Selected(scene::Graph& graph, const ContentsFlagsValue& flags);
|
||||
void Scene_BrushGetFlags_Selected(scene::Graph& graph, ContentsFlagsValue& flags);
|
||||
void Scene_BrushGetFlags_Component_Selected(scene::Graph& graph, ContentsFlagsValue& flags);
|
||||
void Scene_BrushShiftTexdef_Selected(scene::Graph& graph, float s, float t);
|
||||
void Scene_BrushShiftTexdef_Component_Selected(scene::Graph& graph, float s, float t);
|
||||
void Scene_BrushScaleTexdef_Selected(scene::Graph& graph, float s, float t);
|
||||
void Scene_BrushScaleTexdef_Component_Selected(scene::Graph& graph, float s, float t);
|
||||
void Scene_BrushRotateTexdef_Selected(scene::Graph& graph, float angle);
|
||||
void Scene_BrushRotateTexdef_Component_Selected(scene::Graph& graph, float angle);
|
||||
void Scene_BrushSetShader_Selected(scene::Graph& graph, const char* name);
|
||||
void Scene_BrushSetShader_Component_Selected(scene::Graph& graph, const char* name);
|
||||
void Scene_BrushGetShader_Selected(scene::Graph& graph, CopiedString& shader);
|
||||
void Scene_BrushGetShader_Component_Selected(scene::Graph& graph, CopiedString& shader);
|
||||
void Scene_BrushFindReplaceShader(scene::Graph& graph, const char* find, const char* replace);
|
||||
void Scene_BrushFindReplaceShader_Selected(scene::Graph& graph, const char* find, const char* replace);
|
||||
void Scene_BrushFindReplaceShader_Component_Selected(scene::Graph& graph, const char* find, const char* replace);
|
||||
void Scene_BrushSelectByShader(scene::Graph& graph, const char* name);
|
||||
void Scene_BrushSelectByShader_Component(scene::Graph& graph, const char* name);
|
||||
void Scene_BrushFitTexture_Selected(scene::Graph& graph, float s_repeat, float t_repeat);
|
||||
void Scene_BrushFitTexture_Component_Selected(scene::Graph& graph, float s_repeat, float t_repeat);
|
||||
|
||||
class Callback;
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Brush_constructMenu(GtkMenu* menu);
|
||||
|
||||
extern Callback g_texture_lock_status_changed;
|
||||
|
||||
void SelectedFaces_copyTexture();
|
||||
void SelectedFaces_pasteTexture();
|
||||
void FaceTextureClipboard_setDefault();
|
||||
|
||||
void BrushFilters_construct();
|
||||
void Brush_registerCommands();
|
||||
|
||||
#endif
|
||||
361
radiant/brushmodule.cpp
Normal file
361
radiant/brushmodule.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
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 "brushmodule.h"
|
||||
|
||||
#include "qerplugin.h"
|
||||
|
||||
#include "brushnode.h"
|
||||
#include "brushmanip.h"
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "qe3.h"
|
||||
#include "mainframe.h"
|
||||
#include "preferences.h"
|
||||
|
||||
LatchedBool g_useAlternativeTextureProjection(false, "Use alternative texture-projection");
|
||||
bool g_showAlternativeTextureProjectionOption = false;
|
||||
|
||||
bool getTextureLockEnabled()
|
||||
{
|
||||
return g_brush_texturelock_enabled;
|
||||
}
|
||||
|
||||
void Face_importSnapPlanes(bool value)
|
||||
{
|
||||
Face::m_quantise = value ? quantiseInteger : quantiseFloating;
|
||||
}
|
||||
typedef FreeCaller1<bool, Face_importSnapPlanes> FaceImportSnapPlanesCaller;
|
||||
|
||||
void Face_exportSnapPlanes(const BoolImportCallback& importer)
|
||||
{
|
||||
importer(Face::m_quantise == quantiseInteger);
|
||||
}
|
||||
typedef FreeCaller1<const BoolImportCallback&, Face_exportSnapPlanes> FaceExportSnapPlanesCaller;
|
||||
|
||||
void Brush_constructPreferences(PreferencesPage& page)
|
||||
{
|
||||
page.appendCheckBox(
|
||||
"", "Snap planes to integer grid",
|
||||
FaceImportSnapPlanesCaller(),
|
||||
FaceExportSnapPlanesCaller()
|
||||
);
|
||||
page.appendEntry(
|
||||
"Default texture scale",
|
||||
g_texdef_default_scale
|
||||
);
|
||||
if(g_showAlternativeTextureProjectionOption)
|
||||
{
|
||||
page.appendCheckBox(
|
||||
"", "Use alternative texture-projection",
|
||||
LatchedBoolImportCaller(g_useAlternativeTextureProjection),
|
||||
BoolExportCaller(g_useAlternativeTextureProjection.m_latched)
|
||||
);
|
||||
}
|
||||
}
|
||||
void Brush_constructPage(PreferenceGroup& group)
|
||||
{
|
||||
PreferencesPage page(group.createPage("Brush", "Brush Settings"));
|
||||
Brush_constructPreferences(page);
|
||||
}
|
||||
void Brush_registerPreferencesPage()
|
||||
{
|
||||
PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, Brush_constructPage>());
|
||||
}
|
||||
|
||||
|
||||
void Brush_Construct(EBrushType type)
|
||||
{
|
||||
if(type == eBrushTypeQuake3)
|
||||
{
|
||||
g_showAlternativeTextureProjectionOption = true;
|
||||
|
||||
GlobalPreferenceSystem().registerPreference(
|
||||
"AlternativeTextureProjection",
|
||||
BoolImportStringCaller(g_useAlternativeTextureProjection.m_latched),
|
||||
BoolExportStringCaller(g_useAlternativeTextureProjection.m_latched)
|
||||
);
|
||||
g_useAlternativeTextureProjection.useLatched();
|
||||
|
||||
if(g_useAlternativeTextureProjection.m_value)
|
||||
{
|
||||
type = eBrushTypeQuake3BP;
|
||||
}
|
||||
}
|
||||
|
||||
Brush_registerCommands();
|
||||
Brush_registerPreferencesPage();
|
||||
|
||||
BrushFilters_construct();
|
||||
|
||||
BrushClipPlane::constructStatic();
|
||||
BrushInstance::constructStatic();
|
||||
Brush::constructStatic(type);
|
||||
|
||||
Brush::m_maxWorldCoord = g_MaxWorldCoord;
|
||||
BrushInstance::m_counter = &g_brushCount;
|
||||
|
||||
g_texdef_default_scale = 0.5f;
|
||||
const char* value = g_pGameDescription->getKeyValue("default_scale");
|
||||
if(!string_empty(value))
|
||||
{
|
||||
float scale = static_cast<float>(atof(value));
|
||||
if(scale != 0)
|
||||
{
|
||||
g_texdef_default_scale = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
globalErrorStream() << "error parsing \"default_scale\" attribute\n";
|
||||
}
|
||||
}
|
||||
|
||||
FaceTextureClipboard_setDefault();
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("TextureLock", BoolImportStringCaller(g_brush_texturelock_enabled), BoolExportStringCaller(g_brush_texturelock_enabled));
|
||||
GlobalPreferenceSystem().registerPreference("BrushSnapPlanes", makeBoolStringImportCallback(FaceImportSnapPlanesCaller()), makeBoolStringExportCallback(FaceExportSnapPlanesCaller()));
|
||||
GlobalPreferenceSystem().registerPreference("TexdefDefaultScale", FloatImportStringCaller(g_texdef_default_scale), FloatExportStringCaller(g_texdef_default_scale));
|
||||
|
||||
GridStatus_getTextureLockEnabled = getTextureLockEnabled;
|
||||
g_texture_lock_status_changed = FreeCaller<GridStatus_onTextureLockEnabledChanged>();
|
||||
}
|
||||
|
||||
void Brush_Destroy()
|
||||
{
|
||||
Brush::m_maxWorldCoord = 0;
|
||||
BrushInstance::m_counter = 0;
|
||||
|
||||
Brush::destroyStatic();
|
||||
BrushInstance::destroyStatic();
|
||||
BrushClipPlane::destroyStatic();
|
||||
}
|
||||
|
||||
void Brush_clipperColourChanged()
|
||||
{
|
||||
BrushClipPlane::destroyStatic();
|
||||
BrushClipPlane::constructStatic();
|
||||
}
|
||||
|
||||
|
||||
class Quake3BrushCreator : public BrushCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createBrush()
|
||||
{
|
||||
return (new BrushNode)->node();
|
||||
}
|
||||
bool useAlternativeTextureProjection() const
|
||||
{
|
||||
return g_useAlternativeTextureProjection.m_value;
|
||||
}
|
||||
};
|
||||
|
||||
Quake3BrushCreator g_Quake3BrushCreator;
|
||||
|
||||
BrushCreator& GetBrushCreator()
|
||||
{
|
||||
return g_Quake3BrushCreator;
|
||||
}
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
|
||||
class BrushDependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalFilterModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class BrushDoom3API : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushdoom3;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "doom3");
|
||||
|
||||
BrushDoom3API()
|
||||
{
|
||||
Brush_Construct(eBrushTypeDoom3);
|
||||
|
||||
m_brushdoom3 = &GetBrushCreator();
|
||||
}
|
||||
~BrushDoom3API()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushdoom3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushDoom3API, BrushDependencies> BrushDoom3Module;
|
||||
typedef Static<BrushDoom3Module> StaticBrushDoom3Module;
|
||||
StaticRegisterModule staticRegisterBrushDoom3(StaticBrushDoom3Module::instance());
|
||||
|
||||
|
||||
class BrushQuake4API : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushquake4;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "quake4");
|
||||
|
||||
BrushQuake4API()
|
||||
{
|
||||
Brush_Construct(eBrushTypeQuake4);
|
||||
|
||||
m_brushquake4 = &GetBrushCreator();
|
||||
}
|
||||
~BrushQuake4API()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushquake4;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushQuake4API, BrushDependencies> BrushQuake4Module;
|
||||
typedef Static<BrushQuake4Module> StaticBrushQuake4Module;
|
||||
StaticRegisterModule staticRegisterBrushQuake4(StaticBrushQuake4Module::instance());
|
||||
|
||||
|
||||
class BrushQuake3API : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushquake3;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "quake3");
|
||||
|
||||
BrushQuake3API()
|
||||
{
|
||||
Brush_Construct(eBrushTypeQuake3);
|
||||
|
||||
m_brushquake3 = &GetBrushCreator();
|
||||
}
|
||||
~BrushQuake3API()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushquake3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushQuake3API, BrushDependencies> BrushQuake3Module;
|
||||
typedef Static<BrushQuake3Module> StaticBrushQuake3Module;
|
||||
StaticRegisterModule staticRegisterBrushQuake3(StaticBrushQuake3Module::instance());
|
||||
|
||||
|
||||
class BrushQuake2API : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushquake2;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "quake2");
|
||||
|
||||
BrushQuake2API()
|
||||
{
|
||||
Brush_Construct(eBrushTypeQuake2);
|
||||
|
||||
m_brushquake2 = &GetBrushCreator();
|
||||
}
|
||||
~BrushQuake2API()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushquake2;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushQuake2API, BrushDependencies> BrushQuake2Module;
|
||||
typedef Static<BrushQuake2Module> StaticBrushQuake2Module;
|
||||
StaticRegisterModule staticRegisterBrushQuake2(StaticBrushQuake2Module::instance());
|
||||
|
||||
|
||||
class BrushQuake1API : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushquake1;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "quake");
|
||||
|
||||
BrushQuake1API()
|
||||
{
|
||||
Brush_Construct(eBrushTypeQuake);
|
||||
|
||||
m_brushquake1 = &GetBrushCreator();
|
||||
}
|
||||
~BrushQuake1API()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushquake1;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushQuake1API, BrushDependencies> BrushQuake1Module;
|
||||
typedef Static<BrushQuake1Module> StaticBrushQuake1Module;
|
||||
StaticRegisterModule staticRegisterBrushQuake1(StaticBrushQuake1Module::instance());
|
||||
|
||||
|
||||
class BrushHalfLifeAPI : public TypeSystemRef
|
||||
{
|
||||
BrushCreator* m_brushhalflife;
|
||||
public:
|
||||
typedef BrushCreator Type;
|
||||
STRING_CONSTANT(Name, "halflife");
|
||||
|
||||
BrushHalfLifeAPI()
|
||||
{
|
||||
Brush_Construct(eBrushTypeHalfLife);
|
||||
|
||||
m_brushhalflife = &GetBrushCreator();
|
||||
}
|
||||
~BrushHalfLifeAPI()
|
||||
{
|
||||
Brush_Destroy();
|
||||
}
|
||||
BrushCreator* getTable()
|
||||
{
|
||||
return m_brushhalflife;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<BrushHalfLifeAPI, BrushDependencies> BrushHalfLifeModule;
|
||||
typedef Static<BrushHalfLifeModule> StaticBrushHalfLifeModule;
|
||||
StaticRegisterModule staticRegisterBrushHalfLife(StaticBrushHalfLifeModule::instance());
|
||||
27
radiant/brushmodule.h
Normal file
27
radiant/brushmodule.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_BRUSHMODULE_H)
|
||||
#define INCLUDED_BRUSHMODULE_H
|
||||
|
||||
void Brush_clipperColourChanged();
|
||||
|
||||
#endif
|
||||
23
radiant/brushnode.cpp
Normal file
23
radiant/brushnode.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 "brushnode.h"
|
||||
|
||||
167
radiant/brushnode.h
Normal file
167
radiant/brushnode.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
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_BRUSHNODE_H)
|
||||
#define INCLUDED_BRUSHNODE_H
|
||||
|
||||
#include "instancelib.h"
|
||||
#include "brush.h"
|
||||
#include "brushtokens.h"
|
||||
#include "brushxml.h"
|
||||
|
||||
class BrushNode :
|
||||
public scene::Node::Symbiot,
|
||||
public scene::Instantiable,
|
||||
public scene::Cloneable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<BrushNode, scene::Instantiable>::install(m_casts);
|
||||
NodeStaticCast<BrushNode, scene::Cloneable>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, Snappable>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, TransformNode>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, Brush>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, XMLImporter>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, XMLExporter>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, MapImporter>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, MapExporter>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, Nameable>::install(m_casts);
|
||||
NodeContainedCast<BrushNode, BrushDoom3>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
Brush m_brush;
|
||||
BrushTokenImporter m_mapImporter;
|
||||
BrushTokenExporter m_mapExporter;
|
||||
BrushXMLImporter m_xmlImporter;
|
||||
BrushXMLExporter m_xmlExporter;
|
||||
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Snappable& get(NullType<Snappable>)
|
||||
{
|
||||
return m_brush;
|
||||
}
|
||||
TransformNode& get(NullType<TransformNode>)
|
||||
{
|
||||
return m_brush;
|
||||
}
|
||||
Brush& get(NullType<Brush>)
|
||||
{
|
||||
return m_brush;
|
||||
}
|
||||
XMLImporter& get(NullType<XMLImporter>)
|
||||
{
|
||||
return m_xmlImporter;
|
||||
}
|
||||
XMLExporter& get(NullType<XMLExporter>)
|
||||
{
|
||||
return m_xmlExporter;
|
||||
}
|
||||
MapImporter& get(NullType<MapImporter>)
|
||||
{
|
||||
return m_mapImporter;
|
||||
}
|
||||
MapExporter& get(NullType<MapExporter>)
|
||||
{
|
||||
return m_mapExporter;
|
||||
}
|
||||
Nameable& get(NullType<Nameable>)
|
||||
{
|
||||
return m_brush;
|
||||
}
|
||||
BrushDoom3& get(NullType<BrushDoom3>)
|
||||
{
|
||||
return m_brush;
|
||||
}
|
||||
|
||||
BrushNode() :
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_brush(m_node, InstanceSetEvaluateTransform<BrushInstance>::Caller(m_instances), InstanceSet::BoundsChangedCaller(m_instances)),
|
||||
m_mapImporter(m_brush),
|
||||
m_mapExporter(m_brush),
|
||||
m_xmlImporter(m_brush),
|
||||
m_xmlExporter(m_brush)
|
||||
{
|
||||
}
|
||||
BrushNode(const BrushNode& other) :
|
||||
scene::Node::Symbiot(other),
|
||||
scene::Instantiable(other),
|
||||
scene::Cloneable(other),
|
||||
m_node(this, this, StaticTypeCasts::instance().get()),
|
||||
m_brush(other.m_brush, m_node, InstanceSetEvaluateTransform<BrushInstance>::Caller(m_instances), InstanceSet::BoundsChangedCaller(m_instances)),
|
||||
m_mapImporter(m_brush),
|
||||
m_mapExporter(m_brush),
|
||||
m_xmlImporter(m_brush),
|
||||
m_xmlExporter(m_brush)
|
||||
{
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Node& clone() const
|
||||
{
|
||||
return (new BrushNode(*this))->node();
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new BrushInstance(path, parent, m_brush);
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
inline Brush* Node_getBrush(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<Brush>::cast(node);
|
||||
}
|
||||
|
||||
#endif
|
||||
23
radiant/brushtokens.cpp
Normal file
23
radiant/brushtokens.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 "brushtokens.h"
|
||||
|
||||
738
radiant/brushtokens.h
Normal file
738
radiant/brushtokens.h
Normal file
@@ -0,0 +1,738 @@
|
||||
/*
|
||||
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_BRUSHTOKENS_H)
|
||||
#define INCLUDED_BRUSHTOKENS_H
|
||||
|
||||
#include "stringio.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "brush.h"
|
||||
|
||||
inline bool FaceShader_importContentsFlagsValue(FaceShader& faceShader, Tokeniser& tokeniser)
|
||||
{
|
||||
// parse the optional contents/flags/value
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, faceShader.m_flags.m_contentFlags));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, faceShader.m_flags.m_surfaceFlags));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, faceShader.m_flags.m_value));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FaceTexdef_importTokens(FaceTexdef& texdef, Tokeniser& tokeniser)
|
||||
{
|
||||
// parse texdef
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.shift[0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.shift[1]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.rotate));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.scale[0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.scale[1]));
|
||||
|
||||
ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importTokens: bad texdef");
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FaceTexdef_BP_importTokens(FaceTexdef& texdef, Tokeniser& tokeniser)
|
||||
{
|
||||
// parse alternate texdef
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "("));
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "("));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][1]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][2]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")"));
|
||||
}
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "("));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][1]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][2]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")"));
|
||||
}
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")"));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FaceTexdef_HalfLife_importTokens(FaceTexdef& texdef, Tokeniser& tokeniser)
|
||||
{
|
||||
// parse texdef
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "["));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_s.x()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_s.y()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_s.z()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.shift[0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "]"));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "["));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_t.x()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_t.y()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_basis_t.z()));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.shift[1]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "]"));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.rotate));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.scale[0]));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, texdef.m_projection.m_texdef.scale[1]));
|
||||
|
||||
texdef.m_projection.m_texdef.rotate = -texdef.m_projection.m_texdef.rotate;
|
||||
|
||||
ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importTokens: bad texdef");
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FacePlane_importTokens(FacePlane& facePlane, Tokeniser& tokeniser)
|
||||
{
|
||||
// parse planepts
|
||||
for(std::size_t i = 0; i<3; i++)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "("));
|
||||
for(std::size_t j = 0; j < 3; ++j)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getDouble(tokeniser, facePlane.planePoints()[i][j]));
|
||||
}
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")"));
|
||||
}
|
||||
facePlane.MakePlane();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FacePlane_Doom3_importTokens(FacePlane& facePlane, Tokeniser& tokeniser)
|
||||
{
|
||||
Plane3 plane;
|
||||
// parse plane equation
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "("));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getDouble(tokeniser, plane.a));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getDouble(tokeniser, plane.b));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getDouble(tokeniser, plane.c));
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_getDouble(tokeniser, plane.d));
|
||||
plane.d = -plane.d;
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")"));
|
||||
|
||||
facePlane.setDoom3Plane(plane);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FaceShader_Doom3_importTokens(FaceShader& faceShader, Tokeniser& tokeniser)
|
||||
{
|
||||
const char *shader = tokeniser.getToken();
|
||||
if(shader == 0)
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, shader, "#shader-name");
|
||||
return false;
|
||||
}
|
||||
if(string_equal(shader, "_emptyname"))
|
||||
{
|
||||
shader = texdef_name_default();
|
||||
}
|
||||
faceShader.setShader(shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FaceShader_importTokens(FaceShader& faceShader, Tokeniser& tokeniser)
|
||||
{
|
||||
const char* texture = tokeniser.getToken();
|
||||
if(texture == 0)
|
||||
{
|
||||
Tokeniser_unexpectedError(tokeniser, texture, "#texture-name");
|
||||
return false;
|
||||
}
|
||||
if(string_equal(texture, "NULL"))
|
||||
{
|
||||
faceShader.setShader(texdef_name_default());
|
||||
}
|
||||
else
|
||||
{
|
||||
StringOutputStream shader(string_length(GlobalTexturePrefix_get()) + string_length(texture));
|
||||
shader << GlobalTexturePrefix_get() << texture;
|
||||
faceShader.setShader(shader.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class Doom3FaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
Doom3FaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_Doom3_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_BP_importTokens(m_face.getTexdef(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_Doom3_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importContentsFlagsValue(m_face.getShader(), tokeniser));
|
||||
|
||||
m_face.getTexdef().m_projectionInitialised = true;
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Quake4FaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
Quake4FaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_Doom3_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_BP_importTokens(m_face.getTexdef(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_Doom3_importTokens(m_face.getShader(), tokeniser));
|
||||
|
||||
m_face.getTexdef().m_projectionInitialised = true;
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Quake2FaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
Quake2FaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_importTokens(m_face.getTexdef(), tokeniser));
|
||||
if(Tokeniser_nextTokenIsDigit(tokeniser))
|
||||
{
|
||||
m_face.getShader().m_flags.m_specified = true;
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importContentsFlagsValue(m_face.getShader(), tokeniser));
|
||||
}
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Quake3FaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
Quake3FaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_importTokens(m_face.getTexdef(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importContentsFlagsValue(m_face.getShader(), tokeniser));
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Quake3BPFaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
Quake3BPFaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_BP_importTokens(m_face.getTexdef(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importContentsFlagsValue(m_face.getShader(), tokeniser));
|
||||
|
||||
m_face.getTexdef().m_projectionInitialised = true;
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class QuakeFaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
QuakeFaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_importTokens(m_face.getTexdef(), tokeniser));
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class HalfLifeFaceTokenImporter
|
||||
{
|
||||
Face& m_face;
|
||||
public:
|
||||
HalfLifeFaceTokenImporter(Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
RETURN_FALSE_IF_FAIL(FacePlane_importTokens(m_face.getPlane(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceShader_importTokens(m_face.getShader(), tokeniser));
|
||||
RETURN_FALSE_IF_FAIL(FaceTexdef_HalfLife_importTokens(m_face.getTexdef(), tokeniser));
|
||||
m_face.getTexdef().m_scaleApplied = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void FacePlane_Doom3_exportTokens(const FacePlane& facePlane, TokenWriter& writer)
|
||||
{
|
||||
// write plane equation
|
||||
writer.writeToken("(");
|
||||
writer.writeFloat(facePlane.getDoom3Plane().a);
|
||||
writer.writeFloat(facePlane.getDoom3Plane().b);
|
||||
writer.writeFloat(facePlane.getDoom3Plane().c);
|
||||
writer.writeFloat(-facePlane.getDoom3Plane().d);
|
||||
writer.writeToken(")");
|
||||
}
|
||||
|
||||
inline void FacePlane_exportTokens(const FacePlane& facePlane, TokenWriter& writer)
|
||||
{
|
||||
// write planepts
|
||||
for(std::size_t i=0; i<3; i++)
|
||||
{
|
||||
writer.writeToken("(");
|
||||
for(std::size_t j=0; j<3; j++)
|
||||
{
|
||||
writer.writeFloat(Face::m_quantise(facePlane.planePoints()[i][j]));
|
||||
}
|
||||
writer.writeToken(")");
|
||||
}
|
||||
}
|
||||
|
||||
inline void FaceTexdef_BP_exportTokens(const FaceTexdef& faceTexdef, TokenWriter& writer)
|
||||
{
|
||||
// write alternate texdef
|
||||
writer.writeToken("(");
|
||||
{
|
||||
writer.writeToken("(");
|
||||
for(std::size_t i=0;i<3;i++)
|
||||
{
|
||||
writer.writeFloat(faceTexdef.m_projection.m_brushprimit_texdef.coords[0][i]);
|
||||
}
|
||||
writer.writeToken(")");
|
||||
}
|
||||
{
|
||||
writer.writeToken("(");
|
||||
for(std::size_t i=0;i<3;i++)
|
||||
{
|
||||
writer.writeFloat(faceTexdef.m_projection.m_brushprimit_texdef.coords[1][i]);
|
||||
}
|
||||
writer.writeToken(")");
|
||||
}
|
||||
writer.writeToken(")");
|
||||
}
|
||||
|
||||
inline void FaceTexdef_exportTokens(const FaceTexdef& faceTexdef, TokenWriter& writer)
|
||||
{
|
||||
ASSERT_MESSAGE(texdef_sane(faceTexdef.m_projection.m_texdef), "FaceTexdef_exportTokens: bad texdef");
|
||||
// write texdef
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.shift[0]);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.shift[1]);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.rotate);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.scale[0]);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.scale[1]);
|
||||
}
|
||||
|
||||
inline void FaceTexdef_HalfLife_exportTokens(const FaceTexdef& faceTexdef, TokenWriter& writer)
|
||||
{
|
||||
ASSERT_MESSAGE(texdef_sane(faceTexdef.m_projection.m_texdef), "FaceTexdef_exportTokens: bad texdef");
|
||||
// write texdef
|
||||
writer.writeToken("[");
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_s.x());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_s.y());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_s.z());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.shift[0]);
|
||||
writer.writeToken("]");
|
||||
writer.writeToken("[");
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_t.x());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_t.y());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_basis_t.z());
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.shift[1]);
|
||||
writer.writeToken("]");
|
||||
writer.writeFloat(-faceTexdef.m_projection.m_texdef.rotate);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.scale[0]);
|
||||
writer.writeFloat(faceTexdef.m_projection.m_texdef.scale[1]);
|
||||
}
|
||||
|
||||
inline void FaceShader_ContentsFlagsValue_exportTokens(const FaceShader& faceShader, TokenWriter& writer)
|
||||
{
|
||||
// write surface flags
|
||||
writer.writeInteger(faceShader.m_flags.m_contentFlags);
|
||||
writer.writeInteger(faceShader.m_flags.m_surfaceFlags);
|
||||
writer.writeInteger(faceShader.m_flags.m_value);
|
||||
}
|
||||
|
||||
inline void FaceShader_exportTokens(const FaceShader& faceShader, TokenWriter& writer)
|
||||
{
|
||||
// write shader name
|
||||
if(string_empty(shader_get_textureName(faceShader.getShader())))
|
||||
{
|
||||
writer.writeToken("NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.writeToken(shader_get_textureName(faceShader.getShader()));
|
||||
}
|
||||
}
|
||||
|
||||
inline void FaceShader_Doom3_exportTokens(const FaceShader& faceShader, TokenWriter& writer)
|
||||
{
|
||||
// write shader name
|
||||
if(string_empty(shader_get_textureName(faceShader.getShader())))
|
||||
{
|
||||
writer.writeString("_emptyname");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.writeString(faceShader.getShader());
|
||||
}
|
||||
}
|
||||
|
||||
class Doom3FaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
Doom3FaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_Doom3_exportTokens(m_face.getPlane(), writer);
|
||||
FaceTexdef_BP_exportTokens(m_face.getTexdef(), writer);
|
||||
FaceShader_Doom3_exportTokens(m_face.getShader(), writer);
|
||||
FaceShader_ContentsFlagsValue_exportTokens(m_face.getShader(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class Quake4FaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
Quake4FaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_Doom3_exportTokens(m_face.getPlane(), writer);
|
||||
FaceTexdef_BP_exportTokens(m_face.getTexdef(), writer);
|
||||
FaceShader_Doom3_exportTokens(m_face.getShader(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class Quake2FaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
Quake2FaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_exportTokens(m_face.getPlane(), writer);
|
||||
FaceShader_exportTokens(m_face.getShader(), writer);
|
||||
FaceTexdef_exportTokens(m_face.getTexdef(), writer);
|
||||
if(m_face.getShader().m_flags.m_specified || m_face.isDetail())
|
||||
{
|
||||
FaceShader_ContentsFlagsValue_exportTokens(m_face.getShader(), writer);
|
||||
}
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class Quake3FaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
Quake3FaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_exportTokens(m_face.getPlane(), writer);
|
||||
FaceShader_exportTokens(m_face.getShader(), writer);
|
||||
FaceTexdef_exportTokens(m_face.getTexdef(), writer);
|
||||
FaceShader_ContentsFlagsValue_exportTokens(m_face.getShader(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class Quake3BPFaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
Quake3BPFaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_exportTokens(m_face.getPlane(), writer);
|
||||
FaceTexdef_BP_exportTokens(m_face.getTexdef(), writer);
|
||||
FaceShader_exportTokens(m_face.getShader(), writer);
|
||||
FaceShader_ContentsFlagsValue_exportTokens(m_face.getShader(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class QuakeFaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
QuakeFaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_exportTokens(m_face.getPlane(), writer);
|
||||
FaceShader_exportTokens(m_face.getShader(), writer);
|
||||
FaceTexdef_exportTokens(m_face.getTexdef(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
class HalfLifeFaceTokenExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
HalfLifeFaceTokenExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
FacePlane_exportTokens(m_face.getPlane(), writer);
|
||||
FaceShader_exportTokens(m_face.getShader(), writer);
|
||||
FaceTexdef_HalfLife_exportTokens(m_face.getTexdef(), writer);
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BrushTokenImporter : public MapImporter
|
||||
{
|
||||
Brush& m_brush;
|
||||
|
||||
public:
|
||||
BrushTokenImporter(Brush& brush) : m_brush(brush)
|
||||
{
|
||||
}
|
||||
bool importTokens(Tokeniser& tokeniser)
|
||||
{
|
||||
if(Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4)
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{"));
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
// check for end of brush
|
||||
tokeniser.nextLine();
|
||||
const char* token = tokeniser.getToken();
|
||||
if(string_equal(token, "}"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tokeniser.ungetToken();
|
||||
|
||||
m_brush.push_back(FaceSmartPointer(new Face(&m_brush)));
|
||||
|
||||
//!todo BP support
|
||||
tokeniser.nextLine();
|
||||
|
||||
Face& face = *m_brush.back();
|
||||
|
||||
switch(Brush::m_type)
|
||||
{
|
||||
case eBrushTypeDoom3:
|
||||
{
|
||||
Doom3FaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake4:
|
||||
{
|
||||
Quake4FaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake2:
|
||||
{
|
||||
Quake2FaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake3:
|
||||
{
|
||||
Quake3FaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake3BP:
|
||||
{
|
||||
Quake3BPFaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake:
|
||||
{
|
||||
QuakeFaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
case eBrushTypeHalfLife:
|
||||
{
|
||||
HalfLifeFaceTokenImporter importer(face);
|
||||
RETURN_FALSE_IF_FAIL(importer.importTokens(tokeniser));
|
||||
}
|
||||
break;
|
||||
}
|
||||
face.planeChanged();
|
||||
}
|
||||
if(Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4)
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "}"));
|
||||
}
|
||||
|
||||
m_brush.planeChanged();
|
||||
m_brush.shaderChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BrushTokenExporter : public MapExporter
|
||||
{
|
||||
const Brush& m_brush;
|
||||
|
||||
public:
|
||||
BrushTokenExporter(const Brush& brush) : m_brush(brush)
|
||||
{
|
||||
}
|
||||
void exportTokens(TokenWriter& writer) const
|
||||
{
|
||||
m_brush.evaluateBRep(); // ensure b-rep is up-to-date, so that non-contributing faces can be identified.
|
||||
|
||||
if(!m_brush.hasContributingFaces())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
writer.writeToken("{");
|
||||
writer.nextLine();
|
||||
|
||||
if(Brush::m_type == eBrushTypeQuake3BP)
|
||||
{
|
||||
writer.writeToken("brushDef");
|
||||
writer.nextLine();
|
||||
writer.writeToken("{");
|
||||
writer.nextLine();
|
||||
}
|
||||
|
||||
if(Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4)
|
||||
{
|
||||
writer.writeToken("brushDef3");
|
||||
writer.nextLine();
|
||||
writer.writeToken("{");
|
||||
writer.nextLine();
|
||||
}
|
||||
|
||||
for(Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i)
|
||||
{
|
||||
const Face& face = *(*i);
|
||||
|
||||
if(face.contributes())
|
||||
{
|
||||
switch(Brush::m_type)
|
||||
{
|
||||
case eBrushTypeDoom3:
|
||||
{
|
||||
Doom3FaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake4:
|
||||
{
|
||||
Quake4FaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake2:
|
||||
{
|
||||
Quake2FaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake3:
|
||||
{
|
||||
Quake3FaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake3BP:
|
||||
{
|
||||
Quake3BPFaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeQuake:
|
||||
{
|
||||
QuakeFaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
case eBrushTypeHalfLife:
|
||||
{
|
||||
HalfLifeFaceTokenExporter exporter(face);
|
||||
exporter.exportTokens(writer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4)
|
||||
{
|
||||
writer.writeToken("}");
|
||||
writer.nextLine();
|
||||
}
|
||||
|
||||
writer.writeToken("}");
|
||||
writer.nextLine();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
23
radiant/brushxml.cpp
Normal file
23
radiant/brushxml.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 "brushxml.h"
|
||||
|
||||
413
radiant/brushxml.h
Normal file
413
radiant/brushxml.h
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
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_BRUSHXML_H)
|
||||
#define INCLUDED_BRUSHXML_H
|
||||
|
||||
#include "stream/stringstream.h"
|
||||
#include "xml/xmlelement.h"
|
||||
|
||||
#include "brush.h"
|
||||
|
||||
inline void FaceTexdef_BP_importXML(FaceTexdef& texdef, const char* xmlContent)
|
||||
{
|
||||
StringTokeniser content(xmlContent);
|
||||
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[0][0] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[0][1] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[0][2] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[1][0] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[1][1] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_brushprimit_texdef.coords[1][2] = static_cast<float>(atof(content.getToken()));
|
||||
}
|
||||
inline void FaceTexdef_importXML(FaceTexdef& texdef, const char* xmlContent)
|
||||
{
|
||||
StringTokeniser content(xmlContent);
|
||||
|
||||
texdef.m_projection.m_texdef.shift[0] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_texdef.shift[1] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_texdef.rotate = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_texdef.scale[0] = static_cast<float>(atof(content.getToken()));
|
||||
texdef.m_projection.m_texdef.scale[1] = static_cast<float>(atof(content.getToken()));
|
||||
|
||||
ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importXML: bad texdef");
|
||||
}
|
||||
|
||||
inline void FacePlane_importXML(FacePlane& facePlane, const char* xmlContent)
|
||||
{
|
||||
StringTokeniser content(xmlContent);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
facePlane.planePoints()[i][j] = atof(content.getToken());
|
||||
}
|
||||
}
|
||||
facePlane.MakePlane();
|
||||
}
|
||||
|
||||
|
||||
class FaceXMLImporter
|
||||
{
|
||||
struct xml_state_t
|
||||
{
|
||||
enum EState
|
||||
{
|
||||
eDefault,
|
||||
ePlanePts,
|
||||
eTexdef,
|
||||
eBPMatrix,
|
||||
eFlags,
|
||||
eShader,
|
||||
};
|
||||
|
||||
EState m_state;
|
||||
StringOutputStream m_content;
|
||||
|
||||
xml_state_t(EState state)
|
||||
: m_state(state)
|
||||
{}
|
||||
|
||||
EState state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
const char* content() const
|
||||
{
|
||||
return m_content.c_str();
|
||||
}
|
||||
std::size_t write(const char* buffer, std::size_t length)
|
||||
{
|
||||
return m_content.write(buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<xml_state_t> m_xml_state;
|
||||
Face& m_face;
|
||||
public:
|
||||
FaceXMLImporter(Face& face) : m_face(face)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eDefault);
|
||||
}
|
||||
~FaceXMLImporter()
|
||||
{
|
||||
m_face.planeChanged();
|
||||
}
|
||||
|
||||
void pushElement(const XMLElement& element)
|
||||
{
|
||||
ASSERT_MESSAGE(m_xml_state.back().state() == xml_state_t::eDefault, "parse error");
|
||||
|
||||
if(strcmp(element.name(), "planepts") == 0)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::ePlanePts);
|
||||
}
|
||||
else if(strcmp(element.name(), "texdef") == 0)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eTexdef);
|
||||
}
|
||||
else if(strcmp(element.name(), "bpmatrix") == 0)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eBPMatrix);
|
||||
}
|
||||
else if(strcmp(element.name(), "flags") == 0)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eFlags);
|
||||
}
|
||||
else if(strcmp(element.name(), "shader") == 0)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eShader);
|
||||
}
|
||||
}
|
||||
void popElement(const char* name)
|
||||
{
|
||||
ASSERT_MESSAGE(m_xml_state.back().state() != xml_state_t::eDefault, "parse error");
|
||||
|
||||
switch(m_xml_state.back().state())
|
||||
{
|
||||
case xml_state_t::ePlanePts:
|
||||
{
|
||||
FacePlane_importXML(m_face.getPlane(), m_xml_state.back().content());
|
||||
}
|
||||
break;
|
||||
case xml_state_t::eTexdef:
|
||||
{
|
||||
FaceTexdef_importXML(m_face.getTexdef(), m_xml_state.back().content());
|
||||
}
|
||||
break;
|
||||
case xml_state_t::eBPMatrix:
|
||||
{
|
||||
FaceTexdef_BP_importXML(m_face.getTexdef(), m_xml_state.back().content());
|
||||
}
|
||||
break;
|
||||
case xml_state_t::eFlags:
|
||||
{
|
||||
StringTokeniser content(m_xml_state.back().content());
|
||||
|
||||
m_face.getShader().m_flags.m_contentFlags = atoi(content.getToken());
|
||||
m_face.getShader().m_flags.m_surfaceFlags = atoi(content.getToken());
|
||||
m_face.getShader().m_flags.m_value = atoi(content.getToken());
|
||||
}
|
||||
break;
|
||||
case xml_state_t::eShader:
|
||||
{
|
||||
m_face.getShader().setShader(m_xml_state.back().content());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_xml_state.pop_back();
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
ASSERT_MESSAGE(!m_xml_state.empty(), "parse error");
|
||||
return m_xml_state.back().write(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void FaceTexdef_exportXML(const FaceTexdef& texdef, XMLImporter& importer)
|
||||
{
|
||||
StaticElement element("texdef");
|
||||
importer.pushElement(element);
|
||||
|
||||
ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_exportXML: bad texdef");
|
||||
|
||||
importer << texdef.m_projection.m_texdef.shift[0]
|
||||
<< ' ' << texdef.m_projection.m_texdef.shift[1]
|
||||
<< ' ' << texdef.m_projection.m_texdef.rotate
|
||||
<< ' ' << texdef.m_projection.m_texdef.scale[0]
|
||||
<< ' ' << texdef.m_projection.m_texdef.scale[1];
|
||||
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
inline void FaceTexdef_BP_exportXML(const FaceTexdef& texdef, XMLImporter& importer)
|
||||
{
|
||||
StaticElement element("texdef");
|
||||
importer.pushElement(element);
|
||||
|
||||
for(int i = 0; i < 2; ++i)
|
||||
{
|
||||
for(int j = 0; j < 3; ++j)
|
||||
{
|
||||
importer << texdef.m_projection.m_brushprimit_texdef.coords[i][j] << ' ';
|
||||
}
|
||||
}
|
||||
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
inline void FaceShader_ContentsFlagsValue_exportXML(const FaceShader& faceShader, XMLImporter& importer)
|
||||
{
|
||||
StaticElement element("flags");
|
||||
importer.pushElement(element);
|
||||
|
||||
{
|
||||
importer << faceShader.m_flags.m_contentFlags
|
||||
<< ' ' << faceShader.m_flags.m_surfaceFlags
|
||||
<< ' ' << faceShader.m_flags.m_value;
|
||||
}
|
||||
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
|
||||
inline void FacePlane_exportXML(const FacePlane& facePlane, XMLImporter& importer)
|
||||
{
|
||||
StaticElement element("planepts");
|
||||
importer.pushElement(element);
|
||||
|
||||
{
|
||||
// write planepts
|
||||
for (int i=0 ; i<3 ; i++)
|
||||
{
|
||||
for (int j=0 ; j<3 ; j++)
|
||||
{
|
||||
importer << Face::m_quantise(facePlane.planePoints()[i][j]) << ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
|
||||
class FaceXMLExporter
|
||||
{
|
||||
const Face& m_face;
|
||||
public:
|
||||
FaceXMLExporter(const Face& face) : m_face(face)
|
||||
{
|
||||
}
|
||||
void exportXML(XMLImporter& importer)
|
||||
{
|
||||
bool bAlternateTexdef = (Face::m_type == eBrushTypeQuake3BP || Face::m_type == eBrushTypeDoom3 || Face::m_type == eBrushTypeQuake4);
|
||||
|
||||
// write shader
|
||||
{
|
||||
StaticElement element("shader");
|
||||
importer.pushElement(element);
|
||||
importer << m_face.getShader().getShader();
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
|
||||
FacePlane_exportXML(m_face.getPlane(), importer);
|
||||
|
||||
if(!bAlternateTexdef)
|
||||
{
|
||||
FaceTexdef_exportXML(m_face.getTexdef(), importer);
|
||||
}
|
||||
else
|
||||
{
|
||||
FaceTexdef_BP_exportXML(m_face.getTexdef(), importer);
|
||||
}
|
||||
|
||||
FaceShader_ContentsFlagsValue_exportXML(m_face.getShader(), importer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BrushXMLImporter : public XMLImporter
|
||||
{
|
||||
class xml_state_t
|
||||
{
|
||||
public:
|
||||
enum EState
|
||||
{
|
||||
eDefault,
|
||||
eBrush,
|
||||
eFace,
|
||||
};
|
||||
|
||||
private:
|
||||
EState m_state;
|
||||
|
||||
public:
|
||||
xml_state_t(EState state)
|
||||
: m_state(state)
|
||||
{
|
||||
}
|
||||
EState state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<xml_state_t> m_xml_state;
|
||||
char m_faceImporter[sizeof(FaceXMLImporter)];
|
||||
Brush& m_brush;
|
||||
|
||||
FaceXMLImporter& faceImporter()
|
||||
{
|
||||
return *reinterpret_cast<FaceXMLImporter*>(m_faceImporter);
|
||||
}
|
||||
|
||||
public:
|
||||
BrushXMLImporter(Brush& brush) : m_brush(brush)
|
||||
{
|
||||
m_xml_state.push_back(xml_state_t::eDefault);
|
||||
}
|
||||
void pushElement(const XMLElement& element)
|
||||
{
|
||||
switch(m_xml_state.back().state())
|
||||
{
|
||||
case xml_state_t::eDefault:
|
||||
ASSERT_MESSAGE(strcmp(element.name(), "brush") == 0, "parse error");
|
||||
m_xml_state.push_back(xml_state_t::eBrush);
|
||||
break;
|
||||
case xml_state_t::eBrush:
|
||||
ASSERT_MESSAGE(strcmp(element.name(), "plane") == 0, "parse error");
|
||||
m_xml_state.push_back(xml_state_t::eFace);
|
||||
m_brush.push_back(FaceSmartPointer(new Face(&m_brush)));
|
||||
constructor(faceImporter(), makeReference(*m_brush.back()));
|
||||
m_brush.planeChanged();
|
||||
m_brush.shaderChanged();
|
||||
break;
|
||||
case xml_state_t::eFace:
|
||||
m_xml_state.push_back(xml_state_t::eFace);
|
||||
faceImporter().pushElement(element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void popElement(const char* name)
|
||||
{
|
||||
ASSERT_MESSAGE(!m_xml_state.empty(), "parse error");
|
||||
m_xml_state.pop_back();
|
||||
|
||||
switch(m_xml_state.back().state())
|
||||
{
|
||||
case xml_state_t::eDefault:
|
||||
break;
|
||||
case xml_state_t::eBrush:
|
||||
destructor(faceImporter());
|
||||
break;
|
||||
case xml_state_t::eFace:
|
||||
faceImporter().popElement(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
switch(m_xml_state.back().state())
|
||||
{
|
||||
case xml_state_t::eFace:
|
||||
return faceImporter().write(data, length);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
class BrushXMLExporter : public XMLExporter
|
||||
{
|
||||
const Brush& m_brush;
|
||||
|
||||
public:
|
||||
BrushXMLExporter(const Brush& brush) : m_brush(brush)
|
||||
{
|
||||
}
|
||||
void exportXML(XMLImporter& importer)
|
||||
{
|
||||
m_brush.evaluateBRep(); // ensure b-rep is up-to-date, so that non-contributing faces can be identified.
|
||||
ASSERT_MESSAGE(m_brush.hasContributingFaces(), "exporting an empty brush");
|
||||
|
||||
const StaticElement brushElement("brush");
|
||||
importer.pushElement(brushElement);
|
||||
|
||||
for(Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes())
|
||||
{
|
||||
const StaticElement element("plane");
|
||||
importer.pushElement(element);
|
||||
FaceXMLExporter(*(*i)).exportXML(importer);
|
||||
importer.popElement(element.name());
|
||||
}
|
||||
}
|
||||
|
||||
importer.popElement(brushElement.name());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1158
radiant/build.cpp
Normal file
1158
radiant/build.cpp
Normal file
File diff suppressed because it is too large
Load Diff
44
radiant/build.h
Normal file
44
radiant/build.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
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_BUILD_H)
|
||||
#define INCLUDED_BUILD_H
|
||||
|
||||
void build_set_variable(const char* name, const char* value);
|
||||
void build_clear_variables();
|
||||
|
||||
class CommandListener
|
||||
{
|
||||
public:
|
||||
virtual void execute(const char* command) = 0;
|
||||
};
|
||||
void build_run(const char* name, CommandListener& listener);
|
||||
|
||||
void DoBuildMenu();
|
||||
|
||||
void BuildMenu_Construct();
|
||||
void BuildMenu_Destroy();
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Build_constructMenu(GtkMenu* menu);
|
||||
extern GtkMenu* g_bsp_menu;
|
||||
|
||||
|
||||
#endif
|
||||
1982
radiant/camwindow.cpp
Normal file
1982
radiant/camwindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
87
radiant/camwindow.h
Normal file
87
radiant/camwindow.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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_CAMWINDOW_H)
|
||||
#define INCLUDED_CAMWINDOW_H
|
||||
|
||||
#include "math/vector.h"
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
|
||||
class CamWnd;
|
||||
CamWnd* NewCamWnd();
|
||||
void DeleteCamWnd(CamWnd* camwnd);
|
||||
|
||||
class Callback;
|
||||
void AddCameraMovedCallback(const Callback& callback);
|
||||
|
||||
void CamWnd_Update(CamWnd& camwnd);
|
||||
|
||||
GtkWidget* CamWnd_getWidget(CamWnd& camwnd);
|
||||
void CamWnd_setParent(CamWnd& camwnd, GtkWindow* parent);
|
||||
|
||||
void GlobalCamera_setCamWnd(CamWnd& camwnd);
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void fill_view_camera_menu(GtkMenu* menu);
|
||||
typedef struct _GtkToolbar GtkToolbar;
|
||||
void CamWnd_constructToolbar(GtkToolbar* toolbar);
|
||||
void CamWnd_registerShortcuts();
|
||||
|
||||
void GlobalCamera_Benchmark();
|
||||
|
||||
const Vector3& Camera_getOrigin(CamWnd& camwnd);
|
||||
void Camera_setOrigin(CamWnd& camwnd, const Vector3& origin);
|
||||
|
||||
enum
|
||||
{
|
||||
CAMERA_PITCH = 0, // up / down
|
||||
CAMERA_YAW = 1, // left / right
|
||||
CAMERA_ROLL = 2, // fall over
|
||||
};
|
||||
|
||||
const Vector3& Camera_getAngles(CamWnd& camwnd);
|
||||
void Camera_setAngles(CamWnd& camwnd, const Vector3& angles);
|
||||
|
||||
|
||||
struct camwindow_globals_t
|
||||
{
|
||||
Vector3 color_cameraback;
|
||||
Vector3 color_selbrushes3d;
|
||||
|
||||
int m_nCubicScale;
|
||||
|
||||
camwindow_globals_t() :
|
||||
color_cameraback(0.25f, 0.25f, 0.25f),
|
||||
color_selbrushes3d(1.0f, 0.f, 0.f),
|
||||
m_nCubicScale(13)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern camwindow_globals_t g_camwindow_globals;
|
||||
|
||||
void CamWnd_Construct();
|
||||
void CamWnd_Destroy();
|
||||
|
||||
#endif
|
||||
23
radiant/clippertool.cpp
Normal file
23
radiant/clippertool.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 "clippertool.h"
|
||||
|
||||
25
radiant/clippertool.h
Normal file
25
radiant/clippertool.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_CLIPPERTOOL_H)
|
||||
#define INCLUDED_CLIPPERTOOL_H
|
||||
|
||||
#endif
|
||||
546
radiant/commands.cpp
Normal file
546
radiant/commands.cpp
Normal file
@@ -0,0 +1,546 @@
|
||||
/*
|
||||
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 "commands.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "warnings.h"
|
||||
|
||||
#include <map>
|
||||
#include "string/string.h"
|
||||
#include "versionlib.h"
|
||||
|
||||
typedef std::pair<Accelerator, bool> ShortcutValue; // accelerator, isRegistered
|
||||
typedef std::map<CopiedString, ShortcutValue> Shortcuts;
|
||||
|
||||
void Shortcuts_foreach(Shortcuts& shortcuts, CommandVisitor& visitor)
|
||||
{
|
||||
for(Shortcuts::iterator i = shortcuts.begin(); i != shortcuts.end(); ++i)
|
||||
{
|
||||
visitor.visit((*i).first.c_str(), (*i).second.first);
|
||||
}
|
||||
}
|
||||
|
||||
Shortcuts g_shortcuts;
|
||||
|
||||
const Accelerator& GlobalShortcuts_insert(const char* name, const Accelerator& accelerator)
|
||||
{
|
||||
return (*g_shortcuts.insert(Shortcuts::value_type(name, ShortcutValue(accelerator, false))).first).second.first;
|
||||
}
|
||||
|
||||
void GlobalShortcuts_foreach(CommandVisitor& visitor)
|
||||
{
|
||||
Shortcuts_foreach(g_shortcuts, visitor);
|
||||
}
|
||||
|
||||
void GlobalShortcuts_register(const char* name)
|
||||
{
|
||||
Shortcuts::iterator i = g_shortcuts.find(name);
|
||||
if(i != g_shortcuts.end())
|
||||
{
|
||||
(*i).second.second = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalShortcuts_reportUnregistered()
|
||||
{
|
||||
for(Shortcuts::iterator i = g_shortcuts.begin(); i != g_shortcuts.end(); ++i)
|
||||
{
|
||||
if((*i).second.first.key != 0 && !(*i).second.second)
|
||||
{
|
||||
globalOutputStream() << "shortcut not registered: " << (*i).first.c_str() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<CopiedString, Command> Commands;
|
||||
|
||||
Commands g_commands;
|
||||
|
||||
void GlobalCommands_insert(const char* name, const Callback& callback, const Accelerator& accelerator)
|
||||
{
|
||||
bool added = g_commands.insert(Commands::value_type(name, Command(callback, GlobalShortcuts_insert(name, accelerator)))).second;
|
||||
ASSERT_MESSAGE(added, "command already registered: " << makeQuoted(name));
|
||||
}
|
||||
|
||||
const Command& GlobalCommands_find(const char* command)
|
||||
{
|
||||
Commands::iterator i = g_commands.find(command);
|
||||
ASSERT_MESSAGE(i != g_commands.end(), "failed to lookup command " << makeQuoted(command));
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
typedef std::map<CopiedString, Toggle> Toggles;
|
||||
|
||||
|
||||
Toggles g_toggles;
|
||||
|
||||
void GlobalToggles_insert(const char* name, const Callback& callback, const BoolExportCallback& exportCallback, const Accelerator& accelerator)
|
||||
{
|
||||
bool added = g_toggles.insert(Toggles::value_type(name, Toggle(callback, GlobalShortcuts_insert(name, accelerator), exportCallback))).second;
|
||||
ASSERT_MESSAGE(added, "toggle already registered: " << makeQuoted(name));
|
||||
}
|
||||
const Toggle& GlobalToggles_find(const char* name)
|
||||
{
|
||||
Toggles::iterator i = g_toggles.find(name);
|
||||
ASSERT_MESSAGE(i != g_toggles.end(), "failed to lookup toggle " << makeQuoted(name));
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
typedef std::map<CopiedString, KeyEvent> KeyEvents;
|
||||
|
||||
|
||||
KeyEvents g_keyEvents;
|
||||
|
||||
void GlobalKeyEvents_insert(const char* name, const Accelerator& accelerator, const Callback& keyDown, const Callback& keyUp)
|
||||
{
|
||||
bool added = g_keyEvents.insert(KeyEvents::value_type(name, KeyEvent(GlobalShortcuts_insert(name, accelerator), keyDown, keyUp))).second;
|
||||
ASSERT_MESSAGE(added, "command already registered: " << makeQuoted(name));
|
||||
}
|
||||
const KeyEvent& GlobalKeyEvents_find(const char* name)
|
||||
{
|
||||
KeyEvents::iterator i = g_keyEvents.find(name);
|
||||
ASSERT_MESSAGE(i != g_keyEvents.end(), "failed to lookup keyEvent " << makeQuoted(name));
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define __toascii(c) ((c) & 0x7f)
|
||||
#endif
|
||||
|
||||
inline char ascii_for_keyval(int keyval)
|
||||
{
|
||||
return __toascii(keyval);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct SKeyInfo
|
||||
{
|
||||
const char* m_strName;
|
||||
unsigned int m_nVKKey;
|
||||
};
|
||||
|
||||
SKeyInfo g_Keys[] =
|
||||
{
|
||||
{"Space", GDK_space},
|
||||
{"Backspace", GDK_BackSpace},
|
||||
{"Escape", GDK_Escape},
|
||||
{"End", GDK_End},
|
||||
{"Insert", GDK_Insert},
|
||||
{"Delete", GDK_Delete},
|
||||
{"PageUp", GDK_Prior},
|
||||
{"PageDown", GDK_Next},
|
||||
{"Up", GDK_Up},
|
||||
{"Down", GDK_Down},
|
||||
{"Left", GDK_Left},
|
||||
{"Right", GDK_Right},
|
||||
{"F1", GDK_F1},
|
||||
{"F2", GDK_F2},
|
||||
{"F3", GDK_F3},
|
||||
{"F4", GDK_F4},
|
||||
{"F5", GDK_F5},
|
||||
{"F6", GDK_F6},
|
||||
{"F7", GDK_F7},
|
||||
{"F8", GDK_F8},
|
||||
{"F9", GDK_F9},
|
||||
{"F10", GDK_F10},
|
||||
{"F11", GDK_F11},
|
||||
{"F12", GDK_F12},
|
||||
{"Tab", GDK_Tab},
|
||||
{"Return", GDK_Return},
|
||||
{"Comma", GDK_comma},
|
||||
{"Period", GDK_period},
|
||||
{"Plus", GDK_KP_Add},
|
||||
{"Multiply", GDK_multiply},
|
||||
{"Minus", GDK_KP_Subtract},
|
||||
{"NumPad0", GDK_KP_0},
|
||||
{"NumPad1", GDK_KP_1},
|
||||
{"NumPad2", GDK_KP_2},
|
||||
{"NumPad3", GDK_KP_3},
|
||||
{"NumPad4", GDK_KP_4},
|
||||
{"NumPad5", GDK_KP_5},
|
||||
{"NumPad6", GDK_KP_6},
|
||||
{"NumPad7", GDK_KP_7},
|
||||
{"NumPad8", GDK_KP_8},
|
||||
{"NumPad9", GDK_KP_9},
|
||||
{"[", 219},
|
||||
{"]", 221},
|
||||
{"\\", 220},
|
||||
{"Home", GDK_Home}
|
||||
};
|
||||
|
||||
int g_nKeyCount = sizeof(g_Keys) / sizeof(SKeyInfo);
|
||||
|
||||
const char* global_keys_find(unsigned int key)
|
||||
{
|
||||
for(int i = 0; i < g_nKeyCount; ++i)
|
||||
{
|
||||
if(g_Keys[i].m_nVKKey == key)
|
||||
{
|
||||
return g_Keys[i].m_strName;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned int global_keys_find(const char* name)
|
||||
{
|
||||
for(int i = 0; i < g_nKeyCount; ++i)
|
||||
{
|
||||
if(string_equal_nocase(g_Keys[i].m_strName, name))
|
||||
{
|
||||
return g_Keys[i].m_nVKKey;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#include <gtk/gtkbox.h>
|
||||
#include <gtk/gtkliststore.h>
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
#include <gtk/gtkcellrenderertext.h>
|
||||
|
||||
#include "gtkutil/dialog.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
#include "stream/textfilestream.h"
|
||||
#include "stream/stringstream.h"
|
||||
|
||||
|
||||
struct command_list_dialog_t : public ModalDialog
|
||||
{
|
||||
command_list_dialog_t()
|
||||
: m_close_button(*this, eIDCANCEL)
|
||||
{
|
||||
}
|
||||
ModalDialogButton m_close_button;
|
||||
};
|
||||
|
||||
template<typename TextOutputStreamType>
|
||||
TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Accelerator& accelerator)
|
||||
{
|
||||
if(accelerator.modifiers & GDK_SHIFT_MASK)
|
||||
{
|
||||
ostream << "Shift + ";
|
||||
}
|
||||
if(accelerator.modifiers & GDK_MOD1_MASK)
|
||||
{
|
||||
ostream << "Alt + ";
|
||||
}
|
||||
if(accelerator.modifiers & GDK_CONTROL_MASK)
|
||||
{
|
||||
ostream << "Control + ";
|
||||
}
|
||||
|
||||
const char* keyName = global_keys_find(accelerator.key);
|
||||
if(!string_empty(keyName))
|
||||
{
|
||||
ostream << keyName;
|
||||
}
|
||||
else
|
||||
{
|
||||
ostream << static_cast<char>(accelerator.key);
|
||||
}
|
||||
|
||||
return ostream;
|
||||
}
|
||||
|
||||
void DoCommandListDlg()
|
||||
{
|
||||
command_list_dialog_t dialog;
|
||||
|
||||
GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Mapped Commands", dialog, -1, 400);
|
||||
|
||||
GtkAccelGroup* accel = gtk_accel_group_new();
|
||||
gtk_window_add_accel_group(window, accel);
|
||||
|
||||
GtkHBox* hbox = create_dialog_hbox(4, 4);
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
|
||||
|
||||
{
|
||||
GtkScrolledWindow* scr = create_scrolled_window(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(scr), TRUE, TRUE, 0);
|
||||
|
||||
{
|
||||
GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
|
||||
{
|
||||
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
|
||||
GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", 0, 0);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
|
||||
}
|
||||
|
||||
{
|
||||
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
|
||||
GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 1, 0);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
|
||||
}
|
||||
|
||||
gtk_widget_show(view);
|
||||
gtk_container_add(GTK_CONTAINER (scr), view);
|
||||
|
||||
{
|
||||
// Initialize dialog
|
||||
StringOutputStream path(256);
|
||||
path << SettingsPath_get() << "commandlist.txt";
|
||||
globalOutputStream() << "Writing the command list to " << path.c_str() << "\n";
|
||||
class BuildCommandList : public CommandVisitor
|
||||
{
|
||||
TextFileOutputStream m_commandList;
|
||||
GtkListStore* m_store;
|
||||
public:
|
||||
BuildCommandList(const char* filename, GtkListStore* store) : m_commandList(filename), m_store(store)
|
||||
{
|
||||
}
|
||||
void visit(const char* name, Accelerator& accelerator)
|
||||
{
|
||||
StringOutputStream modifiers;
|
||||
modifiers << accelerator;
|
||||
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_list_store_append(m_store, &iter);
|
||||
gtk_list_store_set(m_store, &iter, 0, name, 1, modifiers.c_str(), -1);
|
||||
}
|
||||
|
||||
if(!m_commandList.failed())
|
||||
{
|
||||
m_commandList << makeLeftJustified(name, 25) << " " << modifiers.c_str() << '\n';
|
||||
}
|
||||
}
|
||||
} visitor(path.c_str(), store);
|
||||
|
||||
GlobalShortcuts_foreach(visitor);
|
||||
}
|
||||
|
||||
g_object_unref(G_OBJECT(store));
|
||||
}
|
||||
}
|
||||
|
||||
GtkVBox* vbox = create_dialog_vbox(4);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("Close", dialog.m_close_button);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_grab_focus(GTK_WIDGET(button));
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
}
|
||||
|
||||
modal_dialog_show(window, dialog);
|
||||
gtk_widget_destroy(GTK_WIDGET(window));
|
||||
}
|
||||
|
||||
#include "profile/profile.h"
|
||||
|
||||
const char* const COMMANDS_VERSION = "1.0";
|
||||
|
||||
void SaveCommandMap(const char* path)
|
||||
{
|
||||
StringOutputStream strINI(256);
|
||||
strINI << path << "shortcuts.ini";
|
||||
|
||||
TextFileOutputStream file(strINI.c_str());
|
||||
if(!file.failed())
|
||||
{
|
||||
file << "[Version]\n";
|
||||
file << "number=" << COMMANDS_VERSION << "\n";
|
||||
file << "\n";
|
||||
file << "[Commands]\n";
|
||||
class WriteCommandMap : public CommandVisitor
|
||||
{
|
||||
TextFileOutputStream& m_file;
|
||||
public:
|
||||
WriteCommandMap(TextFileOutputStream& file) : m_file(file)
|
||||
{
|
||||
}
|
||||
void visit(const char* name, Accelerator& accelerator)
|
||||
{
|
||||
m_file << name << "=";
|
||||
|
||||
const char* key = global_keys_find(accelerator.key);
|
||||
if(!string_empty(key))
|
||||
{
|
||||
m_file << key;
|
||||
}
|
||||
else if(accelerator.key != 0)
|
||||
{
|
||||
m_file << ascii_for_keyval(accelerator.key);
|
||||
}
|
||||
|
||||
if(accelerator.modifiers & GDK_MOD1_MASK)
|
||||
{
|
||||
m_file << "+Alt";
|
||||
}
|
||||
if(accelerator.modifiers & GDK_CONTROL_MASK)
|
||||
{
|
||||
m_file << "+Ctrl";
|
||||
}
|
||||
if(accelerator.modifiers & GDK_SHIFT_MASK)
|
||||
{
|
||||
m_file << "+Shift";
|
||||
}
|
||||
|
||||
m_file << "\n";
|
||||
}
|
||||
} visitor(file);
|
||||
GlobalShortcuts_foreach(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
const char* stringrange_find(const char* first, const char* last, char c)
|
||||
{
|
||||
const char* p = strchr(first, '+');
|
||||
if(p == 0)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
class ReadCommandMap : public CommandVisitor
|
||||
{
|
||||
const char* m_filename;
|
||||
std::size_t m_count;
|
||||
public:
|
||||
ReadCommandMap(const char* filename) : m_filename(filename), m_count(0)
|
||||
{
|
||||
}
|
||||
void visit(const char* name, Accelerator& accelerator)
|
||||
{
|
||||
char value[1024];
|
||||
if (read_var(m_filename, "Commands", name, value ))
|
||||
{
|
||||
if(string_empty(value))
|
||||
{
|
||||
accelerator.key = 0;
|
||||
accelerator.modifiers = (GdkModifierType)0;
|
||||
return;
|
||||
}
|
||||
int modifiers = 0;
|
||||
const char* last = value + string_length(value);
|
||||
const char* keyEnd = stringrange_find(value, last, '+');
|
||||
for(const char* modifier = keyEnd; modifier != last;)
|
||||
{
|
||||
const char* next = stringrange_find(modifier + 1, last, '+');
|
||||
if(next - modifier == 4
|
||||
&& string_equal_nocase_n(modifier, "+alt", 4))
|
||||
{
|
||||
modifiers |= GDK_MOD1_MASK;
|
||||
}
|
||||
else if(next - modifier == 5
|
||||
&& string_equal_nocase_n(modifier, "+ctrl", 5) != 0)
|
||||
{
|
||||
modifiers |= GDK_CONTROL_MASK;
|
||||
}
|
||||
else if(next - modifier == 6
|
||||
&& string_equal_nocase_n(modifier, "+shift", 6) != 0)
|
||||
{
|
||||
modifiers |= GDK_SHIFT_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted(value) << ": unknown modifier " << makeQuoted(StringRange(modifier, next)) << "\n";
|
||||
}
|
||||
modifier = next;
|
||||
}
|
||||
accelerator.modifiers = (GdkModifierType)modifiers;
|
||||
|
||||
|
||||
// strBuff has been cleaned of it's modifiers .. switch between a regular key and a virtual one
|
||||
// based on length
|
||||
if(keyEnd - value == 1) // most often case.. deal with first
|
||||
{
|
||||
accelerator.key = std::toupper(value[0]);
|
||||
++m_count;
|
||||
}
|
||||
else // special key
|
||||
{
|
||||
CopiedString keyName(value, keyEnd);
|
||||
accelerator.key = global_keys_find(keyName.c_str());
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
++m_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted(value) << ": unknown key " << makeQuoted(keyName.c_str()) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::size_t count() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
};
|
||||
|
||||
void LoadCommandMap(const char* path)
|
||||
{
|
||||
StringOutputStream strINI(256);
|
||||
strINI << path << "shortcuts.ini";
|
||||
|
||||
FILE* f = fopen (strINI.c_str(), "r");
|
||||
if (f != 0)
|
||||
{
|
||||
fclose(f);
|
||||
globalOutputStream() << "loading custom shortcuts list from " << makeQuoted(strINI.c_str()) << "\n";
|
||||
|
||||
Version version = version_parse(COMMANDS_VERSION);
|
||||
Version dataVersion = { 0, 0 };
|
||||
|
||||
{
|
||||
char value[1024];
|
||||
if(read_var(strINI.c_str(), "Version", "number", value))
|
||||
{
|
||||
dataVersion = version_parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
if(version_compatible(version, dataVersion))
|
||||
{
|
||||
globalOutputStream() << "commands import: data version " << dataVersion << " is compatible with code version " << version << "\n";
|
||||
ReadCommandMap visitor(strINI.c_str());
|
||||
GlobalShortcuts_foreach(visitor);
|
||||
globalOutputStream() << "parsed " << Unsigned(visitor.count()) << " custom shortcuts\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "commands import: data version " << dataVersion << " is not compatible with code version " << version << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "failed to load custom shortcuts from " << makeQuoted(strINI.c_str()) << "\n";
|
||||
}
|
||||
}
|
||||
54
radiant/commands.h
Normal file
54
radiant/commands.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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_COMMANDS_H)
|
||||
#define INCLUDED_COMMANDS_H
|
||||
|
||||
#include "gtkutil/accelerator.h"
|
||||
|
||||
|
||||
const Accelerator& GlobalShortcuts_insert(const char* name, const Accelerator& accelerator);
|
||||
void GlobalShortcuts_register(const char* name);
|
||||
void GlobalShortcuts_reportUnregistered();
|
||||
|
||||
class CommandVisitor
|
||||
{
|
||||
public:
|
||||
virtual void visit(const char* name, Accelerator& accelerator) = 0;
|
||||
};
|
||||
|
||||
void GlobalCommands_insert(const char* name, const Callback& callback, const Accelerator& accelerator = accelerator_null());
|
||||
const Command& GlobalCommands_find(const char* name);
|
||||
|
||||
void GlobalToggles_insert(const char* name, const Callback& callback, const BoolExportCallback& exportCallback, const Accelerator& accelerator = accelerator_null());
|
||||
const Toggle& GlobalToggles_find(const char* name);
|
||||
|
||||
void GlobalKeyEvents_insert(const char* name, const Accelerator& accelerator, const Callback& keyDown, const Callback& keyUp);
|
||||
const KeyEvent& GlobalKeyEvents_find(const char* name);
|
||||
|
||||
|
||||
void DoCommandListDlg();
|
||||
|
||||
void LoadCommandMap(const char* path);
|
||||
void SaveCommandMap(const char* path);
|
||||
|
||||
|
||||
#endif
|
||||
253
radiant/console.cpp
Normal file
253
radiant/console.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
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 "console.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <gtk/gtktextbuffer.h>
|
||||
#include <gtk/gtktextview.h>
|
||||
#include <gtk/gtkmenuitem.h>
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
|
||||
#include "gtkutil/accelerator.h"
|
||||
#include "gtkutil/messagebox.h"
|
||||
#include "gtkutil/container.h"
|
||||
#include "gtkutil/menu.h"
|
||||
#include "gtkutil/nonmodal.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "convert.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "aboutmsg.h"
|
||||
#include "gtkmisc.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
// handle to the console log file
|
||||
namespace
|
||||
{
|
||||
FILE* g_hLogFile;
|
||||
}
|
||||
|
||||
bool g_Console_enableLogging = false;
|
||||
|
||||
// called whenever we need to open/close/check the console log file
|
||||
void Sys_LogFile(bool enable)
|
||||
{
|
||||
if (enable && !g_hLogFile)
|
||||
{
|
||||
// settings say we should be logging and we don't have a log file .. so create it
|
||||
// open a file to log the console (if user prefs say so)
|
||||
// the file handle is g_hLogFile
|
||||
// the log file is erased
|
||||
StringOutputStream name(256);
|
||||
name << SettingsPath_get() << "radiant.log";
|
||||
g_hLogFile = fopen( name.c_str(), "w" );
|
||||
if (g_hLogFile != 0)
|
||||
{
|
||||
globalOutputStream() << "Started logging to " << name.c_str() << "\n";
|
||||
time_t localtime;
|
||||
time(&localtime);
|
||||
globalOutputStream() << "Today is: " << ctime(&localtime)
|
||||
<< "This is GtkRadiant '" RADIANT_VERSION "' compiled " __DATE__ "\n" RADIANT_ABOUTMSG "\n";
|
||||
}
|
||||
else
|
||||
gtk_MessageBox (0, "Failed to create log file, check write permissions in Radiant directory.\n",
|
||||
"Console logging", eMB_OK, eMB_ICONERROR );
|
||||
}
|
||||
else if (!enable && g_hLogFile != 0)
|
||||
{
|
||||
// settings say we should not be logging but still we have an active logfile .. close it
|
||||
time_t localtime;
|
||||
time(&localtime);
|
||||
globalOutputStream() << "Closing log file at " << ctime(&localtime) << "\n";
|
||||
fclose( g_hLogFile );
|
||||
g_hLogFile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* g_console = 0;
|
||||
|
||||
void console_clear()
|
||||
{
|
||||
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(g_console));
|
||||
gtk_text_buffer_set_text(buffer, "", -1);
|
||||
}
|
||||
|
||||
void console_populate_popup(GtkTextView* textview, GtkMenu* menu, gpointer user_data)
|
||||
{
|
||||
menu_separator(menu);
|
||||
|
||||
GtkWidget* item = gtk_menu_item_new_with_label ("Clear");
|
||||
g_signal_connect(G_OBJECT (item), "activate", G_CALLBACK(console_clear), 0);
|
||||
gtk_widget_show (item);
|
||||
container_add_widget(GTK_CONTAINER(menu), item);
|
||||
}
|
||||
|
||||
gboolean destroy_set_null(GtkWindow* widget, GtkWidget** p)
|
||||
{
|
||||
*p = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget* Console_constructWindow(GtkWindow* toplevel)
|
||||
{
|
||||
GtkWidget* scr = gtk_scrolled_window_new (0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
|
||||
gtk_widget_show(scr);
|
||||
|
||||
{
|
||||
GtkWidget* text = gtk_text_view_new();
|
||||
gtk_widget_set_size_request(text, 0, -1); // allow shrinking
|
||||
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
|
||||
gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
|
||||
gtk_container_add(GTK_CONTAINER (scr), text);
|
||||
gtk_widget_show(text);
|
||||
g_console = text;
|
||||
|
||||
//globalExtendedASCIICharacterSet().print();
|
||||
|
||||
widget_connect_escape_clear_focus_widget(g_console);
|
||||
|
||||
g_signal_connect(G_OBJECT(g_console), "populate-popup", G_CALLBACK(console_populate_popup), 0);
|
||||
g_signal_connect(G_OBJECT(g_console), "destroy", G_CALLBACK(destroy_set_null), &g_console);
|
||||
}
|
||||
|
||||
gtk_container_set_focus_chain(GTK_CONTAINER(scr), NULL);
|
||||
|
||||
return scr;
|
||||
}
|
||||
|
||||
std::size_t Sys_Print(int level, const char* buf, std::size_t length)
|
||||
{
|
||||
bool contains_newline = strchr(buf, '\n') != 0;
|
||||
|
||||
if(level == SYS_ERR)
|
||||
{
|
||||
Sys_LogFile(true);
|
||||
}
|
||||
|
||||
if (g_hLogFile != 0)
|
||||
{
|
||||
fwrite(buf, 1, length, g_hLogFile);
|
||||
if(contains_newline)
|
||||
{
|
||||
fflush(g_hLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (level != SYS_NOCON)
|
||||
{
|
||||
if (g_console != 0)
|
||||
{
|
||||
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(g_console));
|
||||
|
||||
GtkTextIter iter;
|
||||
gtk_text_buffer_get_end_iter(buffer, &iter);
|
||||
|
||||
static GtkTextMark* end = gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
|
||||
|
||||
const GdkColor yellow = { 0, 0xb0ff, 0xb0ff, 0x0000 };
|
||||
const GdkColor red = { 0, 0xffff, 0x0000, 0x0000 };
|
||||
const GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
|
||||
|
||||
static GtkTextTag* error_tag = gtk_text_buffer_create_tag (buffer, "red_foreground", "foreground-gdk", &red, 0);
|
||||
static GtkTextTag* warning_tag = gtk_text_buffer_create_tag (buffer, "yellow_foreground", "foreground-gdk", &yellow, 0);
|
||||
static GtkTextTag* standard_tag = gtk_text_buffer_create_tag (buffer, "black_foreground", "foreground-gdk", &black, 0);
|
||||
GtkTextTag* tag;
|
||||
switch (level)
|
||||
{
|
||||
case SYS_WRN:
|
||||
tag = warning_tag;
|
||||
break;
|
||||
case SYS_ERR:
|
||||
tag = error_tag;
|
||||
break;
|
||||
case SYS_STD:
|
||||
case SYS_VRB:
|
||||
default:
|
||||
tag = standard_tag;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
StringOutputStream converted;
|
||||
if(!globalCharacterSet().isUTF8())
|
||||
{
|
||||
converted << ConvertLocaleToUTF8(StringRange(buf, buf + length));
|
||||
}
|
||||
else
|
||||
{
|
||||
converted << StringRange(buf, buf + length);
|
||||
}
|
||||
|
||||
gtk_text_buffer_insert_with_tags(buffer, &iter, converted.c_str(), gint(string_length(converted.c_str())), tag, 0);
|
||||
|
||||
// update console widget immediatly if we're doing something time-consuming
|
||||
if(contains_newline)
|
||||
{
|
||||
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(g_console), end);
|
||||
|
||||
if(!ScreenUpdates_Enabled() && GTK_WIDGET_REALIZED(g_console))
|
||||
{
|
||||
ScreenUpdates_process();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
class SysPrintOutputStream : public TextOutputStream
|
||||
{
|
||||
public:
|
||||
std::size_t write(const char* buffer, std::size_t length)
|
||||
{
|
||||
return Sys_Print(SYS_STD, buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
class SysPrintErrorStream : public TextOutputStream
|
||||
{
|
||||
public:
|
||||
std::size_t write(const char* buffer, std::size_t length)
|
||||
{
|
||||
return Sys_Print(SYS_ERR, buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
SysPrintOutputStream g_outputStream;
|
||||
|
||||
TextOutputStream& getSysPrintOutputStream()
|
||||
{
|
||||
return g_outputStream;
|
||||
}
|
||||
|
||||
SysPrintErrorStream g_errorStream;
|
||||
|
||||
TextOutputStream& getSysPrintErrorStream()
|
||||
{
|
||||
return g_errorStream;
|
||||
}
|
||||
|
||||
|
||||
47
radiant/console.h
Normal file
47
radiant/console.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
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_CONSOLE_H)
|
||||
#define INCLUDED_CONSOLE_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#define SYS_VRB 0 ///< verbose support (on/off)
|
||||
#define SYS_STD 1 ///< standard print level - this is the default
|
||||
#define SYS_WRN 2 ///< warnings
|
||||
#define SYS_ERR 3 ///< error
|
||||
#define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
|
||||
|
||||
std::size_t Sys_Print(int level, const char* buf, std::size_t length);
|
||||
class TextOutputStream;
|
||||
TextOutputStream& getSysPrintOutputStream();
|
||||
TextOutputStream& getSysPrintErrorStream();
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
GtkWidget* Console_constructWindow(GtkWindow* toplevel);
|
||||
|
||||
// will open/close the log file based on the parameter
|
||||
void Sys_LogFile(bool enable);
|
||||
extern bool g_Console_enableLogging;
|
||||
|
||||
|
||||
#endif
|
||||
575
radiant/csg.cpp
Normal file
575
radiant/csg.cpp
Normal file
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
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 "csg.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "map.h"
|
||||
#include "brushmanip.h"
|
||||
#include "brushnode.h"
|
||||
#include "grid.h"
|
||||
|
||||
|
||||
|
||||
void Brush_makeHollow(const Brush& brush, brush_vector_t& out, float offset)
|
||||
{
|
||||
for(Brush::const_iterator i(brush.begin()); i != brush.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes())
|
||||
{
|
||||
out.push_back(new Brush(brush));
|
||||
Face* newFace = out.back()->addFace(*(*i));
|
||||
if(newFace != 0)
|
||||
{
|
||||
newFace->flipWinding();
|
||||
newFace->getPlane().offset(offset);
|
||||
newFace->planeChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BrushHollowSelectedWalker : public scene::Graph::Walker
|
||||
{
|
||||
float m_offset;
|
||||
public:
|
||||
BrushHollowSelectedWalker(float offset)
|
||||
: m_offset(offset)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
if(path.top().get().visible())
|
||||
{
|
||||
Brush* brush = Node_getBrush(path.top());
|
||||
if(brush != 0
|
||||
&& Instance_getSelectable(instance)->isSelected()
|
||||
&& path.size() > 1)
|
||||
{
|
||||
brush_vector_t out;
|
||||
Brush_makeHollow(*brush, out, m_offset);
|
||||
for(brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i)
|
||||
{
|
||||
NodeSmartReference node((new BrushNode())->node());
|
||||
(*i)->removeEmptyFaces();
|
||||
Node_getBrush(node)->copy(*(*i));
|
||||
delete (*i);
|
||||
Node_getTraversable(path.parent())->insert(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<Brush*> brushlist_t;
|
||||
|
||||
class BrushGatherSelected : public scene::Graph::Walker
|
||||
{
|
||||
brush_vector_t& m_brushlist;
|
||||
public:
|
||||
BrushGatherSelected(brush_vector_t& brushlist)
|
||||
: m_brushlist(brushlist)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
if(path.top().get().visible())
|
||||
{
|
||||
Brush* brush = Node_getBrush(path.top());
|
||||
if(brush != 0
|
||||
&& Instance_getSelectable(instance)->isSelected())
|
||||
{
|
||||
m_brushlist.push_back(brush);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class BrushDeleteSelected : public scene::Graph::Walker
|
||||
{
|
||||
public:
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void post(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
if(path.top().get().visible())
|
||||
{
|
||||
Brush* brush = Node_getBrush(path.top());
|
||||
if(brush != 0
|
||||
&& Instance_getSelectable(instance)->isSelected()
|
||||
&& path.size() > 1)
|
||||
{
|
||||
Path_deleteTop(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Scene_BrushMakeHollow_Selected(scene::Graph& graph)
|
||||
{
|
||||
GlobalSceneGraph().traverse(BrushHollowSelectedWalker(GetGridSize()));
|
||||
GlobalSceneGraph().traverse(BrushDeleteSelected());
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CSG_MakeHollow
|
||||
=============
|
||||
*/
|
||||
|
||||
void CSG_MakeHollow (void)
|
||||
{
|
||||
UndoableCommand undo("brushHollow");
|
||||
|
||||
Scene_BrushMakeHollow_Selected(GlobalSceneGraph());
|
||||
|
||||
SceneChangeNotify();
|
||||
}
|
||||
|
||||
|
||||
/// \brief Returns true if
|
||||
/// \li !flipped && brush is BACK or ON
|
||||
/// \li flipped && brush is FRONT or ON
|
||||
bool Brush_testPlane(const Brush& brush, const Plane3& plane, bool flipped)
|
||||
{
|
||||
brush.evaluateBRep();
|
||||
for(Brush::const_iterator i(brush.begin()); i != brush.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes() && !Winding_TestPlane((*i)->getWinding(), plane, flipped))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
brushsplit_t Brush_classifyPlane(const Brush& brush, const Plane3& plane)
|
||||
{
|
||||
brush.evaluateBRep();
|
||||
brushsplit_t split;
|
||||
for(Brush::const_iterator i(brush.begin()); i != brush.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes())
|
||||
{
|
||||
split += Winding_ClassifyPlane((*i)->getWinding(), plane);
|
||||
}
|
||||
}
|
||||
return split;
|
||||
}
|
||||
|
||||
bool Brush_subtract(const Brush& brush, const Brush& other, brush_vector_t& ret_fragments)
|
||||
{
|
||||
if(aabb_intersects_aabb(brush.localAABB(), other.localAABB()))
|
||||
{
|
||||
brush_vector_t fragments;
|
||||
fragments.reserve(other.size());
|
||||
Brush back(brush);
|
||||
|
||||
for(Brush::const_iterator i(other.begin()); i != other.end(); ++i)
|
||||
{
|
||||
if((*i)->contributes())
|
||||
{
|
||||
brushsplit_t split = Brush_classifyPlane(back, (*i)->plane3());
|
||||
if(split.counts[ePlaneFront] != 0
|
||||
&& split.counts[ePlaneBack] != 0)
|
||||
{
|
||||
fragments.push_back(new Brush(back));
|
||||
Face* newFace = fragments.back()->addFace(*(*i));
|
||||
if(newFace != 0)
|
||||
{
|
||||
newFace->flipWinding();
|
||||
}
|
||||
back.addFace(*(*i));
|
||||
}
|
||||
else if(split.counts[ePlaneBack] == 0)
|
||||
{
|
||||
for(brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i)
|
||||
{
|
||||
delete(*i);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret_fragments.insert(ret_fragments.end(), fragments.begin(), fragments.end());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class SubtractBrushesFromUnselected : public scene::Graph::Walker
|
||||
{
|
||||
const brush_vector_t& m_brushlist;
|
||||
std::size_t& m_before;
|
||||
std::size_t& m_after;
|
||||
public:
|
||||
SubtractBrushesFromUnselected(const brush_vector_t& brushlist, std::size_t& before, std::size_t& after)
|
||||
: m_brushlist(brushlist), m_before(before), m_after(after)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void post(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
if(path.top().get().visible())
|
||||
{
|
||||
Brush* brush = Node_getBrush(path.top());
|
||||
if(brush != 0
|
||||
&& !Instance_getSelectable(instance)->isSelected())
|
||||
{
|
||||
brush_vector_t buffer[2];
|
||||
bool swap = false;
|
||||
Brush* original = new Brush(*brush);
|
||||
buffer[static_cast<std::size_t>(swap)].push_back(original);
|
||||
|
||||
{
|
||||
for(brush_vector_t::const_iterator i(m_brushlist.begin()); i != m_brushlist.end(); ++i)
|
||||
{
|
||||
for(brush_vector_t::iterator j(buffer[static_cast<std::size_t>(swap)].begin()); j != buffer[static_cast<std::size_t>(swap)].end(); ++j)
|
||||
{
|
||||
if(Brush_subtract(*(*j), *(*i), buffer[static_cast<std::size_t>(!swap)]))
|
||||
{
|
||||
delete (*j);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[static_cast<std::size_t>(!swap)].push_back((*j));
|
||||
}
|
||||
}
|
||||
buffer[static_cast<std::size_t>(swap)].clear();
|
||||
swap = !swap;
|
||||
}
|
||||
}
|
||||
|
||||
brush_vector_t& out = buffer[static_cast<std::size_t>(swap)];
|
||||
|
||||
if(out.size() == 1 && out.back() == original)
|
||||
{
|
||||
delete original;
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_before;
|
||||
for(brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i)
|
||||
{
|
||||
++m_after;
|
||||
NodeSmartReference node((new BrushNode())->node());
|
||||
(*i)->removeEmptyFaces();
|
||||
ASSERT_MESSAGE(!(*i)->empty(), "brush left with no faces after subtract");
|
||||
Node_getBrush(node)->copy(*(*i));
|
||||
delete (*i);
|
||||
Node_getTraversable(path.parent())->insert(node);
|
||||
}
|
||||
Path_deleteTop(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void CSG_Subtract()
|
||||
{
|
||||
brush_vector_t selected_brushes;
|
||||
GlobalSceneGraph().traverse(BrushGatherSelected(selected_brushes));
|
||||
|
||||
if (selected_brushes.empty())
|
||||
{
|
||||
globalOutputStream() << "CSG Subtract: No brushes selected.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned(selected_brushes.size()) << " brushes.\n";
|
||||
|
||||
UndoableCommand undo("brushSubtract");
|
||||
|
||||
// subtract selected from unselected
|
||||
std::size_t before = 0;
|
||||
std::size_t after = 0;
|
||||
GlobalSceneGraph().traverse(SubtractBrushesFromUnselected(selected_brushes, before, after));
|
||||
globalOutputStream() << "CSG Subtract: Result: "
|
||||
<< Unsigned(after) << " fragment" << (after == 1 ? "" : "s")
|
||||
<< " from " << Unsigned(before) << " brush" << (before == 1? "" : "es") << ".\n";
|
||||
|
||||
SceneChangeNotify();
|
||||
}
|
||||
}
|
||||
|
||||
class BrushSplitByPlaneSelected : public scene::Graph::Walker
|
||||
{
|
||||
const Vector3& m_p0;
|
||||
const Vector3& m_p1;
|
||||
const Vector3& m_p2;
|
||||
const char* m_shader;
|
||||
const TextureProjection& m_projection;
|
||||
EBrushSplit m_split;
|
||||
public:
|
||||
BrushSplitByPlaneSelected(const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection, EBrushSplit split)
|
||||
: m_p0(p0), m_p1(p1), m_p2(p2), m_shader(shader), m_projection(projection), m_split(split)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void post(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
if(path.top().get().visible())
|
||||
{
|
||||
Brush* brush = Node_getBrush(path.top());
|
||||
if(brush != 0
|
||||
&& Instance_getSelectable(instance)->isSelected())
|
||||
{
|
||||
Plane3 plane(plane3_for_points(m_p0, m_p1, m_p2));
|
||||
if(plane3_valid(plane))
|
||||
{
|
||||
brushsplit_t split = Brush_classifyPlane(*brush, m_split == eFront ? plane3_flipped(plane) : plane);
|
||||
if(split.counts[ePlaneBack] && split.counts[ePlaneFront])
|
||||
{
|
||||
// the plane intersects this brush
|
||||
if(m_split == eFrontAndBack)
|
||||
{
|
||||
NodeSmartReference node((new BrushNode())->node());
|
||||
Brush* fragment = Node_getBrush(node);
|
||||
fragment->copy(*brush);
|
||||
Face* newFace = fragment->addPlane(m_p0, m_p1, m_p2, m_shader, m_projection);
|
||||
if(newFace != 0 && m_split != eFront)
|
||||
{
|
||||
newFace->flipWinding();
|
||||
}
|
||||
fragment->removeEmptyFaces();
|
||||
ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split");
|
||||
|
||||
Node_getTraversable(path.parent())->insert(node);
|
||||
{
|
||||
scene::Path fragmentPath = path;
|
||||
fragmentPath.top() = makeReference(node.get());
|
||||
selectPath(fragmentPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
Face* newFace = brush->addPlane(m_p0, m_p1, m_p2, m_shader, m_projection);
|
||||
if(newFace != 0 && m_split == eFront)
|
||||
{
|
||||
newFace->flipWinding();
|
||||
}
|
||||
brush->removeEmptyFaces();
|
||||
ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after split");
|
||||
}
|
||||
else
|
||||
// the plane does not intersect this brush
|
||||
if(m_split != eFrontAndBack && split.counts[ePlaneBack] != 0)
|
||||
{
|
||||
// the brush is "behind" the plane
|
||||
Path_deleteTop(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Scene_BrushSplitByPlane(scene::Graph& graph, const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, EBrushSplit split)
|
||||
{
|
||||
TextureProjection projection;
|
||||
TexDef_Construct_Default(projection);
|
||||
graph.traverse(BrushSplitByPlaneSelected(p0, p1, p2, shader, projection, split));
|
||||
SceneChangeNotify();
|
||||
}
|
||||
|
||||
|
||||
class BrushInstanceSetClipPlane : public scene::Graph::Walker
|
||||
{
|
||||
Plane3 m_plane;
|
||||
public:
|
||||
BrushInstanceSetClipPlane(const Plane3& plane)
|
||||
: m_plane(plane)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
BrushInstance* brush = Instance_getBrush(instance);
|
||||
if(brush != 0
|
||||
&& path.top().get().visible()
|
||||
&& brush->isSelected())
|
||||
{
|
||||
BrushInstance& brushInstance = *brush;
|
||||
brushInstance.setClipPlane(m_plane);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void Scene_BrushSetClipPlane(scene::Graph& graph, const Plane3& plane)
|
||||
{
|
||||
graph.traverse(BrushInstanceSetClipPlane(plane));
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CSG_Merge
|
||||
=============
|
||||
*/
|
||||
bool Brush_merge(Brush& brush, const brush_vector_t& in, bool onlyshape)
|
||||
{
|
||||
// gather potential outer faces
|
||||
|
||||
{
|
||||
typedef std::vector<const Face*> Faces;
|
||||
Faces faces;
|
||||
for(brush_vector_t::const_iterator i(in.begin()); i != in.end(); ++i)
|
||||
{
|
||||
(*i)->evaluateBRep();
|
||||
for(Brush::const_iterator j((*i)->begin()); j != (*i)->end(); ++j)
|
||||
{
|
||||
if(!(*j)->contributes())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Face& face1 = *(*j);
|
||||
|
||||
bool skip = false;
|
||||
// test faces of all input brushes
|
||||
//!\todo SPEEDUP: Flag already-skip faces and only test brushes from i+1 upwards.
|
||||
for(brush_vector_t::const_iterator k(in.begin()); !skip && k != in.end(); ++k)
|
||||
{
|
||||
if(k != i) // don't test a brush against itself
|
||||
{
|
||||
for(Brush::const_iterator l((*k)->begin()); !skip && l != (*k)->end(); ++l)
|
||||
{
|
||||
const Face& face2 = *(*l);
|
||||
|
||||
// face opposes another face
|
||||
if(plane3_opposing(face1.plane3(), face2.plane3()))
|
||||
{
|
||||
// skip opposing planes
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check faces already stored
|
||||
for(Faces::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m)
|
||||
{
|
||||
const Face& face2 = *(*m);
|
||||
|
||||
// face equals another face
|
||||
if (plane3_equal(face1.plane3(), face2.plane3()))
|
||||
{
|
||||
//if the texture/shader references should be the same but are not
|
||||
if (!onlyshape && !shader_equal(face1.getShader().getShader(), face2.getShader().getShader()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// skip duplicate planes
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// face1 plane intersects face2 winding or vice versa
|
||||
if (Winding_PlanesConcave(face1.getWinding(), face2.getWinding(), face1.plane3(), face2.plane3()))
|
||||
{
|
||||
// result would not be convex
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!skip)
|
||||
{
|
||||
faces.push_back(&face1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Faces::const_iterator i = faces.begin(); i != faces.end(); ++i)
|
||||
{
|
||||
if(!brush.addFace(*(*i)))
|
||||
{
|
||||
// result would have too many sides
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
brush.removeEmptyFaces();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSG_Merge(void)
|
||||
{
|
||||
brush_vector_t selected_brushes;
|
||||
|
||||
// remove selected
|
||||
GlobalSceneGraph().traverse(BrushGatherSelected(selected_brushes));
|
||||
|
||||
if (selected_brushes.empty())
|
||||
{
|
||||
globalOutputStream() << "CSG Merge: No brushes selected.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected_brushes.size() < 2)
|
||||
{
|
||||
globalOutputStream() << "CSG Merge: At least two brushes have to be selected.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
globalOutputStream() << "CSG Merge: Merging " << Unsigned(selected_brushes.size()) << " brushes.\n";
|
||||
|
||||
UndoableCommand undo("brushMerge");
|
||||
|
||||
scene::Path merged_path = GlobalSelectionSystem().ultimateSelected().path();
|
||||
|
||||
NodeSmartReference node((new BrushNode())->node());
|
||||
Brush* brush = Node_getBrush(node);
|
||||
// if the new brush would not be convex
|
||||
if(!Brush_merge(*brush, selected_brushes, true))
|
||||
{
|
||||
globalOutputStream() << "CSG Merge: Failed - result would not be convex.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after merge");
|
||||
|
||||
// free the original brushes
|
||||
GlobalSceneGraph().traverse(BrushDeleteSelected());
|
||||
|
||||
merged_path.pop();
|
||||
Node_getTraversable(merged_path.top())->insert(node);
|
||||
merged_path.push(makeReference(node.get()));
|
||||
|
||||
selectPath(merged_path, true);
|
||||
|
||||
globalOutputStream() << "CSG Merge: Succeeded.\n";
|
||||
SceneChangeNotify();
|
||||
}
|
||||
}
|
||||
46
radiant/csg.h
Normal file
46
radiant/csg.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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_CSG_H)
|
||||
#define INCLUDED_CSG_H
|
||||
|
||||
void CSG_MakeHollow (void);
|
||||
void CSG_Subtract (void);
|
||||
void CSG_Merge (void);
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Graph;
|
||||
}
|
||||
template<typename Element> class BasicVector3;
|
||||
typedef BasicVector3<float> Vector3;
|
||||
class Plane3;
|
||||
|
||||
void Scene_BrushSetClipPlane(scene::Graph& graph, const Plane3& plane);
|
||||
enum EBrushSplit
|
||||
{
|
||||
eFront,
|
||||
eBack,
|
||||
eFrontAndBack,
|
||||
};
|
||||
void Scene_BrushSplitByPlane(scene::Graph& graph, const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, EBrushSplit split);
|
||||
|
||||
#endif
|
||||
740
radiant/dialog.cpp
Normal file
740
radiant/dialog.cpp
Normal file
@@ -0,0 +1,740 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
//
|
||||
// Base dialog class, provides a way to run modal dialogs and
|
||||
// set/get the widget values in member variables.
|
||||
//
|
||||
// Leonardo Zide (leo@lokigames.com)
|
||||
//
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
|
||||
#include "mainframe.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <gtk/gtkvbox.h>
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtktogglebutton.h>
|
||||
#include <gtk/gtkspinbutton.h>
|
||||
#include <gtk/gtkradiobutton.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
#include <gtk/gtkcombobox.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtktable.h>
|
||||
#include <gtk/gtkhscale.h>
|
||||
#include <gtk/gtkalignment.h>
|
||||
|
||||
#include "stream/stringstream.h"
|
||||
#include "convert.h"
|
||||
#include "gtkutil/dialog.h"
|
||||
#include "gtkutil/button.h"
|
||||
#include "gtkutil/entry.h"
|
||||
#include "gtkutil/image.h"
|
||||
|
||||
#include "gtkmisc.h"
|
||||
|
||||
|
||||
GtkEntry* DialogEntry_new()
|
||||
{
|
||||
GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
|
||||
gtk_widget_show(GTK_WIDGET(entry));
|
||||
gtk_widget_set_size_request(GTK_WIDGET(entry), 64, -1);
|
||||
return entry;
|
||||
}
|
||||
|
||||
class DialogEntryRow
|
||||
{
|
||||
public:
|
||||
DialogEntryRow(GtkWidget* row, GtkEntry* entry) : m_row(row), m_entry(entry)
|
||||
{
|
||||
}
|
||||
GtkWidget* m_row;
|
||||
GtkEntry* m_entry;
|
||||
};
|
||||
|
||||
DialogEntryRow DialogEntryRow_new(const char* name)
|
||||
{
|
||||
GtkWidget* alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
|
||||
gtk_widget_show(alignment);
|
||||
|
||||
GtkEntry* entry = DialogEntry_new();
|
||||
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(entry));
|
||||
|
||||
return DialogEntryRow(GTK_WIDGET(DialogRow_new(name, alignment)), entry);
|
||||
}
|
||||
|
||||
|
||||
GtkSpinButton* DialogSpinner_new(double value, double lower, double upper, int fraction)
|
||||
{
|
||||
double step = 1.0 / double(fraction);
|
||||
unsigned int digits = 0;
|
||||
for(;fraction > 1; fraction /= 10)
|
||||
{
|
||||
++digits;
|
||||
}
|
||||
GtkSpinButton* spin = GTK_SPIN_BUTTON(gtk_spin_button_new(GTK_ADJUSTMENT(gtk_adjustment_new(value, lower, upper, step, 10, 10)), step, digits));
|
||||
gtk_widget_show(GTK_WIDGET(spin));
|
||||
gtk_widget_set_size_request(GTK_WIDGET(spin), 64, -1);
|
||||
return spin;
|
||||
}
|
||||
|
||||
class DialogSpinnerRow
|
||||
{
|
||||
public:
|
||||
DialogSpinnerRow(GtkWidget* row, GtkSpinButton* spin) : m_row(row), m_spin(spin)
|
||||
{
|
||||
}
|
||||
GtkWidget* m_row;
|
||||
GtkSpinButton* m_spin;
|
||||
};
|
||||
|
||||
DialogSpinnerRow DialogSpinnerRow_new(const char* name, double value, double lower, double upper, int fraction)
|
||||
{
|
||||
GtkWidget* alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
|
||||
gtk_widget_show(alignment);
|
||||
|
||||
GtkSpinButton* spin = DialogSpinner_new(value, lower, upper, fraction);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(spin));
|
||||
|
||||
return DialogSpinnerRow(GTK_WIDGET(DialogRow_new(name, alignment)), spin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<
|
||||
typename Type_,
|
||||
typename Other_,
|
||||
void(*Import)(Type_&, Other_),
|
||||
void(*Export)(Type_&, const Callback1<Other_>&)
|
||||
>
|
||||
class ImportExport
|
||||
{
|
||||
public:
|
||||
typedef Type_ Type;
|
||||
typedef Other_ Other;
|
||||
|
||||
typedef ReferenceCaller1<Type, Other, Import> ImportCaller;
|
||||
typedef ReferenceCaller1<Type, const Callback1<Other>&, Export> ExportCaller;
|
||||
};
|
||||
|
||||
typedef ImportExport<bool, bool, BoolImport, BoolExport> BoolImportExport;
|
||||
typedef ImportExport<int, int, IntImport, IntExport> IntImportExport;
|
||||
typedef ImportExport<std::size_t, std::size_t, SizeImport, SizeExport> SizeImportExport;
|
||||
typedef ImportExport<float, float, FloatImport, FloatExport> FloatImportExport;
|
||||
typedef ImportExport<CopiedString, const char*, StringImport, StringExport> StringImportExport;
|
||||
|
||||
|
||||
|
||||
void BoolToggleImport(GtkToggleButton& widget, bool value)
|
||||
{
|
||||
gtk_toggle_button_set_active(&widget, value);
|
||||
}
|
||||
void BoolToggleExport(GtkToggleButton& widget, const BoolImportCallback& importCallback)
|
||||
{
|
||||
importCallback(gtk_toggle_button_get_active(&widget) != FALSE);
|
||||
}
|
||||
typedef ImportExport<GtkToggleButton, bool, BoolToggleImport, BoolToggleExport> BoolToggleImportExport;
|
||||
|
||||
|
||||
void IntRadioImport(GtkRadioButton& widget, int index)
|
||||
{
|
||||
radio_button_set_active(&widget, index);
|
||||
}
|
||||
void IntRadioExport(GtkRadioButton& widget, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback(radio_button_get_active(&widget));
|
||||
}
|
||||
typedef ImportExport<GtkRadioButton, int, IntRadioImport, IntRadioExport> IntRadioImportExport;
|
||||
|
||||
|
||||
void TextEntryImport(GtkEntry& widget, const char* text)
|
||||
{
|
||||
StringOutputStream value(64);
|
||||
value << ConvertLocaleToUTF8(text);
|
||||
gtk_entry_set_text(&widget, value.c_str());
|
||||
}
|
||||
void TextEntryExport(GtkEntry& widget, const StringImportCallback& importCallback)
|
||||
{
|
||||
StringOutputStream value(64);
|
||||
value << ConvertUTF8ToLocale(gtk_entry_get_text(&widget));
|
||||
importCallback(value.c_str());
|
||||
}
|
||||
typedef ImportExport<GtkEntry, const char*, TextEntryImport, TextEntryExport> TextEntryImportExport;
|
||||
|
||||
|
||||
void IntEntryImport(GtkEntry& widget, int value)
|
||||
{
|
||||
entry_set_int(&widget, value);
|
||||
}
|
||||
void IntEntryExport(GtkEntry& widget, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback(atoi(gtk_entry_get_text (&widget)));
|
||||
}
|
||||
typedef ImportExport<GtkEntry, int, IntEntryImport, IntEntryExport> IntEntryImportExport;
|
||||
|
||||
|
||||
void SizeEntryImport(GtkEntry& widget, std::size_t value)
|
||||
{
|
||||
entry_set_int(&widget, int(value));
|
||||
}
|
||||
void SizeEntryExport(GtkEntry& widget, const SizeImportCallback& importCallback)
|
||||
{
|
||||
int value = atoi(gtk_entry_get_text(&widget));
|
||||
if(value < 0)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
importCallback(value);
|
||||
}
|
||||
typedef ImportExport<GtkEntry, std::size_t, SizeEntryImport, SizeEntryExport> SizeEntryImportExport;
|
||||
|
||||
|
||||
void FloatEntryImport(GtkEntry& widget, float value)
|
||||
{
|
||||
entry_set_float(&widget, value);
|
||||
}
|
||||
void FloatEntryExport(GtkEntry& widget, const FloatImportCallback& importCallback)
|
||||
{
|
||||
importCallback((float)atof(gtk_entry_get_text(&widget)));
|
||||
}
|
||||
typedef ImportExport<GtkEntry, float, FloatEntryImport, FloatEntryExport> FloatEntryImportExport;
|
||||
|
||||
|
||||
void FloatSpinnerImport(GtkSpinButton& widget, float value)
|
||||
{
|
||||
gtk_spin_button_set_value(&widget, value);
|
||||
}
|
||||
void FloatSpinnerExport(GtkSpinButton& widget, const FloatImportCallback& importCallback)
|
||||
{
|
||||
importCallback(float(gtk_spin_button_get_value_as_float(&widget)));
|
||||
}
|
||||
typedef ImportExport<GtkSpinButton, float, FloatSpinnerImport, FloatSpinnerExport> FloatSpinnerImportExport;
|
||||
|
||||
|
||||
void IntSpinnerImport(GtkSpinButton& widget, int value)
|
||||
{
|
||||
gtk_spin_button_set_value(&widget, value);
|
||||
}
|
||||
void IntSpinnerExport(GtkSpinButton& widget, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback(gtk_spin_button_get_value_as_int(&widget));
|
||||
}
|
||||
typedef ImportExport<GtkSpinButton, int, IntSpinnerImport, IntSpinnerExport> IntSpinnerImportExport;
|
||||
|
||||
|
||||
void IntAdjustmentImport(GtkAdjustment& widget, int value)
|
||||
{
|
||||
gtk_adjustment_set_value(&widget, value);
|
||||
}
|
||||
void IntAdjustmentExport(GtkAdjustment& widget, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback((int)gtk_adjustment_get_value(&widget));
|
||||
}
|
||||
typedef ImportExport<GtkAdjustment, int, IntAdjustmentImport, IntAdjustmentExport> IntAdjustmentImportExport;
|
||||
|
||||
|
||||
void IntComboImport(GtkComboBox& widget, int value)
|
||||
{
|
||||
gtk_combo_box_set_active(&widget, value);
|
||||
}
|
||||
void IntComboExport(GtkComboBox& widget, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback(gtk_combo_box_get_active(&widget));
|
||||
}
|
||||
typedef ImportExport<GtkComboBox, int, IntComboImport, IntComboExport> IntComboImportExport;
|
||||
|
||||
|
||||
template<typename FirstArgument>
|
||||
class CallbackDialogData : public DLG_DATA
|
||||
{
|
||||
public:
|
||||
typedef Callback1<FirstArgument> ImportCallback;
|
||||
typedef Callback1<const ImportCallback&> ExportCallback;
|
||||
|
||||
private:
|
||||
ImportCallback m_importWidget;
|
||||
ExportCallback m_exportWidget;
|
||||
ImportCallback m_importViewer;
|
||||
ExportCallback m_exportViewer;
|
||||
|
||||
public:
|
||||
CallbackDialogData(const ImportCallback& importWidget, const ExportCallback& exportWidget, const ImportCallback& importViewer, const ExportCallback& exportViewer)
|
||||
: m_importWidget(importWidget), m_exportWidget(exportWidget), m_importViewer(importViewer), m_exportViewer(exportViewer)
|
||||
{
|
||||
}
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
void importData() const
|
||||
{
|
||||
m_exportViewer(m_importWidget);
|
||||
}
|
||||
void exportData() const
|
||||
{
|
||||
m_exportWidget(m_importViewer);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Widget, typename Viewer>
|
||||
class AddData
|
||||
{
|
||||
DialogDataList& m_data;
|
||||
public:
|
||||
AddData(DialogDataList& data) : m_data(data)
|
||||
{
|
||||
}
|
||||
void apply(typename Widget::Type& widget, typename Viewer::Type& viewer) const
|
||||
{
|
||||
m_data.push_back(
|
||||
new CallbackDialogData<typename Widget::Other>(
|
||||
typename Widget::ImportCaller(widget),
|
||||
typename Widget::ExportCaller(widget),
|
||||
typename Viewer::ImportCaller(viewer),
|
||||
typename Viewer::ExportCaller(viewer)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Widget>
|
||||
class AddCustomData
|
||||
{
|
||||
DialogDataList& m_data;
|
||||
public:
|
||||
AddCustomData(DialogDataList& data) : m_data(data)
|
||||
{
|
||||
}
|
||||
void apply(
|
||||
typename Widget::Type& widget,
|
||||
const Callback1<typename Widget::Other>& importViewer,
|
||||
const Callback1<const Callback1<typename Widget::Other>&>& exportViewer
|
||||
) const
|
||||
{
|
||||
m_data.push_back(
|
||||
new CallbackDialogData<typename Widget::Other>(
|
||||
typename Widget::ImportCaller(widget),
|
||||
typename Widget::ExportCaller(widget),
|
||||
importViewer,
|
||||
exportViewer
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Dialog class
|
||||
|
||||
Dialog::Dialog() : m_window(0), m_parent(0)
|
||||
{
|
||||
}
|
||||
|
||||
Dialog::~Dialog()
|
||||
{
|
||||
for(DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i)
|
||||
{
|
||||
(*i)->release();
|
||||
}
|
||||
|
||||
ASSERT_MESSAGE(m_window == 0, "dialog window not destroyed");
|
||||
}
|
||||
|
||||
void Dialog::ShowDlg()
|
||||
{
|
||||
ASSERT_MESSAGE(m_window != 0, "dialog was not constructed")
|
||||
importData();
|
||||
gtk_widget_show(GTK_WIDGET(m_window));
|
||||
}
|
||||
|
||||
void Dialog::HideDlg()
|
||||
{
|
||||
ASSERT_MESSAGE(m_window != 0, "dialog was not constructed")
|
||||
exportData();
|
||||
gtk_widget_hide(GTK_WIDGET(m_window));
|
||||
}
|
||||
|
||||
static gint delete_event_callback(GtkWidget *widget, GdkEvent* event, gpointer data)
|
||||
{
|
||||
reinterpret_cast<Dialog*>(data)->HideDlg();
|
||||
reinterpret_cast<Dialog*>(data)->EndModal(eIDCANCEL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Dialog::Create()
|
||||
{
|
||||
ASSERT_MESSAGE(m_window == 0, "dialog cannot be constructed")
|
||||
|
||||
m_window = BuildDialog();
|
||||
g_signal_connect(G_OBJECT(m_window), "delete_event", G_CALLBACK(delete_event_callback), this);
|
||||
}
|
||||
|
||||
void Dialog::Destroy()
|
||||
{
|
||||
ASSERT_MESSAGE(m_window != 0, "dialog cannot be destroyed");
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(m_window));
|
||||
m_window = 0;
|
||||
}
|
||||
|
||||
|
||||
void Dialog::AddBoolToggleData(GtkToggleButton& widget, const BoolImportCallback& importViewer, const BoolExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<BoolToggleImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddIntRadioData(GtkRadioButton& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<IntRadioImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddTextEntryData(GtkEntry& widget, const StringImportCallback& importViewer, const StringExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<TextEntryImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddIntEntryData(GtkEntry& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<IntEntryImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddSizeEntryData(GtkEntry& widget, const SizeImportCallback& importViewer, const SizeExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<SizeEntryImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddFloatEntryData(GtkEntry& widget, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<FloatEntryImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddFloatSpinnerData(GtkSpinButton& widget, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<FloatSpinnerImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddIntSpinnerData(GtkSpinButton& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<IntSpinnerImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddIntAdjustmentData(GtkAdjustment& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<IntAdjustmentImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
void Dialog::AddIntComboData(GtkComboBox& widget, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
AddCustomData<IntComboImportExport>(m_data).apply(widget, importViewer, exportViewer);
|
||||
}
|
||||
|
||||
|
||||
void Dialog::AddDialogData(GtkToggleButton& widget, bool& data)
|
||||
{
|
||||
AddData<BoolToggleImportExport, BoolImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkRadioButton& widget, int& data)
|
||||
{
|
||||
AddData<IntRadioImportExport, IntImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkEntry& widget, CopiedString& data)
|
||||
{
|
||||
AddData<TextEntryImportExport, StringImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkEntry& widget, int& data)
|
||||
{
|
||||
AddData<IntEntryImportExport, IntImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkEntry& widget, std::size_t& data)
|
||||
{
|
||||
AddData<SizeEntryImportExport, SizeImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkEntry& widget, float& data)
|
||||
{
|
||||
AddData<FloatEntryImportExport, FloatImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkSpinButton& widget, float& data)
|
||||
{
|
||||
AddData<FloatSpinnerImportExport, FloatImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkSpinButton& widget, int& data)
|
||||
{
|
||||
AddData<IntSpinnerImportExport, IntImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkAdjustment& widget, int& data)
|
||||
{
|
||||
AddData<IntAdjustmentImportExport, IntImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
void Dialog::AddDialogData(GtkComboBox& widget, int& data)
|
||||
{
|
||||
AddData<IntComboImportExport, IntImportExport>(m_data).apply(widget, data);
|
||||
}
|
||||
|
||||
void Dialog::exportData()
|
||||
{
|
||||
for(DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i)
|
||||
{
|
||||
(*i)->exportData();
|
||||
}
|
||||
}
|
||||
|
||||
void Dialog::importData()
|
||||
{
|
||||
for(DialogDataList::iterator i = m_data.begin(); i != m_data.end(); ++i)
|
||||
{
|
||||
(*i)->importData();
|
||||
}
|
||||
}
|
||||
|
||||
void Dialog::EndModal (EMessageBoxReturn code)
|
||||
{
|
||||
m_modal.loop = 0;
|
||||
m_modal.ret = code;
|
||||
}
|
||||
|
||||
EMessageBoxReturn Dialog::DoModal()
|
||||
{
|
||||
importData();
|
||||
|
||||
PreModal();
|
||||
|
||||
EMessageBoxReturn ret = modal_dialog_show(m_window, m_modal);
|
||||
ASSERT_NOTNULL(m_window);
|
||||
if(ret == eIDOK)
|
||||
{
|
||||
exportData();
|
||||
}
|
||||
|
||||
gtk_widget_hide(GTK_WIDGET(m_window));
|
||||
|
||||
PostModal(m_modal.ret);
|
||||
|
||||
return m_modal.ret;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget* Dialog::addCheckBox(GtkWidget* vbox, const char* name, const char* flag, const BoolImportCallback& importViewer, const BoolExportCallback& exportViewer)
|
||||
{
|
||||
GtkWidget* check = gtk_check_button_new_with_label(flag);
|
||||
gtk_widget_show(check);
|
||||
AddBoolToggleData(*GTK_TOGGLE_BUTTON(check), importViewer, exportViewer);
|
||||
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(DialogRow_new(name, check)));
|
||||
return check;
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addCheckBox(GtkWidget* vbox, const char* name, const char* flag, bool& data)
|
||||
{
|
||||
return addCheckBox(vbox, name, flag, BoolImportCaller(data), BoolExportCaller(data));
|
||||
}
|
||||
|
||||
void Dialog::addCombo(GtkWidget* vbox, const char* name, StringArrayRange values, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
GtkWidget* alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
|
||||
gtk_widget_show(alignment);
|
||||
{
|
||||
GtkWidget* combo = gtk_combo_box_new_text();
|
||||
|
||||
for(StringArrayRange::Iterator i = values.begin; i != values.end; ++i)
|
||||
{
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), *i);
|
||||
}
|
||||
|
||||
AddIntComboData(*GTK_COMBO_BOX(combo), importViewer, exportViewer);
|
||||
|
||||
gtk_widget_show (combo);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), combo);
|
||||
}
|
||||
|
||||
GtkTable* row = DialogRow_new(name, alignment);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(row));
|
||||
}
|
||||
|
||||
void Dialog::addCombo(GtkWidget* vbox, const char* name, int& data, StringArrayRange values)
|
||||
{
|
||||
addCombo(vbox, name, values, IntImportCaller(data), IntExportCaller(data));
|
||||
}
|
||||
|
||||
void Dialog::addSlider(GtkWidget* vbox, const char* name, int& data, gboolean draw_value, const char* low, const char* high, double value, double lower, double upper, double step_increment, double page_increment, double page_size)
|
||||
{
|
||||
#if 0
|
||||
if(draw_value == FALSE)
|
||||
{
|
||||
GtkWidget* hbox2 = gtk_hbox_new (FALSE, 0);
|
||||
gtk_widget_show (hbox2);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox2), FALSE, FALSE, 0);
|
||||
{
|
||||
GtkWidget* label = gtk_label_new (low);
|
||||
gtk_widget_show (label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
|
||||
}
|
||||
{
|
||||
GtkWidget* label = gtk_label_new (high);
|
||||
gtk_widget_show (label);
|
||||
gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// adjustment
|
||||
GtkObject* adj = gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
|
||||
AddIntAdjustmentData(*GTK_ADJUSTMENT(adj), IntImportCaller(data), IntExportCaller(data));
|
||||
|
||||
// scale
|
||||
GtkWidget* alignment = gtk_alignment_new(0.0, 0.5, 1.0, 0.0);
|
||||
gtk_widget_show(alignment);
|
||||
|
||||
GtkWidget* scale = gtk_hscale_new(GTK_ADJUSTMENT(adj));
|
||||
gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_LEFT);
|
||||
gtk_widget_show(scale);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), scale);
|
||||
|
||||
gtk_scale_set_draw_value(GTK_SCALE (scale), draw_value);
|
||||
gtk_scale_set_digits(GTK_SCALE (scale), 0);
|
||||
|
||||
GtkTable* row = DialogRow_new(name, alignment);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(row));
|
||||
}
|
||||
|
||||
void Dialog::addRadio(GtkWidget* vbox, const char* name, StringArrayRange names, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
GtkWidget* alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
|
||||
gtk_widget_show(alignment);
|
||||
{
|
||||
RadioHBox radioBox = RadioHBox_new(names);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(radioBox.m_hbox));
|
||||
AddIntRadioData(*GTK_RADIO_BUTTON(radioBox.m_radio), importViewer, exportViewer);
|
||||
}
|
||||
|
||||
GtkTable* row = DialogRow_new(name, alignment);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(row));
|
||||
}
|
||||
|
||||
void Dialog::addRadio(GtkWidget* vbox, const char* name, int& data, StringArrayRange names)
|
||||
{
|
||||
addRadio(vbox, name, names, IntImportCaller(data), IntExportCaller(data));
|
||||
}
|
||||
|
||||
void Dialog::addRadioIcons(GtkWidget* vbox, const char* name, StringArrayRange icons, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
GtkWidget* table = gtk_table_new (2, static_cast<guint>(icons.end - icons.begin), FALSE);
|
||||
gtk_widget_show (table);
|
||||
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 5);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 5);
|
||||
|
||||
GSList* group = 0;
|
||||
GtkWidget* radio = 0;
|
||||
for(StringArrayRange::Iterator icon = icons.begin; icon != icons.end; ++icon)
|
||||
{
|
||||
guint pos = static_cast<guint>(icon - icons.begin);
|
||||
GtkImage* image = new_local_image(*icon);
|
||||
gtk_widget_show(GTK_WIDGET(image));
|
||||
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(image), pos, pos+1, 0, 1,
|
||||
(GtkAttachOptions) (0),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
radio = gtk_radio_button_new(group);
|
||||
gtk_widget_show (radio);
|
||||
gtk_table_attach (GTK_TABLE (table), radio, pos, pos+1, 1, 2,
|
||||
(GtkAttachOptions) (0),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
|
||||
}
|
||||
|
||||
AddIntRadioData(*GTK_RADIO_BUTTON(radio), importViewer, exportViewer);
|
||||
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(DialogRow_new(name, table)));
|
||||
}
|
||||
|
||||
void Dialog::addRadioIcons(GtkWidget* vbox, const char* name, int& data, StringArrayRange icons)
|
||||
{
|
||||
addRadioIcons(vbox, name, icons, IntImportCaller(data), IntExportCaller(data));
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addEntry(GtkWidget* vbox, const char* name, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
DialogEntryRow row(DialogEntryRow_new(name));
|
||||
AddIntEntryData(*row.m_entry, importViewer, exportViewer);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), row.m_row);
|
||||
return row.m_row;
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addEntry(GtkWidget* vbox, const char* name, const SizeImportCallback& importViewer, const SizeExportCallback& exportViewer)
|
||||
{
|
||||
DialogEntryRow row(DialogEntryRow_new(name));
|
||||
AddSizeEntryData(*row.m_entry, importViewer, exportViewer);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), row.m_row);
|
||||
return row.m_row;
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addEntry(GtkWidget* vbox, const char* name, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer)
|
||||
{
|
||||
DialogEntryRow row(DialogEntryRow_new(name));
|
||||
AddFloatEntryData(*row.m_entry, importViewer, exportViewer);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), row.m_row);
|
||||
return row.m_row;
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addPathEntry(GtkWidget* vbox, const char* name, bool browse_directory, const StringImportCallback& importViewer, const StringExportCallback& exportViewer)
|
||||
{
|
||||
PathEntry pathEntry = PathEntry_new();
|
||||
g_signal_connect(G_OBJECT(pathEntry.m_button), "clicked", G_CALLBACK(browse_directory ? button_clicked_entry_browse_directory : button_clicked_entry_browse_file), pathEntry.m_entry);
|
||||
|
||||
AddTextEntryData(*GTK_ENTRY(pathEntry.m_entry), importViewer, exportViewer);
|
||||
|
||||
GtkTable* row = DialogRow_new(name, GTK_WIDGET(pathEntry.m_frame));
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), GTK_WIDGET(row));
|
||||
|
||||
return GTK_WIDGET(row);
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addPathEntry(GtkWidget* vbox, const char* name, CopiedString& data, bool browse_directory)
|
||||
{
|
||||
return addPathEntry(vbox, name, browse_directory, StringImportCallback(StringImportCaller(data)), StringExportCallback(StringExportCaller(data)));
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addSpinner(GtkWidget* vbox, const char* name, double value, double lower, double upper, const IntImportCallback& importViewer, const IntExportCallback& exportViewer)
|
||||
{
|
||||
DialogSpinnerRow row(DialogSpinnerRow_new(name, value, lower, upper, 1));
|
||||
AddIntSpinnerData(*row.m_spin, importViewer, exportViewer);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), row.m_row);
|
||||
return row.m_row;
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addSpinner(GtkWidget* vbox, const char* name, int& data, double value, double lower, double upper)
|
||||
{
|
||||
return addSpinner(vbox, name, value, lower, upper, IntImportCallback(IntImportCaller(data)), IntExportCallback(IntExportCaller(data)));
|
||||
}
|
||||
|
||||
GtkWidget* Dialog::addSpinner(GtkWidget* vbox, const char* name, double value, double lower, double upper, const FloatImportCallback& importViewer, const FloatExportCallback& exportViewer)
|
||||
{
|
||||
DialogSpinnerRow row(DialogSpinnerRow_new(name, value, lower, upper, 10));
|
||||
AddFloatSpinnerData(*row.m_spin, importViewer, exportViewer);
|
||||
DialogVBox_packRow(GTK_VBOX(vbox), row.m_row);
|
||||
return row.m_row;
|
||||
}
|
||||
208
radiant/dialog.h
Normal file
208
radiant/dialog.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
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_DIALOG_H)
|
||||
#define INCLUDED_DIALOG_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "gtkutil/dialog.h"
|
||||
#include "generic/callback.h"
|
||||
#include "string/string.h"
|
||||
|
||||
template<typename Environment, typename FirstArgument, void(*func)(Environment&, FirstArgument)>
|
||||
class ReferenceCaller1;
|
||||
|
||||
inline void BoolImport(bool& self, bool value)
|
||||
{
|
||||
self = value;
|
||||
}
|
||||
typedef ReferenceCaller1<bool, bool, BoolImport> BoolImportCaller;
|
||||
|
||||
inline void BoolExport(bool& self, const BoolImportCallback& importCallback)
|
||||
{
|
||||
importCallback(self);
|
||||
}
|
||||
typedef ReferenceCaller1<bool, const BoolImportCallback&, BoolExport> BoolExportCaller;
|
||||
|
||||
|
||||
inline void IntImport(int& self, int value)
|
||||
{
|
||||
self = value;
|
||||
}
|
||||
typedef ReferenceCaller1<int, int, IntImport> IntImportCaller;
|
||||
|
||||
inline void IntExport(int& self, const IntImportCallback& importCallback)
|
||||
{
|
||||
importCallback(self);
|
||||
}
|
||||
typedef ReferenceCaller1<int, const IntImportCallback&, IntExport> IntExportCaller;
|
||||
|
||||
|
||||
inline void SizeImport(std::size_t& self, std::size_t value)
|
||||
{
|
||||
self = value;
|
||||
}
|
||||
typedef ReferenceCaller1<std::size_t, std::size_t, SizeImport> SizeImportCaller;
|
||||
|
||||
inline void SizeExport(std::size_t& self, const SizeImportCallback& importCallback)
|
||||
{
|
||||
importCallback(self);
|
||||
}
|
||||
typedef ReferenceCaller1<std::size_t, const SizeImportCallback&, SizeExport> SizeExportCaller;
|
||||
|
||||
|
||||
inline void FloatImport(float& self, float value)
|
||||
{
|
||||
self = value;
|
||||
}
|
||||
typedef ReferenceCaller1<float, float, FloatImport> FloatImportCaller;
|
||||
|
||||
inline void FloatExport(float& self, const FloatImportCallback& importCallback)
|
||||
{
|
||||
importCallback(self);
|
||||
}
|
||||
typedef ReferenceCaller1<float, const FloatImportCallback&, FloatExport> FloatExportCaller;
|
||||
|
||||
|
||||
inline void StringImport(CopiedString& self, const char* value)
|
||||
{
|
||||
self = value;
|
||||
}
|
||||
typedef ReferenceCaller1<CopiedString, const char*, StringImport> StringImportCaller;
|
||||
inline void StringExport(CopiedString& self, const StringImportCallback& importCallback)
|
||||
{
|
||||
importCallback(self.c_str());
|
||||
}
|
||||
typedef ReferenceCaller1<CopiedString, const StringImportCallback&, StringExport> StringExportCaller;
|
||||
|
||||
|
||||
struct DLG_DATA
|
||||
{
|
||||
virtual void release() = 0;
|
||||
virtual void importData() const = 0;
|
||||
virtual void exportData() const = 0;
|
||||
};
|
||||
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
typedef struct _GtkToggleButton GtkToggleButton;
|
||||
typedef struct _GtkRadioButton GtkRadioButton;
|
||||
typedef struct _GtkSpinButton GtkSpinButton;
|
||||
typedef struct _GtkComboBox GtkComboBox;
|
||||
typedef struct _GtkEntry GtkEntry;
|
||||
typedef struct _GtkAdjustment GtkAdjustment;
|
||||
|
||||
template<typename FirstArgument>
|
||||
class CallbackDialogData;
|
||||
|
||||
typedef std::list<DLG_DATA*> DialogDataList;
|
||||
|
||||
class Dialog
|
||||
{
|
||||
GtkWindow* m_window;
|
||||
DialogDataList m_data;
|
||||
public:
|
||||
ModalDialog m_modal;
|
||||
GtkWindow* m_parent;
|
||||
|
||||
Dialog();
|
||||
virtual ~Dialog();
|
||||
|
||||
/*!
|
||||
start modal dialog box
|
||||
you need to use AddModalButton to select eIDOK eIDCANCEL buttons
|
||||
*/
|
||||
EMessageBoxReturn DoModal();
|
||||
void EndModal (EMessageBoxReturn code);
|
||||
virtual GtkWindow* BuildDialog() = 0;
|
||||
virtual void exportData();
|
||||
virtual void importData();
|
||||
virtual void PreModal() { };
|
||||
virtual void PostModal (EMessageBoxReturn code) { };
|
||||
virtual void ShowDlg();
|
||||
virtual void HideDlg();
|
||||
void Create();
|
||||
void Destroy();
|
||||
GtkWindow* GetWidget()
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
const GtkWindow* GetWidget() const
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
|
||||
GtkWidget* addCheckBox(GtkWidget* vbox, const char* name, const char* flag, const BoolImportCallback& importCallback, const BoolExportCallback& exportCallback);
|
||||
GtkWidget* addCheckBox(GtkWidget* vbox, const char* name, const char* flag, bool& data);
|
||||
void addCombo(GtkWidget* vbox, const char* name, StringArrayRange values, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void addCombo(GtkWidget* vbox, const char* name, int& data, StringArrayRange values);
|
||||
void addSlider(GtkWidget* vbox, const char* name, int& data, gboolean draw_value, const char* low, const char* high, double value, double lower, double upper, double step_increment, double page_increment, double page_size);
|
||||
void addRadio(GtkWidget* vbox, const char* name, StringArrayRange names, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void addRadio(GtkWidget* vbox, const char* name, int& data, StringArrayRange names);
|
||||
void addRadioIcons(GtkWidget* vbox, const char* name, StringArrayRange icons, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void addRadioIcons(GtkWidget* vbox, const char* name, int& data, StringArrayRange icons);
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, int& data)
|
||||
{
|
||||
return addEntry(vbox, name, IntImportCaller(data), IntExportCaller(data));
|
||||
}
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, const SizeImportCallback& importCallback, const SizeExportCallback& exportCallback);
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, std::size_t& data)
|
||||
{
|
||||
return addEntry(vbox, name, SizeImportCaller(data), SizeExportCaller(data));
|
||||
}
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, const FloatImportCallback& importCallback, const FloatExportCallback& exportCallback);
|
||||
GtkWidget* addEntry(GtkWidget* vbox, const char* name, float& data)
|
||||
{
|
||||
return addEntry(vbox, name, FloatImportCaller(data), FloatExportCaller(data));
|
||||
}
|
||||
GtkWidget* addPathEntry(GtkWidget* vbox, const char* name, bool browse_directory, const StringImportCallback& importCallback, const StringExportCallback& exportCallback);
|
||||
GtkWidget* addPathEntry(GtkWidget* vbox, const char* name, CopiedString& data, bool directory);
|
||||
GtkWidget* addSpinner(GtkWidget* vbox, const char* name, int& data, double value, double lower, double upper);
|
||||
GtkWidget* addSpinner(GtkWidget* vbox, const char* name, double value, double lower, double upper, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
GtkWidget* addSpinner(GtkWidget* vbox, const char* name, double value, double lower, double upper, const FloatImportCallback& importCallback, const FloatExportCallback& exportCallback);
|
||||
|
||||
protected:
|
||||
|
||||
void AddBoolToggleData(GtkToggleButton& object, const BoolImportCallback& importCallback, const BoolExportCallback& exportCallback);
|
||||
void AddIntRadioData(GtkRadioButton& object, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void AddTextEntryData(GtkEntry& object, const StringImportCallback& importCallback, const StringExportCallback& exportCallback);
|
||||
void AddIntEntryData(GtkEntry& object, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void AddSizeEntryData(GtkEntry& object, const SizeImportCallback& importCallback, const SizeExportCallback& exportCallback);
|
||||
void AddFloatEntryData(GtkEntry& object, const FloatImportCallback& importCallback, const FloatExportCallback& exportCallback);
|
||||
void AddFloatSpinnerData(GtkSpinButton& object, const FloatImportCallback& importCallback, const FloatExportCallback& exportCallback);
|
||||
void AddIntSpinnerData(GtkSpinButton& object, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void AddIntAdjustmentData(GtkAdjustment& object, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
void AddIntComboData(GtkComboBox& object, const IntImportCallback& importCallback, const IntExportCallback& exportCallback);
|
||||
|
||||
void AddDialogData(GtkToggleButton& object, bool& data);
|
||||
void AddDialogData(GtkRadioButton& object, int& data);
|
||||
void AddDialogData(GtkEntry& object, CopiedString& data);
|
||||
void AddDialogData(GtkEntry& object, int& data);
|
||||
void AddDialogData(GtkEntry& object, std::size_t& data);
|
||||
void AddDialogData(GtkEntry& object, float& data);
|
||||
void AddDialogData(GtkSpinButton& object, float& data);
|
||||
void AddDialogData(GtkSpinButton& object, int& data);
|
||||
void AddDialogData(GtkAdjustment& object, int& data);
|
||||
void AddDialogData(GtkComboBox& object, int& data);
|
||||
};
|
||||
|
||||
#endif
|
||||
398
radiant/eclass.cpp
Normal file
398
radiant/eclass.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
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 "eclass.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "ifilesystem.h"
|
||||
|
||||
#include "string/string.h"
|
||||
#include "eclasslib.h"
|
||||
#include "os/path.h"
|
||||
#include "os/dir.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "moduleobservers.h"
|
||||
|
||||
#include "cmdlib.h"
|
||||
|
||||
#include "preferences.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef std::map<const char*, EntityClass*, RawStringLessNoCase> EntityClasses;
|
||||
EntityClasses g_entityClasses;
|
||||
EntityClass *eclass_bad = 0;
|
||||
char eclass_directory[1024];
|
||||
typedef std::map<CopiedString, ListAttributeType> ListAttributeTypes;
|
||||
ListAttributeTypes g_listTypes;
|
||||
}
|
||||
|
||||
/*!
|
||||
implementation of the EClass manager API
|
||||
*/
|
||||
|
||||
void CleanEntityList(EntityClasses& entityClasses)
|
||||
{
|
||||
for(EntityClasses::iterator i = entityClasses.begin(); i != entityClasses.end(); ++i)
|
||||
{
|
||||
(*i).second->free((*i).second);
|
||||
}
|
||||
entityClasses.clear();
|
||||
}
|
||||
|
||||
void Eclass_Clear()
|
||||
{
|
||||
CleanEntityList(g_entityClasses);
|
||||
g_listTypes.clear();
|
||||
}
|
||||
|
||||
EntityClass* EClass_InsertSortedList(EntityClasses& entityClasses, EntityClass *entityClass)
|
||||
{
|
||||
std::pair<EntityClasses::iterator, bool> result = entityClasses.insert(EntityClasses::value_type(entityClass->name(), entityClass));
|
||||
if(!result.second)
|
||||
{
|
||||
entityClass->free(entityClass);
|
||||
}
|
||||
return (*result.first).second;
|
||||
}
|
||||
|
||||
EntityClass* Eclass_InsertAlphabetized (EntityClass *e)
|
||||
{
|
||||
return EClass_InsertSortedList(g_entityClasses, e);
|
||||
}
|
||||
|
||||
void Eclass_forEach(EntityClassVisitor& visitor)
|
||||
{
|
||||
for(EntityClasses::iterator i = g_entityClasses.begin(); i != g_entityClasses.end(); ++i)
|
||||
{
|
||||
visitor.visit((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RadiantEclassCollector : public EntityClassCollector
|
||||
{
|
||||
public:
|
||||
void insert(EntityClass* eclass)
|
||||
{
|
||||
Eclass_InsertAlphabetized(eclass);
|
||||
}
|
||||
void insert(const char* name, const ListAttributeType& list)
|
||||
{
|
||||
g_listTypes.insert(ListAttributeTypes::value_type(name, list));
|
||||
}
|
||||
};
|
||||
|
||||
RadiantEclassCollector g_collector;
|
||||
|
||||
const ListAttributeType* EntityClass_findListType(const char* name)
|
||||
{
|
||||
ListAttributeTypes::iterator i = g_listTypes.find(name);
|
||||
if(i != g_listTypes.end())
|
||||
{
|
||||
return &(*i).second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
class EntityClassFilterMode
|
||||
{
|
||||
public:
|
||||
bool filter_mp_sp;
|
||||
const char* mp_ignore_prefix;
|
||||
const char* sp_ignore_prefix;
|
||||
|
||||
EntityClassFilterMode() :
|
||||
filter_mp_sp(!string_empty(g_pGameDescription->getKeyValue("eclass_filter_gamemode"))),
|
||||
mp_ignore_prefix(g_pGameDescription->getKeyValue("eclass_sp_prefix")),
|
||||
sp_ignore_prefix(g_pGameDescription->getKeyValue("eclass_mp_prefix"))
|
||||
{
|
||||
if(string_empty(mp_ignore_prefix))
|
||||
{
|
||||
mp_ignore_prefix = "sp_";
|
||||
}
|
||||
if(string_empty(sp_ignore_prefix))
|
||||
{
|
||||
sp_ignore_prefix = "mp_";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class EntityClassesLoadFile
|
||||
{
|
||||
const char* m_directory;
|
||||
public:
|
||||
EntityClassesLoadFile(const char* directory) : m_directory(directory)
|
||||
{
|
||||
}
|
||||
void operator()(const char* name) const
|
||||
{
|
||||
EntityClassFilterMode filterMode;
|
||||
|
||||
if(filterMode.filter_mp_sp)
|
||||
{
|
||||
if(string_empty(GlobalRadiant().getGameMode()) || string_equal(GlobalRadiant().getGameMode(), "sp"))
|
||||
{
|
||||
if(string_equal_n(name, filterMode.sp_ignore_prefix, strlen(filterMode.sp_ignore_prefix)))
|
||||
{
|
||||
globalOutputStream() << "Ignoring '" << name << "'\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(string_equal_n(name, filterMode.mp_ignore_prefix, strlen(filterMode.mp_ignore_prefix)))
|
||||
{
|
||||
globalOutputStream() << "Ignoring '" << name << "'\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for a given name, we grab the first .def in the vfs
|
||||
// this allows to override baseq3/scripts/entities.def for instance
|
||||
StringOutputStream relPath(256);
|
||||
relPath << m_directory << name;
|
||||
|
||||
GlobalEClassLoader().scanFile(g_collector, relPath.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
struct PathLess
|
||||
{
|
||||
bool operator()(const CopiedString& path, const CopiedString& other) const
|
||||
{
|
||||
return path_less(path.c_str(), other.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<CopiedString, const char*, PathLess> Paths;
|
||||
|
||||
class PathsInsert
|
||||
{
|
||||
Paths& m_paths;
|
||||
const char* m_directory;
|
||||
public:
|
||||
PathsInsert(Paths& paths, const char* directory) : m_paths(paths), m_directory(directory)
|
||||
{
|
||||
}
|
||||
void operator()(const char* name) const
|
||||
{
|
||||
m_paths.insert(Paths::value_type(name, m_directory));
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
void EntityClassQuake3_constructDirectory(const char* directory, const char* extension)
|
||||
{
|
||||
globalOutputStream() << "EntityClass: searching " << makeQuoted(directory) << " for *." << extension << '\n';
|
||||
Directory_forEach(directory, matchFileExtension(extension, EntityClassesLoadFile(directory)));
|
||||
}
|
||||
#else
|
||||
void EntityClassQuake3_constructDirectory(const char* directory, const char* extension, Paths& paths)
|
||||
{
|
||||
globalOutputStream() << "EntityClass: searching " << makeQuoted(directory) << " for *." << extension << '\n';
|
||||
Directory_forEach(directory, matchFileExtension(extension, PathsInsert(paths, directory)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void EntityClassQuake3_Construct()
|
||||
{
|
||||
#if 1
|
||||
StringOutputStream baseDirectory(256);
|
||||
StringOutputStream gameDirectory(256);
|
||||
const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue("basegame");
|
||||
const char* gamename = GlobalRadiant().getGameName();
|
||||
baseDirectory << GlobalRadiant().getGameToolsPath() << basegame << '/';
|
||||
gameDirectory << GlobalRadiant().getGameToolsPath() << gamename << '/';
|
||||
|
||||
Paths paths;
|
||||
EntityClassQuake3_constructDirectory(baseDirectory.c_str(), GlobalEClassLoader().getExtension(), paths);
|
||||
if(!string_equal(basegame, gamename))
|
||||
{
|
||||
EntityClassQuake3_constructDirectory(gameDirectory.c_str(), GlobalEClassLoader().getExtension(), paths);
|
||||
}
|
||||
|
||||
for(Paths::iterator i = paths.begin(); i != paths.end(); ++i)
|
||||
{
|
||||
EntityClassesLoadFile((*i).second)((*i).first.c_str());
|
||||
}
|
||||
#else
|
||||
StringOutputStream directory(256);
|
||||
directory << GlobalRadiant().getGameToolsPath() << GlobalRadiant().getGameName() << '/';
|
||||
EntityClassQuake3_constructDirectory(directory.c_str(), GlobalEClassLoader().getExtension());
|
||||
#endif
|
||||
}
|
||||
|
||||
EntityClass *Eclass_ForName(const char *name, bool has_brushes)
|
||||
{
|
||||
ASSERT_NOTNULL(name);
|
||||
|
||||
if(string_empty(name))
|
||||
{
|
||||
return eclass_bad;
|
||||
}
|
||||
|
||||
EntityClasses::iterator i = g_entityClasses.find(name);
|
||||
if(i != g_entityClasses.end() && string_equal((*i).first, name))
|
||||
{
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
EntityClass* e = EntityClass_Create_Default(name, has_brushes);
|
||||
return Eclass_InsertAlphabetized(e);
|
||||
}
|
||||
|
||||
class EntityClassQuake3 : public ModuleObserver
|
||||
{
|
||||
std::size_t m_unrealised;
|
||||
ModuleObservers m_observers;
|
||||
public:
|
||||
EntityClassQuake3() : m_unrealised(4)
|
||||
{
|
||||
}
|
||||
void realise()
|
||||
{
|
||||
if(--m_unrealised == 0)
|
||||
{
|
||||
//globalOutputStream() << "Entity Classes: realise\n";
|
||||
EntityClassQuake3_Construct();
|
||||
m_observers.realise();
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
if(++m_unrealised == 1)
|
||||
{
|
||||
m_observers.unrealise();
|
||||
//globalOutputStream() << "Entity Classes: unrealise\n";
|
||||
Eclass_Clear();
|
||||
}
|
||||
}
|
||||
void attach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.attach(observer);
|
||||
}
|
||||
void detach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.detach(observer);
|
||||
}
|
||||
};
|
||||
|
||||
EntityClassQuake3 g_EntityClassQuake3;
|
||||
|
||||
void EntityClass_attach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassQuake3.attach(observer);
|
||||
}
|
||||
void EntityClass_detach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassQuake3.detach(observer);
|
||||
}
|
||||
|
||||
void EntityClass_realise()
|
||||
{
|
||||
g_EntityClassQuake3.realise();
|
||||
}
|
||||
void EntityClass_unrealise()
|
||||
{
|
||||
g_EntityClassQuake3.unrealise();
|
||||
}
|
||||
|
||||
void EntityClassQuake3_construct()
|
||||
{
|
||||
// start by creating the default unknown eclass
|
||||
eclass_bad = EClass_Create("UNKNOWN_CLASS", Vector3(0.0f, 0.5f, 0.0f), "");
|
||||
|
||||
EntityClass_realise();
|
||||
}
|
||||
|
||||
void EntityClassQuake3_destroy()
|
||||
{
|
||||
EntityClass_unrealise();
|
||||
|
||||
eclass_bad->free(eclass_bad);
|
||||
}
|
||||
|
||||
class EntityClassQuake3Dependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalFileSystemModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalEClassModuleRef
|
||||
{
|
||||
public:
|
||||
EntityClassQuake3Dependencies() :
|
||||
GlobalEClassModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclasstype"))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class EclassManagerAPI
|
||||
{
|
||||
EntityClassManager m_eclassmanager;
|
||||
public:
|
||||
typedef EntityClassManager Type;
|
||||
STRING_CONSTANT(Name, "quake3");
|
||||
|
||||
EclassManagerAPI()
|
||||
{
|
||||
EntityClassQuake3_construct();
|
||||
|
||||
m_eclassmanager.findOrInsert = &Eclass_ForName;
|
||||
m_eclassmanager.findListType = &EntityClass_findListType;
|
||||
m_eclassmanager.forEach = &Eclass_forEach;
|
||||
m_eclassmanager.attach = &EntityClass_attach;
|
||||
m_eclassmanager.detach = &EntityClass_detach;
|
||||
m_eclassmanager.realise = &EntityClass_realise;
|
||||
m_eclassmanager.unrealise = &EntityClass_unrealise;
|
||||
|
||||
GlobalRadiant().attachGameToolsPathObserver(g_EntityClassQuake3);
|
||||
GlobalRadiant().attachGameModeObserver(g_EntityClassQuake3);
|
||||
GlobalRadiant().attachGameNameObserver(g_EntityClassQuake3);
|
||||
}
|
||||
~EclassManagerAPI()
|
||||
{
|
||||
GlobalRadiant().detachGameNameObserver(g_EntityClassQuake3);
|
||||
GlobalRadiant().detachGameModeObserver(g_EntityClassQuake3);
|
||||
GlobalRadiant().detachGameToolsPathObserver(g_EntityClassQuake3);
|
||||
|
||||
EntityClassQuake3_destroy();
|
||||
}
|
||||
EntityClassManager* getTable()
|
||||
{
|
||||
return &m_eclassmanager;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<EclassManagerAPI, EntityClassQuake3Dependencies> EclassManagerModule;
|
||||
typedef Static<EclassManagerModule> StaticEclassManagerModule;
|
||||
StaticRegisterModule staticRegisterEclassManager(StaticEclassManagerModule::instance());
|
||||
|
||||
|
||||
25
radiant/eclass.h
Normal file
25
radiant/eclass.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
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_ECLASS_H)
|
||||
#define INCLUDED_ECLASS_H
|
||||
|
||||
#endif
|
||||
407
radiant/eclass_def.cpp
Normal file
407
radiant/eclass_def.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
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 "eclass_def.h"
|
||||
|
||||
#include "iscriplib.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "eclasslib.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "stream/textfilestream.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
#include "os/path.h"
|
||||
|
||||
const char* EClass_GetExtension()
|
||||
{
|
||||
return "def";
|
||||
}
|
||||
void Eclass_ScanFile (EntityClassCollector& collector, const char *filename);
|
||||
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class EntityClassDefDependencies : public GlobalShaderCacheModuleRef, public GlobalScripLibModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EclassDefAPI
|
||||
{
|
||||
EntityClassScanner m_eclassdef;
|
||||
public:
|
||||
typedef EntityClassScanner Type;
|
||||
STRING_CONSTANT(Name, "def");
|
||||
|
||||
EclassDefAPI()
|
||||
{
|
||||
m_eclassdef.scanFile = &Eclass_ScanFile;
|
||||
m_eclassdef.getExtension = &EClass_GetExtension;
|
||||
}
|
||||
EntityClassScanner* getTable()
|
||||
{
|
||||
return &m_eclassdef;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EclassDefAPI, EntityClassDefDependencies> EclassDefModule;
|
||||
typedef Static<EclassDefModule> StaticEclassDefModule;
|
||||
StaticRegisterModule staticRegisterEclassDef(StaticEclassDefModule::instance());
|
||||
|
||||
|
||||
#include "string/string.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
char com_token[1024];
|
||||
bool com_eof;
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_Parse
|
||||
|
||||
Parse a token out of a string
|
||||
==============
|
||||
*/
|
||||
const char *COM_Parse (const char *data)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
{
|
||||
if (c == 0)
|
||||
{
|
||||
com_eof = true;
|
||||
return 0; // end of file;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if (c=='/' && data[1] == '/')
|
||||
{
|
||||
while (*data && *data != '\n')
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
|
||||
// handle quoted strings specially
|
||||
if (c == '\"')
|
||||
{
|
||||
data++;
|
||||
do
|
||||
{
|
||||
c = *data++;
|
||||
if (c=='\"')
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
{
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
com_token[len] = c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
break;
|
||||
} while (c>32);
|
||||
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
const char* Get_COM_Token()
|
||||
{
|
||||
return com_token;
|
||||
}
|
||||
|
||||
|
||||
const char *debugname;
|
||||
|
||||
void setSpecialLoad(EntityClass *e, const char* pWhat, CopiedString& p)
|
||||
{
|
||||
// Hydra: removed some amazingly bad cstring usage, whoever wrote that
|
||||
// needs to be taken out and shot.
|
||||
|
||||
char *pText = 0;
|
||||
char *where = 0;
|
||||
|
||||
where = strstr(e->comments(),pWhat);
|
||||
if (!where)
|
||||
return;
|
||||
|
||||
pText = where + strlen(pWhat);
|
||||
if (*pText == '\"')
|
||||
pText++;
|
||||
|
||||
where = strchr(pText,'\"');
|
||||
if (where)
|
||||
{
|
||||
p = CopiedString(pText, where);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pText;
|
||||
}
|
||||
}
|
||||
|
||||
#include "eclasslib.h"
|
||||
|
||||
/*
|
||||
|
||||
the classname, color triple, and bounding box are parsed out of comments
|
||||
A ? size means take the exact brush size.
|
||||
|
||||
/ *QUAKED <classname> (0 0 0) ?
|
||||
/ *QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
|
||||
|
||||
Flag names can follow the size description:
|
||||
|
||||
/ *QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
|
||||
|
||||
*/
|
||||
|
||||
EntityClass *Eclass_InitFromText (const char *text)
|
||||
{
|
||||
EntityClass* e = Eclass_Alloc();
|
||||
e->free = &Eclass_Free;
|
||||
|
||||
// grab the name
|
||||
text = COM_Parse (text);
|
||||
e->m_name = Get_COM_Token();
|
||||
debugname = e->name();
|
||||
|
||||
{
|
||||
// grab the color, reformat as texture name
|
||||
int r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
|
||||
if (r != 3)
|
||||
return e;
|
||||
eclass_capture_state(e);
|
||||
}
|
||||
|
||||
while (*text != ')')
|
||||
{
|
||||
if (!*text) {
|
||||
return 0;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
text++;
|
||||
|
||||
// get the size
|
||||
text = COM_Parse (text);
|
||||
if (Get_COM_Token()[0] == '(')
|
||||
{ // parse the size as two vectors
|
||||
e->fixedsize = true;
|
||||
int r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
|
||||
&e->maxs[0], &e->maxs[1], &e->maxs[2]);
|
||||
if (r != 6) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i=0 ; i<2 ; i++)
|
||||
{
|
||||
while (*text != ')')
|
||||
{
|
||||
if (!*text) {
|
||||
return 0;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
char parms[256];
|
||||
// get the flags
|
||||
{
|
||||
// copy to the first /n
|
||||
char* p = parms;
|
||||
while (*text && *text != '\n')
|
||||
*p++ = *text++;
|
||||
*p = 0;
|
||||
text++;
|
||||
}
|
||||
|
||||
{
|
||||
// any remaining words are parm flags
|
||||
const char* p = parms;
|
||||
for (std::size_t i=0 ; i<MAX_FLAGS ; i++)
|
||||
{
|
||||
p = COM_Parse (p);
|
||||
if (!p)
|
||||
break;
|
||||
strcpy (e->flagnames[i], Get_COM_Token());
|
||||
}
|
||||
}
|
||||
|
||||
e->m_comments = text;
|
||||
|
||||
setSpecialLoad(e, "model=", e->m_modelpath);
|
||||
StringOutputStream buffer(string_length(e->m_modelpath.c_str()));
|
||||
buffer << PathCleaned(e->m_modelpath.c_str());
|
||||
e->m_modelpath = buffer.c_str();
|
||||
|
||||
if(!e->fixedsize)
|
||||
{
|
||||
EntityClass_insertAttribute(*e, "angle", EntityClassAttribute("direction", "Direction", "0"));
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityClass_insertAttribute(*e, "angle", EntityClassAttribute("angle", "Yaw Angle", "0"));
|
||||
}
|
||||
EntityClass_insertAttribute(*e, "model", EntityClassAttribute("model", "Model"));
|
||||
EntityClass_insertAttribute(*e, "noise", EntityClassAttribute("sound", "Sound"));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void Eclass_ScanFile (EntityClassCollector& collector, const char *filename)
|
||||
{
|
||||
EntityClass *e;
|
||||
|
||||
TextFileInputStream inputFile(filename);
|
||||
if(inputFile.failed())
|
||||
{
|
||||
globalErrorStream() << "ScanFile: " << filename << " not found\n";
|
||||
return;
|
||||
}
|
||||
globalOutputStream() << "ScanFile: " << filename << "\n";
|
||||
|
||||
enum EParserState
|
||||
{
|
||||
eParseDefault,
|
||||
eParseSolidus,
|
||||
eParseComment,
|
||||
eParseQuakeED,
|
||||
eParseEntityClass,
|
||||
eParseEntityClassEnd,
|
||||
} state = eParseDefault;
|
||||
const char* quakeEd = "QUAKED";
|
||||
const char* p = 0;
|
||||
StringBuffer buffer;
|
||||
SingleCharacterInputStream<TextFileInputStream> bufferedInput(inputFile);
|
||||
for(;;)
|
||||
{
|
||||
char c;
|
||||
if(!bufferedInput.readChar(c))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case eParseDefault:
|
||||
if(c == '/')
|
||||
{
|
||||
state = eParseSolidus;
|
||||
}
|
||||
break;
|
||||
case eParseSolidus:
|
||||
if(c == '/')
|
||||
{
|
||||
state = eParseComment;
|
||||
}
|
||||
else if(c == '*')
|
||||
{
|
||||
p = quakeEd;
|
||||
state = eParseQuakeED;
|
||||
}
|
||||
break;
|
||||
case eParseComment:
|
||||
if(c == '\n')
|
||||
{
|
||||
state = eParseDefault;
|
||||
}
|
||||
break;
|
||||
case eParseQuakeED:
|
||||
if(c == *p)
|
||||
{
|
||||
if(*(++p) == '\0')
|
||||
{
|
||||
state = eParseEntityClass;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state = eParseDefault;
|
||||
}
|
||||
break;
|
||||
case eParseEntityClass:
|
||||
if(c == '*')
|
||||
{
|
||||
state = eParseEntityClassEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.push_back(c);
|
||||
}
|
||||
break;
|
||||
case eParseEntityClassEnd:
|
||||
if(c == '/')
|
||||
{
|
||||
e = Eclass_InitFromText(buffer.c_str());
|
||||
state = eParseDefault;
|
||||
if (e)
|
||||
collector.insert(e);
|
||||
else
|
||||
globalErrorStream() << "Error parsing: " << debugname << " in " << filename << "\n";
|
||||
|
||||
buffer.clear();
|
||||
state = eParseDefault;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.push_back('*');
|
||||
buffer.push_back(c);
|
||||
state = eParseEntityClass;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
radiant/eclass_def.h
Normal file
25
radiant/eclass_def.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
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_ECLASS_DEF_H)
|
||||
#define INCLUDED_ECLASS_DEF_H
|
||||
|
||||
#endif
|
||||
812
radiant/eclass_doom3.cpp
Normal file
812
radiant/eclass_doom3.cpp
Normal file
@@ -0,0 +1,812 @@
|
||||
/*
|
||||
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 "eclass_doom3.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iscriplib.h"
|
||||
#include "iarchive.h"
|
||||
#include "qerplugin.h"
|
||||
|
||||
#include "generic/callback.h"
|
||||
#include "string/string.h"
|
||||
#include "eclasslib.h"
|
||||
#include "os/path.h"
|
||||
#include "os/dir.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "moduleobservers.h"
|
||||
#include "stringio.h"
|
||||
|
||||
class RawString
|
||||
{
|
||||
const char* m_value;
|
||||
public:
|
||||
RawString(const char* value) : m_value(value)
|
||||
{
|
||||
}
|
||||
const char* c_str() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const RawString& self, const RawString& other)
|
||||
{
|
||||
return string_less_nocase(self.c_str(), other.c_str());
|
||||
}
|
||||
|
||||
typedef std::map<RawString, EntityClass*> EntityClasses;
|
||||
EntityClasses g_EntityClassDoom3_classes;
|
||||
EntityClass *g_EntityClassDoom3_bad = 0;
|
||||
|
||||
|
||||
void EntityClassDoom3_clear()
|
||||
{
|
||||
for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i)
|
||||
{
|
||||
(*i).second->free((*i).second);
|
||||
}
|
||||
g_EntityClassDoom3_classes.clear();
|
||||
}
|
||||
|
||||
// entityClass will be inserted only if another of the same name does not already exist.
|
||||
// if entityClass was inserted, the same object is returned, otherwise the already-existing object is returned.
|
||||
EntityClass* EntityClassDoom3_insertUnique(EntityClass* entityClass)
|
||||
{
|
||||
return (*g_EntityClassDoom3_classes.insert(EntityClasses::value_type(entityClass->name(), entityClass)).first).second;
|
||||
}
|
||||
|
||||
void EntityClassDoom3_forEach(EntityClassVisitor& visitor)
|
||||
{
|
||||
for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i)
|
||||
{
|
||||
visitor.visit((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityClassDoom3_parseUnknown(Tokeniser& tokeniser)
|
||||
{
|
||||
//const char* name =
|
||||
tokeniser.getToken();
|
||||
|
||||
//globalOutputStream() << "parsing unknown block " << makeQuoted(name) << "\n";
|
||||
|
||||
const char* token = tokeniser.getToken();
|
||||
ASSERT_MESSAGE(string_equal(token, "{"), "error parsing entity definition");
|
||||
tokeniser.nextLine();
|
||||
|
||||
std::size_t depth = 1;
|
||||
for(;;)
|
||||
{
|
||||
const char* token = tokeniser.getToken();
|
||||
if(string_equal(token, "}"))
|
||||
{
|
||||
if(--depth == 0)
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(string_equal(token, "{"))
|
||||
{
|
||||
++depth;
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
bool m_resolved;
|
||||
CopiedString m_mesh;
|
||||
CopiedString m_skin;
|
||||
CopiedString m_parent;
|
||||
typedef std::map<CopiedString, CopiedString> Anims;
|
||||
Anims m_anims;
|
||||
Model() : m_resolved(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<CopiedString, Model> Models;
|
||||
|
||||
Models g_models;
|
||||
|
||||
void Model_resolveInheritance(const char* name, Model& model)
|
||||
{
|
||||
if(model.m_resolved == false)
|
||||
{
|
||||
model.m_resolved = true;
|
||||
|
||||
if(!string_empty(model.m_parent.c_str()))
|
||||
{
|
||||
Models::iterator i = g_models.find(model.m_parent);
|
||||
if(i == g_models.end())
|
||||
{
|
||||
globalErrorStream() << "model " << name << " inherits unknown model " << model.m_parent.c_str() << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Model_resolveInheritance((*i).first.c_str(), (*i).second);
|
||||
model.m_mesh = (*i).second.m_mesh;
|
||||
model.m_skin = (*i).second.m_skin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityClassDoom3_parseModel(Tokeniser& tokeniser)
|
||||
{
|
||||
const char* name = tokeniser.getToken();
|
||||
|
||||
Model& model = g_models[name];
|
||||
|
||||
const char* token = tokeniser.getToken();
|
||||
ASSERT_MESSAGE(string_equal(token, "{"), "error parsing model definition");
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* parameter = tokeniser.getToken();
|
||||
if(string_equal(parameter, "}"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
else if(string_equal(parameter, "inherit"))
|
||||
{
|
||||
model.m_parent = tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(parameter, "remove"))
|
||||
{
|
||||
//const char* remove =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(parameter, "mesh"))
|
||||
{
|
||||
model.m_mesh = tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(parameter, "skin"))
|
||||
{
|
||||
model.m_skin = tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(parameter, "offset"))
|
||||
{
|
||||
tokeniser.getToken(); // (
|
||||
tokeniser.getToken();
|
||||
tokeniser.getToken();
|
||||
tokeniser.getToken();
|
||||
tokeniser.getToken(); // )
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
else if(string_equal(parameter, "channel"))
|
||||
{
|
||||
//const char* channelName =
|
||||
tokeniser.getToken();
|
||||
tokeniser.getToken(); // (
|
||||
for(;;)
|
||||
{
|
||||
const char* end = tokeniser.getToken();
|
||||
if(string_equal(end, ")"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(string_equal(parameter, "anim"))
|
||||
{
|
||||
CopiedString animName(tokeniser.getToken());
|
||||
const char* animFile = tokeniser.getToken();
|
||||
model.m_anims.insert(Model::Anims::value_type(animName, animFile));
|
||||
|
||||
const char* token = tokeniser.getToken();
|
||||
|
||||
while(string_equal(token, ","))
|
||||
{
|
||||
animFile = tokeniser.getToken();
|
||||
token = tokeniser.getToken();
|
||||
}
|
||||
|
||||
if(string_equal(token, "{"))
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
const char* end = tokeniser.getToken();
|
||||
if(string_equal(end, "}"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE("unknown model parameter: " << makeQuoted(parameter));
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool char_isSpaceOrTab(char c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
inline bool char_isNotSpaceOrTab(char c)
|
||||
{
|
||||
return !char_isSpaceOrTab(c);
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
inline const char* string_find_if(const char* string, Predicate predicate)
|
||||
{
|
||||
for(; *string != 0; ++string)
|
||||
{
|
||||
if(predicate(*string))
|
||||
{
|
||||
return string;
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
inline const char* string_findFirstSpaceOrTab(const char* string)
|
||||
{
|
||||
return string_find_if(string, char_isSpaceOrTab);
|
||||
}
|
||||
|
||||
inline const char* string_findFirstNonSpaceOrTab(const char* string)
|
||||
{
|
||||
return string_find_if(string, char_isNotSpaceOrTab);
|
||||
}
|
||||
|
||||
|
||||
void EntityClassDoom3_parseEntityDef(Tokeniser& tokeniser)
|
||||
{
|
||||
EntityClass* entityClass = Eclass_Alloc();
|
||||
entityClass->free = &Eclass_Free;
|
||||
|
||||
entityClass->m_name = tokeniser.getToken();
|
||||
|
||||
const char* token = tokeniser.getToken();
|
||||
ASSERT_MESSAGE(string_equal(token, "{"), "error parsing entity definition");
|
||||
tokeniser.nextLine();
|
||||
|
||||
StringOutputStream usage(256);
|
||||
StringOutputStream description(256);
|
||||
CopiedString* currentDescription = 0;
|
||||
StringOutputStream* currentString = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* key = tokeniser.getToken();
|
||||
|
||||
const char* last = string_findFirstSpaceOrTab(key);
|
||||
CopiedString first(key, last);
|
||||
|
||||
if(!string_empty(last))
|
||||
{
|
||||
last = string_findFirstNonSpaceOrTab(last);
|
||||
}
|
||||
|
||||
if(currentString != 0 && string_equal(key, "\\"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
*currentString << " " << tokeniser.getToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(currentDescription != 0)
|
||||
{
|
||||
*currentDescription = description.c_str();
|
||||
description.clear();
|
||||
currentDescription = 0;
|
||||
}
|
||||
currentString = 0;
|
||||
|
||||
if(string_equal(key, "}"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
else if(string_equal(key, "model"))
|
||||
{
|
||||
entityClass->fixedsize = true;
|
||||
StringOutputStream buffer(256);
|
||||
buffer << PathCleaned(tokeniser.getToken());
|
||||
entityClass->m_modelpath = buffer.c_str();
|
||||
}
|
||||
else if(string_equal(key, "editor_color"))
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
if(!string_empty(value))
|
||||
{
|
||||
entityClass->colorSpecified = true;
|
||||
bool success = string_parse_vector3(value, entityClass->color);
|
||||
ASSERT_MESSAGE(success, "editor_color: parse error");
|
||||
}
|
||||
}
|
||||
else if(string_equal(key, "editor_ragdoll"))
|
||||
{
|
||||
//bool ragdoll = atoi(tokeniser.getToken()) != 0;
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(key, "editor_mins"))
|
||||
{
|
||||
entityClass->sizeSpecified = true;
|
||||
const char* value = tokeniser.getToken();
|
||||
if(!string_empty(value) && !string_equal(value, "?"))
|
||||
{
|
||||
entityClass->fixedsize = true;
|
||||
bool success = string_parse_vector3(value, entityClass->mins);
|
||||
ASSERT_MESSAGE(success, "editor_mins: parse error");
|
||||
}
|
||||
}
|
||||
else if(string_equal(key, "editor_maxs"))
|
||||
{
|
||||
entityClass->sizeSpecified = true;
|
||||
const char* value = tokeniser.getToken();
|
||||
if(!string_empty(value) && !string_equal(value, "?"))
|
||||
{
|
||||
entityClass->fixedsize = true;
|
||||
bool success = string_parse_vector3(value, entityClass->maxs);
|
||||
ASSERT_MESSAGE(success, "editor_maxs: parse error");
|
||||
}
|
||||
}
|
||||
else if(string_equal(key, "editor_usage"))
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
usage << value;
|
||||
currentString = &usage;
|
||||
}
|
||||
else if(string_equal_n(key, "editor_usage", 12))
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
usage << "\n" << value;
|
||||
currentString = &usage;
|
||||
}
|
||||
else if(string_equal(key, "editor_rotatable")
|
||||
|| string_equal(key, "editor_showangle")
|
||||
|| string_equal(key, "editor_mover")
|
||||
|| string_equal(key, "editor_model")
|
||||
|| string_equal(key, "editor_material")
|
||||
|| string_equal(key, "editor_combatnode")
|
||||
|| (!string_empty(last) && string_equal(first.c_str(), "editor_gui"))
|
||||
|| string_equal_n(key, "editor_copy", 11))
|
||||
{
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && (string_equal(first.c_str(), "editor_var") || string_equal(first.c_str(), "editor_string")))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "string";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_float"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "string";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_snd"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "sound";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_bool"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "boolean";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_int"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "integer";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_model"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "model";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && string_equal(first.c_str(), "editor_color"))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "color";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(!string_empty(last) && (string_equal(first.c_str(), "editor_material") || string_equal(first.c_str(), "editor_mat")))
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, last).second;
|
||||
attribute.m_type = "shader";
|
||||
currentDescription = &attribute.m_description;
|
||||
currentString = &description;
|
||||
description << tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(key, "inherit"))
|
||||
{
|
||||
entityClass->inheritanceResolved = false;
|
||||
ASSERT_MESSAGE(entityClass->m_parent.empty(), "only one 'inherit' supported per entityDef");
|
||||
entityClass->m_parent.push_back(tokeniser.getToken());
|
||||
}
|
||||
// begin quake4-specific keys
|
||||
else if(string_equal(key, "editor_targetonsel"))
|
||||
{
|
||||
//const char* value =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(key, "editor_menu"))
|
||||
{
|
||||
//const char* value =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
else if(string_equal(key, "editor_ignore"))
|
||||
{
|
||||
//const char* value =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
// end quake4-specific keys
|
||||
else
|
||||
{
|
||||
ASSERT_MESSAGE(!string_equal_n(key, "editor_", 7), "unsupported editor key: " << makeQuoted(key));
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, key).second;
|
||||
attribute.m_type = "string";
|
||||
attribute.m_value = tokeniser.getToken();
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
entityClass->m_comments = usage.c_str();
|
||||
|
||||
if(string_equal(entityClass->m_name.c_str(), "light"))
|
||||
{
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "light_radius").second;
|
||||
attribute.m_type = "vector3";
|
||||
attribute.m_value = "300 300 300";
|
||||
}
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "light_center").second;
|
||||
attribute.m_type = "vector3";
|
||||
}
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "noshadows").second;
|
||||
attribute.m_type = "boolean";
|
||||
attribute.m_value = "0";
|
||||
}
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "nospecular").second;
|
||||
attribute.m_type = "boolean";
|
||||
attribute.m_value = "0";
|
||||
}
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "nodiffuse").second;
|
||||
attribute.m_type = "boolean";
|
||||
attribute.m_value = "0";
|
||||
}
|
||||
{
|
||||
EntityClassAttribute& attribute = EntityClass_insertAttribute(*entityClass, "falloff").second;
|
||||
attribute.m_type = "real";
|
||||
}
|
||||
}
|
||||
|
||||
EntityClass* inserted = EntityClassDoom3_insertUnique(entityClass);
|
||||
if(inserted != entityClass)
|
||||
{
|
||||
globalErrorStream() << "entityDef " << entityClass->name() << " is already defined, second definition ignored\n";
|
||||
eclass_capture_state(entityClass); // finish constructing the entity so that it can be destroyed cleanly.
|
||||
entityClass->free(entityClass);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityClassDoom3_parse(TextInputStream& inputStream)
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(inputStream);
|
||||
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* blockType = tokeniser.getToken();
|
||||
if(blockType == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(string_equal(blockType, "entityDef"))
|
||||
{
|
||||
EntityClassDoom3_parseEntityDef(tokeniser);
|
||||
}
|
||||
else if(string_equal(blockType, "model"))
|
||||
{
|
||||
EntityClassDoom3_parseModel(tokeniser);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityClassDoom3_parseUnknown(tokeniser);
|
||||
}
|
||||
}
|
||||
|
||||
tokeniser.release();
|
||||
}
|
||||
|
||||
|
||||
void EntityClassDoom3_loadFile(const char* filename)
|
||||
{
|
||||
globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n";
|
||||
|
||||
StringOutputStream fullname(256);
|
||||
fullname << "def/" << filename;
|
||||
|
||||
ArchiveTextFile* file = GlobalFileSystem().openTextFile(fullname.c_str());
|
||||
if(file != 0)
|
||||
{
|
||||
EntityClassDoom3_parse(file->getInputStream());
|
||||
file->release();
|
||||
}
|
||||
}
|
||||
|
||||
EntityClass* EntityClassDoom3_findOrInsert(const char *name, bool has_brushes)
|
||||
{
|
||||
ASSERT_NOTNULL(name);
|
||||
|
||||
if(string_empty(name))
|
||||
{
|
||||
return g_EntityClassDoom3_bad;
|
||||
}
|
||||
|
||||
EntityClasses::iterator i = g_EntityClassDoom3_classes.find(name);
|
||||
if(i != g_EntityClassDoom3_classes.end()
|
||||
//&& string_equal((*i).first, name)
|
||||
)
|
||||
{
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
EntityClass* e = EntityClass_Create_Default(name, has_brushes);
|
||||
EntityClass* inserted = EntityClassDoom3_insertUnique(e);
|
||||
ASSERT_MESSAGE(inserted == e, "");
|
||||
return inserted;
|
||||
}
|
||||
|
||||
const ListAttributeType* EntityClassDoom3_findListType(const char* name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void EntityClass_resolveInheritance(EntityClass* derivedClass)
|
||||
{
|
||||
if(derivedClass->inheritanceResolved == false)
|
||||
{
|
||||
derivedClass->inheritanceResolved = true;
|
||||
EntityClasses::iterator i = g_EntityClassDoom3_classes.find(derivedClass->m_parent.front().c_str());
|
||||
if(i == g_EntityClassDoom3_classes.end())
|
||||
{
|
||||
globalErrorStream() << "failed to find entityDef " << makeQuoted(derivedClass->m_parent.front().c_str()) << " inherited by " << makeQuoted(derivedClass->m_name.c_str()) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityClass* parentClass = (*i).second;
|
||||
EntityClass_resolveInheritance(parentClass);
|
||||
if(!derivedClass->colorSpecified)
|
||||
{
|
||||
derivedClass->colorSpecified = parentClass->colorSpecified;
|
||||
derivedClass->color = parentClass->color;
|
||||
}
|
||||
if(!derivedClass->sizeSpecified)
|
||||
{
|
||||
derivedClass->sizeSpecified = parentClass->sizeSpecified;
|
||||
derivedClass->mins = parentClass->mins;
|
||||
derivedClass->maxs = parentClass->maxs;
|
||||
derivedClass->fixedsize = parentClass->fixedsize;
|
||||
}
|
||||
|
||||
for(EntityClassAttributes::iterator j = parentClass->m_attributes.begin(); j != parentClass->m_attributes.end(); ++j)
|
||||
{
|
||||
EntityClass_insertAttribute(*derivedClass, (*j).first.c_str(), (*j).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EntityClassDoom3 : public ModuleObserver
|
||||
{
|
||||
std::size_t m_unrealised;
|
||||
ModuleObservers m_observers;
|
||||
public:
|
||||
EntityClassDoom3() : m_unrealised(2)
|
||||
{
|
||||
}
|
||||
void realise()
|
||||
{
|
||||
if(--m_unrealised == 0)
|
||||
{
|
||||
globalOutputStream() << "searching vfs directory " << makeQuoted("def") << " for *.def\n";
|
||||
GlobalFileSystem().forEachFile("def/", "def", FreeCaller1<const char*, EntityClassDoom3_loadFile>());
|
||||
|
||||
{
|
||||
for(Models::iterator i = g_models.begin(); i != g_models.end(); ++i)
|
||||
{
|
||||
Model_resolveInheritance((*i).first.c_str(), (*i).second);
|
||||
}
|
||||
}
|
||||
{
|
||||
for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i)
|
||||
{
|
||||
EntityClass_resolveInheritance((*i).second);
|
||||
if(!string_empty((*i).second->m_modelpath.c_str()))
|
||||
{
|
||||
Models::iterator j = g_models.find((*i).second->m_modelpath);
|
||||
if(j != g_models.end())
|
||||
{
|
||||
(*i).second->m_modelpath = (*j).second.m_mesh;
|
||||
(*i).second->m_skin = (*j).second.m_skin;
|
||||
}
|
||||
}
|
||||
eclass_capture_state((*i).second);
|
||||
|
||||
StringOutputStream usage(256);
|
||||
|
||||
usage << "-------- KEYS --------\n";
|
||||
|
||||
for(EntityClassAttributes::iterator j = (*i).second->m_attributes.begin(); j != (*i).second->m_attributes.end(); ++j)
|
||||
{
|
||||
const char* name = EntityClassAttributePair_getName(*j);
|
||||
const char* description = EntityClassAttributePair_getDescription(*j);
|
||||
if(!string_equal(name, description))
|
||||
{
|
||||
usage << EntityClassAttributePair_getName(*j) << " : " << EntityClassAttributePair_getDescription(*j) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
(*i).second->m_comments = usage.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
m_observers.realise();
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
if(++m_unrealised == 1)
|
||||
{
|
||||
m_observers.unrealise();
|
||||
EntityClassDoom3_clear();
|
||||
}
|
||||
}
|
||||
void attach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.attach(observer);
|
||||
}
|
||||
void detach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.detach(observer);
|
||||
}
|
||||
};
|
||||
|
||||
EntityClassDoom3 g_EntityClassDoom3;
|
||||
|
||||
void EntityClassDoom3_attach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassDoom3.attach(observer);
|
||||
}
|
||||
void EntityClassDoom3_detach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassDoom3.detach(observer);
|
||||
}
|
||||
|
||||
void EntityClassDoom3_realise()
|
||||
{
|
||||
g_EntityClassDoom3.realise();
|
||||
}
|
||||
void EntityClassDoom3_unrealise()
|
||||
{
|
||||
g_EntityClassDoom3.unrealise();
|
||||
}
|
||||
|
||||
void EntityClassDoom3_construct()
|
||||
{
|
||||
GlobalFileSystem().attach(g_EntityClassDoom3);
|
||||
|
||||
// start by creating the default unknown eclass
|
||||
g_EntityClassDoom3_bad = EClass_Create("UNKNOWN_CLASS", Vector3(0.0f, 0.5f, 0.0f), "");
|
||||
|
||||
EntityClassDoom3_realise();
|
||||
}
|
||||
|
||||
void EntityClassDoom3_destroy()
|
||||
{
|
||||
EntityClassDoom3_unrealise();
|
||||
|
||||
g_EntityClassDoom3_bad->free(g_EntityClassDoom3_bad);
|
||||
|
||||
GlobalFileSystem().detach(g_EntityClassDoom3);
|
||||
}
|
||||
|
||||
class EntityClassDoom3Dependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EntityClassDoom3API
|
||||
{
|
||||
EntityClassManager m_eclassmanager;
|
||||
public:
|
||||
typedef EntityClassManager Type;
|
||||
STRING_CONSTANT(Name, "doom3");
|
||||
|
||||
EntityClassDoom3API()
|
||||
{
|
||||
EntityClassDoom3_construct();
|
||||
|
||||
m_eclassmanager.findOrInsert = &EntityClassDoom3_findOrInsert;
|
||||
m_eclassmanager.findListType = &EntityClassDoom3_findListType;
|
||||
m_eclassmanager.forEach = &EntityClassDoom3_forEach;
|
||||
m_eclassmanager.attach = &EntityClassDoom3_attach;
|
||||
m_eclassmanager.detach = &EntityClassDoom3_detach;
|
||||
m_eclassmanager.realise = &EntityClassDoom3_realise;
|
||||
m_eclassmanager.unrealise = &EntityClassDoom3_unrealise;
|
||||
}
|
||||
~EntityClassDoom3API()
|
||||
{
|
||||
EntityClassDoom3_destroy();
|
||||
}
|
||||
EntityClassManager* getTable()
|
||||
{
|
||||
return &m_eclassmanager;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<EntityClassDoom3API, EntityClassDoom3Dependencies> EntityClassDoom3Module;
|
||||
typedef Static<EntityClassDoom3Module> StaticEntityClassDoom3Module;
|
||||
StaticRegisterModule staticRegisterEntityClassDoom3(StaticEntityClassDoom3Module::instance());
|
||||
25
radiant/eclass_doom3.h
Normal file
25
radiant/eclass_doom3.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_ECLASS_DOOM3_H)
|
||||
#define INCLUDED_ECLASS_DOOM3_H
|
||||
|
||||
#endif
|
||||
807
radiant/eclass_fgd.cpp
Normal file
807
radiant/eclass_fgd.cpp
Normal file
@@ -0,0 +1,807 @@
|
||||
/*
|
||||
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 "eclass_fgd.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "ifilesystem.h"
|
||||
#include "iscriplib.h"
|
||||
#include "qerplugin.h"
|
||||
|
||||
#include "string/string.h"
|
||||
#include "eclasslib.h"
|
||||
#include "os/path.h"
|
||||
#include "os/dir.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "moduleobservers.h"
|
||||
#include "stringio.h"
|
||||
#include "stream/textfilestream.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef std::map<const char*, EntityClass*, RawStringLessNoCase> EntityClasses;
|
||||
EntityClasses g_EntityClassFGD_classes;
|
||||
typedef std::map<const char*, EntityClass*, RawStringLess> BaseClasses;
|
||||
BaseClasses g_EntityClassFGD_bases;
|
||||
EntityClass *g_EntityClassFGD_bad = 0;
|
||||
typedef std::map<CopiedString, ListAttributeType> ListAttributeTypes;
|
||||
ListAttributeTypes g_listTypesFGD;
|
||||
}
|
||||
|
||||
|
||||
void EntityClassFGD_clear()
|
||||
{
|
||||
for(BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i)
|
||||
{
|
||||
(*i).second->free((*i).second);
|
||||
}
|
||||
g_EntityClassFGD_bases.clear();
|
||||
g_listTypesFGD.clear();
|
||||
}
|
||||
|
||||
EntityClass* EntityClassFGD_insertUniqueBase(EntityClass* entityClass)
|
||||
{
|
||||
std::pair<BaseClasses::iterator, bool> result = g_EntityClassFGD_bases.insert(BaseClasses::value_type(entityClass->name(), entityClass));
|
||||
if(!result.second)
|
||||
{
|
||||
globalErrorStream() << "duplicate base class: " << makeQuoted(entityClass->name()) << "\n";
|
||||
//eclass_capture_state(entityClass);
|
||||
//entityClass->free(entityClass);
|
||||
}
|
||||
return (*result.first).second;
|
||||
}
|
||||
|
||||
EntityClass* EntityClassFGD_insertUnique(EntityClass* entityClass)
|
||||
{
|
||||
EntityClassFGD_insertUniqueBase(entityClass);
|
||||
std::pair<EntityClasses::iterator, bool> result = g_EntityClassFGD_classes.insert(EntityClasses::value_type(entityClass->name(), entityClass));
|
||||
if(!result.second)
|
||||
{
|
||||
globalErrorStream() << "duplicate entity class: " << makeQuoted(entityClass->name()) << "\n";
|
||||
eclass_capture_state(entityClass);
|
||||
entityClass->free(entityClass);
|
||||
}
|
||||
return (*result.first).second;
|
||||
}
|
||||
|
||||
void EntityClassFGD_forEach(EntityClassVisitor& visitor)
|
||||
{
|
||||
for(EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); i != g_EntityClassFGD_classes.end(); ++i)
|
||||
{
|
||||
visitor.visit((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool EntityClassFGD_parseToken(Tokeniser& tokeniser, const char* token)
|
||||
{
|
||||
return string_equal(tokeniser.getToken(), token);
|
||||
}
|
||||
|
||||
#define PARSE_ERROR "error parsing entity class definition"
|
||||
|
||||
void EntityClassFGD_parseSplitString(Tokeniser& tokeniser, CopiedString& string)
|
||||
{
|
||||
StringOutputStream buffer(256);
|
||||
for(;;)
|
||||
{
|
||||
buffer << tokeniser.getToken();
|
||||
if(!string_equal(tokeniser.getToken(), "+"))
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
string = buffer.c_str();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityClassFGD_parseClass(Tokeniser& tokeniser, bool fixedsize, bool isBase)
|
||||
{
|
||||
EntityClass* entityClass = Eclass_Alloc();
|
||||
entityClass->free = &Eclass_Free;
|
||||
entityClass->fixedsize = fixedsize;
|
||||
entityClass->inheritanceResolved = false;
|
||||
entityClass->mins = Vector3(-8, -8, -8);
|
||||
entityClass->maxs = Vector3(8, 8, 8);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* property = tokeniser.getToken();
|
||||
if(string_equal(property, "="))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if(string_equal(property, "base"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
for(;;)
|
||||
{
|
||||
const char* base = tokeniser.getToken();
|
||||
if(string_equal(base, ")"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if(!string_equal(base, ","))
|
||||
{
|
||||
entityClass->m_parent.push_back(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(string_equal(property, "size"))
|
||||
{
|
||||
entityClass->sizeSpecified = true;
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
Tokeniser_getFloat(tokeniser, entityClass->mins.x());
|
||||
Tokeniser_getFloat(tokeniser, entityClass->mins.y());
|
||||
Tokeniser_getFloat(tokeniser, entityClass->mins.z());
|
||||
const char* token = tokeniser.getToken();
|
||||
if(string_equal(token, ","))
|
||||
{
|
||||
Tokeniser_getFloat(tokeniser, entityClass->maxs.x());
|
||||
Tokeniser_getFloat(tokeniser, entityClass->maxs.y());
|
||||
Tokeniser_getFloat(tokeniser, entityClass->maxs.z());
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
entityClass->maxs = entityClass->mins;
|
||||
vector3_negate(entityClass->mins);
|
||||
ASSERT_MESSAGE(string_equal(token, ")"), "");
|
||||
}
|
||||
}
|
||||
else if(string_equal(property, "color"))
|
||||
{
|
||||
entityClass->colorSpecified = true;
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
Tokeniser_getFloat(tokeniser, entityClass->color.x());
|
||||
entityClass->color.x() /= 256.0;
|
||||
Tokeniser_getFloat(tokeniser, entityClass->color.y());
|
||||
entityClass->color.y() /= 256.0;
|
||||
Tokeniser_getFloat(tokeniser, entityClass->color.z());
|
||||
entityClass->color.z() /= 256.0;
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else if(string_equal(property, "iconsprite"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
StringOutputStream buffer(256);
|
||||
buffer << PathCleaned(tokeniser.getToken());
|
||||
entityClass->m_modelpath = buffer.c_str();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else if(string_equal(property, "sprite")
|
||||
|| string_equal(property, "decal")
|
||||
// hl2 below
|
||||
|| string_equal(property, "overlay")
|
||||
|| string_equal(property, "light")
|
||||
|| string_equal(property, "keyframe")
|
||||
|| string_equal(property, "animator")
|
||||
|| string_equal(property, "quadbounds"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
// hl2 below
|
||||
else if(string_equal(property, "sphere")
|
||||
|| string_equal(property, "sweptplayerhull")
|
||||
|| string_equal(property, "studio")
|
||||
|| string_equal(property, "studioprop")
|
||||
|| string_equal(property, "lightprop")
|
||||
|| string_equal(property, "lightcone")
|
||||
|| string_equal(property, "sidelist"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
if(string_equal(tokeniser.getToken(), ")"))
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else if(string_equal(property, "line")
|
||||
|| string_equal(property, "cylinder"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
//const char* r =
|
||||
tokeniser.getToken();
|
||||
//const char* g =
|
||||
tokeniser.getToken();
|
||||
//const char* b =
|
||||
tokeniser.getToken();
|
||||
for(;;)
|
||||
{
|
||||
if(string_equal(tokeniser.getToken(), ")"))
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
break;
|
||||
}
|
||||
//const char* name =
|
||||
tokeniser.getToken();
|
||||
}
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else if(string_equal(property, "wirebox"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
//const char* mins =
|
||||
tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ","), PARSE_ERROR);
|
||||
//const char* maxs =
|
||||
tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else if(string_equal(property, "halfgridsnap"))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
entityClass->m_name = tokeniser.getToken();
|
||||
|
||||
if(!isBase)
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR);
|
||||
|
||||
EntityClassFGD_parseSplitString(tokeniser, entityClass->m_comments);
|
||||
}
|
||||
|
||||
tokeniser.nextLine();
|
||||
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR);
|
||||
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
CopiedString key = tokeniser.getToken();
|
||||
if(string_equal(key.c_str(), "]"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
|
||||
if(string_equal_nocase(key.c_str(), "input")
|
||||
|| string_equal_nocase(key.c_str(), "output"))
|
||||
{
|
||||
const char* name = tokeniser.getToken();
|
||||
if(!string_equal(name, "("))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
//const char* type =
|
||||
tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
const char* descriptionSeparator = tokeniser.getToken();
|
||||
if(string_equal(descriptionSeparator, ":"))
|
||||
{
|
||||
CopiedString description;
|
||||
EntityClassFGD_parseSplitString(tokeniser, description);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
CopiedString type = tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
|
||||
if(string_equal_nocase(type.c_str(), "flags"))
|
||||
{
|
||||
EntityClassAttribute attribute;
|
||||
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "="), PARSE_ERROR);
|
||||
tokeniser.nextLine();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR);
|
||||
tokeniser.nextLine();
|
||||
for(;;)
|
||||
{
|
||||
const char* flag = tokeniser.getToken();
|
||||
if(string_equal(flag, "]"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR);
|
||||
//const char* name =
|
||||
tokeniser.getToken();
|
||||
{
|
||||
const char* defaultSeparator = tokeniser.getToken();
|
||||
if(string_equal(defaultSeparator, ":"))
|
||||
{
|
||||
tokeniser.getToken();
|
||||
{
|
||||
const char* descriptionSeparator = tokeniser.getToken();
|
||||
if(string_equal(descriptionSeparator, ":"))
|
||||
{
|
||||
EntityClassFGD_parseSplitString(tokeniser, attribute.m_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
EntityClass_insertAttribute(*entityClass, key.c_str(), attribute);
|
||||
}
|
||||
else if(string_equal_nocase(type.c_str(), "choices"))
|
||||
{
|
||||
EntityClassAttribute attribute;
|
||||
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR);
|
||||
attribute.m_name = tokeniser.getToken();
|
||||
const char* valueSeparator = tokeniser.getToken();
|
||||
if(string_equal(valueSeparator, ":"))
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
if(!string_equal(value, ":"))
|
||||
{
|
||||
attribute.m_value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
{
|
||||
const char* descriptionSeparator = tokeniser.getToken();
|
||||
if(string_equal(descriptionSeparator, ":"))
|
||||
{
|
||||
EntityClassFGD_parseSplitString(tokeniser, attribute.m_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "="), PARSE_ERROR);
|
||||
tokeniser.nextLine();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR);
|
||||
tokeniser.nextLine();
|
||||
|
||||
StringOutputStream listTypeName(64);
|
||||
listTypeName << entityClass->m_name.c_str() << "_" << attribute.m_name.c_str();
|
||||
attribute.m_type = listTypeName.c_str();
|
||||
|
||||
ListAttributeType& listType = g_listTypesFGD[listTypeName.c_str()];
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
if(string_equal(value, "]"))
|
||||
{
|
||||
tokeniser.nextLine();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopiedString tmp(value);
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR);
|
||||
const char* name = tokeniser.getToken();
|
||||
listType.push_back(name, tmp.c_str());
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
for(ListAttributeType::const_iterator i = listType.begin(); i != listType.end(); ++i)
|
||||
{
|
||||
if(string_equal(attribute.m_value.c_str(), (*i).first.c_str()))
|
||||
{
|
||||
attribute.m_value = (*i).second.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
EntityClass_insertAttribute(*entityClass, key.c_str(), attribute);
|
||||
}
|
||||
else if(string_equal_nocase(type.c_str(), "decal"))
|
||||
{
|
||||
}
|
||||
else if(string_equal_nocase(type.c_str(), "string")
|
||||
|| string_equal_nocase(type.c_str(), "integer")
|
||||
|| string_equal_nocase(type.c_str(), "studio")
|
||||
|| string_equal_nocase(type.c_str(), "sprite")
|
||||
|| string_equal_nocase(type.c_str(), "color255")
|
||||
|| string_equal_nocase(type.c_str(), "target_source")
|
||||
|| string_equal_nocase(type.c_str(), "target_destination")
|
||||
|| string_equal_nocase(type.c_str(), "sound")
|
||||
// hl2 below
|
||||
|| string_equal_nocase(type.c_str(), "angle")
|
||||
|| string_equal_nocase(type.c_str(), "origin")
|
||||
|| string_equal_nocase(type.c_str(), "float")
|
||||
|| string_equal_nocase(type.c_str(), "node_dest")
|
||||
|| string_equal_nocase(type.c_str(), "filterclass")
|
||||
|| string_equal_nocase(type.c_str(), "vector")
|
||||
|| string_equal_nocase(type.c_str(), "sidelist")
|
||||
|| string_equal_nocase(type.c_str(), "material")
|
||||
|| string_equal_nocase(type.c_str(), "vecline")
|
||||
|| string_equal_nocase(type.c_str(), "axis")
|
||||
|| string_equal_nocase(type.c_str(), "npcclass")
|
||||
|| string_equal_nocase(type.c_str(), "target_name_or_class")
|
||||
|| string_equal_nocase(type.c_str(), "pointentityclass")
|
||||
|| string_equal_nocase(type.c_str(), "scene"))
|
||||
{
|
||||
if(!string_equal(tokeniser.getToken(), "readonly"))
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR);
|
||||
const char* attributeType = "string";
|
||||
if(string_equal_nocase(type.c_str(), "studio"))
|
||||
{
|
||||
attributeType = "model";
|
||||
}
|
||||
|
||||
EntityClassAttribute attribute;
|
||||
attribute.m_type = attributeType;
|
||||
attribute.m_name = tokeniser.getToken();
|
||||
|
||||
const char* defaultSeparator = tokeniser.getToken();
|
||||
if(string_equal(defaultSeparator, ":"))
|
||||
{
|
||||
const char* value = tokeniser.getToken();
|
||||
if(!string_equal(value, ":"))
|
||||
{
|
||||
attribute.m_value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
|
||||
{
|
||||
const char* descriptionSeparator = tokeniser.getToken();
|
||||
if(string_equal(descriptionSeparator, ":"))
|
||||
{
|
||||
EntityClassFGD_parseSplitString(tokeniser, attribute.m_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tokeniser.ungetToken();
|
||||
}
|
||||
EntityClass_insertAttribute(*entityClass, key.c_str(), attribute);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE("unknown key type: " << makeQuoted(type.c_str()));
|
||||
}
|
||||
tokeniser.nextLine();
|
||||
}
|
||||
|
||||
if(isBase)
|
||||
{
|
||||
EntityClassFGD_insertUniqueBase(entityClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityClassFGD_insertUnique(entityClass);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityClassFGD_loadFile(const char* filename);
|
||||
|
||||
void EntityClassFGD_parse(TextInputStream& inputStream, const char* path)
|
||||
{
|
||||
Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(inputStream);
|
||||
|
||||
tokeniser.nextLine();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
const char* blockType = tokeniser.getToken();
|
||||
if(blockType == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(string_equal(blockType, "@SolidClass"))
|
||||
{
|
||||
EntityClassFGD_parseClass(tokeniser, false, false);
|
||||
}
|
||||
else if(string_equal(blockType, "@BaseClass"))
|
||||
{
|
||||
EntityClassFGD_parseClass(tokeniser, false, true);
|
||||
}
|
||||
else if(string_equal(blockType, "@PointClass")
|
||||
// hl2 below
|
||||
|| string_equal(blockType, "@KeyFrameClass")
|
||||
|| string_equal(blockType, "@MoveClass")
|
||||
|| string_equal(blockType, "@FilterClass")
|
||||
|| string_equal(blockType, "@NPCClass"))
|
||||
{
|
||||
EntityClassFGD_parseClass(tokeniser, true, false);
|
||||
}
|
||||
// hl2 below
|
||||
else if(string_equal(blockType, "@include"))
|
||||
{
|
||||
StringOutputStream includePath(256);
|
||||
includePath << StringRange(path, path_get_filename_start(path));
|
||||
includePath << tokeniser.getToken();
|
||||
EntityClassFGD_loadFile(includePath.c_str());
|
||||
}
|
||||
else if(string_equal(blockType, "@mapsize"))
|
||||
{
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR);
|
||||
//const char* min =
|
||||
tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ","), PARSE_ERROR);
|
||||
//const char* max =
|
||||
tokeniser.getToken();
|
||||
ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE("unknown block type: " << makeQuoted(blockType));
|
||||
}
|
||||
}
|
||||
|
||||
tokeniser.release();
|
||||
}
|
||||
|
||||
|
||||
void EntityClassFGD_loadFile(const char* filename)
|
||||
{
|
||||
TextFileInputStream file(filename);
|
||||
if(!file.failed())
|
||||
{
|
||||
globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n";
|
||||
|
||||
EntityClassFGD_parse(file, filename);
|
||||
}
|
||||
}
|
||||
|
||||
EntityClass* EntityClassFGD_findOrInsert(const char *name, bool has_brushes)
|
||||
{
|
||||
ASSERT_NOTNULL(name);
|
||||
|
||||
if(string_empty(name))
|
||||
{
|
||||
return g_EntityClassFGD_bad;
|
||||
}
|
||||
|
||||
EntityClasses::iterator i = g_EntityClassFGD_classes.find(name);
|
||||
if(i != g_EntityClassFGD_classes.end()
|
||||
//&& string_equal((*i).first, name)
|
||||
)
|
||||
{
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
EntityClass* e = EntityClass_Create_Default(name, has_brushes);
|
||||
return EntityClassFGD_insertUnique(e);
|
||||
}
|
||||
|
||||
const ListAttributeType* EntityClassFGD_findListType(const char *name)
|
||||
{
|
||||
ListAttributeTypes::iterator i = g_listTypesFGD.find(name);
|
||||
if(i != g_listTypesFGD.end())
|
||||
{
|
||||
return &(*i).second;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EntityClassFGD_resolveInheritance(EntityClass* derivedClass)
|
||||
{
|
||||
if(derivedClass->inheritanceResolved == false)
|
||||
{
|
||||
derivedClass->inheritanceResolved = true;
|
||||
for(StringList::iterator j = derivedClass->m_parent.begin(); j != derivedClass->m_parent.end(); ++j)
|
||||
{
|
||||
BaseClasses::iterator i = g_EntityClassFGD_bases.find((*j).c_str());
|
||||
if(i == g_EntityClassFGD_bases.end())
|
||||
{
|
||||
globalErrorStream() << "failed to find entityDef " << makeQuoted((*j).c_str()) << " inherited by " << makeQuoted(derivedClass->m_name.c_str()) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityClass* parentClass = (*i).second;
|
||||
EntityClassFGD_resolveInheritance(parentClass);
|
||||
if(!derivedClass->colorSpecified)
|
||||
{
|
||||
derivedClass->colorSpecified = parentClass->colorSpecified;
|
||||
derivedClass->color = parentClass->color;
|
||||
}
|
||||
if(!derivedClass->sizeSpecified)
|
||||
{
|
||||
derivedClass->sizeSpecified = parentClass->sizeSpecified;
|
||||
derivedClass->mins = parentClass->mins;
|
||||
derivedClass->maxs = parentClass->maxs;
|
||||
}
|
||||
|
||||
for(EntityClassAttributes::iterator k = parentClass->m_attributes.begin(); k != parentClass->m_attributes.end(); ++k)
|
||||
{
|
||||
EntityClass_insertAttribute(*derivedClass, (*k).first.c_str(), (*k).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EntityClassFGD : public ModuleObserver
|
||||
{
|
||||
std::size_t m_unrealised;
|
||||
ModuleObservers m_observers;
|
||||
public:
|
||||
EntityClassFGD() : m_unrealised(3)
|
||||
{
|
||||
}
|
||||
void realise()
|
||||
{
|
||||
if(--m_unrealised == 0)
|
||||
{
|
||||
StringOutputStream filename(256);
|
||||
filename << GlobalRadiant().getGameToolsPath() << GlobalRadiant().getGameName() << "/halflife.fgd";
|
||||
EntityClassFGD_loadFile(filename.c_str());
|
||||
|
||||
{
|
||||
for(EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); i != g_EntityClassFGD_classes.end(); ++i)
|
||||
{
|
||||
EntityClassFGD_resolveInheritance((*i).second);
|
||||
if((*i).second->fixedsize && string_empty((*i).second->m_modelpath.c_str()))
|
||||
{
|
||||
if(!(*i).second->sizeSpecified)
|
||||
{
|
||||
globalErrorStream() << "size not specified for entity class: " << makeQuoted((*i).second->m_name.c_str()) << '\n';
|
||||
}
|
||||
if(!(*i).second->colorSpecified)
|
||||
{
|
||||
globalErrorStream() << "color not specified for entity class: " << makeQuoted((*i).second->m_name.c_str()) << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
for(BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i)
|
||||
{
|
||||
eclass_capture_state((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
m_observers.realise();
|
||||
}
|
||||
}
|
||||
void unrealise()
|
||||
{
|
||||
if(++m_unrealised == 1)
|
||||
{
|
||||
m_observers.unrealise();
|
||||
EntityClassFGD_clear();
|
||||
}
|
||||
}
|
||||
void attach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.attach(observer);
|
||||
}
|
||||
void detach(ModuleObserver& observer)
|
||||
{
|
||||
m_observers.detach(observer);
|
||||
}
|
||||
};
|
||||
|
||||
EntityClassFGD g_EntityClassFGD;
|
||||
|
||||
void EntityClassFGD_attach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassFGD.attach(observer);
|
||||
}
|
||||
void EntityClassFGD_detach(ModuleObserver& observer)
|
||||
{
|
||||
g_EntityClassFGD.detach(observer);
|
||||
}
|
||||
|
||||
void EntityClassFGD_realise()
|
||||
{
|
||||
g_EntityClassFGD.realise();
|
||||
}
|
||||
void EntityClassFGD_unrealise()
|
||||
{
|
||||
g_EntityClassFGD.unrealise();
|
||||
}
|
||||
|
||||
void EntityClassFGD_construct()
|
||||
{
|
||||
// start by creating the default unknown eclass
|
||||
g_EntityClassFGD_bad = EClass_Create("UNKNOWN_CLASS", Vector3(0.0f, 0.5f, 0.0f), "");
|
||||
|
||||
EntityClassFGD_realise();
|
||||
}
|
||||
|
||||
void EntityClassFGD_destroy()
|
||||
{
|
||||
EntityClassFGD_unrealise();
|
||||
|
||||
g_EntityClassFGD_bad->free(g_EntityClassFGD_bad);
|
||||
}
|
||||
|
||||
class EntityClassFGDDependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef, public GlobalRadiantModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EntityClassFGDAPI
|
||||
{
|
||||
EntityClassManager m_eclassmanager;
|
||||
public:
|
||||
typedef EntityClassManager Type;
|
||||
STRING_CONSTANT(Name, "halflife");
|
||||
|
||||
EntityClassFGDAPI()
|
||||
{
|
||||
EntityClassFGD_construct();
|
||||
|
||||
m_eclassmanager.findOrInsert = &EntityClassFGD_findOrInsert;
|
||||
m_eclassmanager.findListType = &EntityClassFGD_findListType;
|
||||
m_eclassmanager.forEach = &EntityClassFGD_forEach;
|
||||
m_eclassmanager.attach = &EntityClassFGD_attach;
|
||||
m_eclassmanager.detach = &EntityClassFGD_detach;
|
||||
m_eclassmanager.realise = &EntityClassFGD_realise;
|
||||
m_eclassmanager.unrealise = &EntityClassFGD_unrealise;
|
||||
|
||||
GlobalRadiant().attachGameToolsPathObserver(g_EntityClassFGD);
|
||||
GlobalRadiant().attachGameNameObserver(g_EntityClassFGD);
|
||||
}
|
||||
~EntityClassFGDAPI()
|
||||
{
|
||||
GlobalRadiant().detachGameNameObserver(g_EntityClassFGD);
|
||||
GlobalRadiant().detachGameToolsPathObserver(g_EntityClassFGD);
|
||||
|
||||
EntityClassFGD_destroy();
|
||||
}
|
||||
EntityClassManager* getTable()
|
||||
{
|
||||
return &m_eclassmanager;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<EntityClassFGDAPI, EntityClassFGDDependencies> EntityClassFGDModule;
|
||||
typedef Static<EntityClassFGDModule> StaticEntityClassFGDModule;
|
||||
StaticRegisterModule staticRegisterEntityClassFGD(StaticEntityClassFGDModule::instance());
|
||||
25
radiant/eclass_fgd.h
Normal file
25
radiant/eclass_fgd.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_ECLASS_FGD_H)
|
||||
#define INCLUDED_ECLASS_FGD_H
|
||||
|
||||
#endif
|
||||
524
radiant/eclass_xml.cpp
Normal file
524
radiant/eclass_xml.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
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 "eclass_xml.h"
|
||||
|
||||
#include "ieclass.h"
|
||||
#include "irender.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "xml/xmlparser.h"
|
||||
#include "generic/object.h"
|
||||
#include "generic/reference.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "stream/textfilestream.h"
|
||||
#include "os/path.h"
|
||||
#include "eclasslib.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#define PARSE_ERROR(elementName, name) makeQuoted(elementName) << " is not a valid child of " << makeQuoted(name)
|
||||
|
||||
class IgnoreBreaks
|
||||
{
|
||||
public:
|
||||
const char* m_first;
|
||||
const char* m_last;
|
||||
IgnoreBreaks(const char* first, const char* last) : m_first(first), m_last(last)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TextOutputStreamType>
|
||||
TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const IgnoreBreaks& ignoreBreaks)
|
||||
{
|
||||
for(const char* i = ignoreBreaks.m_first; i != ignoreBreaks.m_last; ++i)
|
||||
{
|
||||
if(*i != '\n')
|
||||
{
|
||||
ostream << *i;
|
||||
}
|
||||
}
|
||||
return ostream;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class TreeXMLImporter : public TextOutputStream
|
||||
{
|
||||
public:
|
||||
virtual TreeXMLImporter& pushElement(const XMLElement& element) = 0;
|
||||
virtual void popElement(const char* name) = 0;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class Storage
|
||||
{
|
||||
char m_storage[sizeof(Type)];
|
||||
public:
|
||||
Type& get()
|
||||
{
|
||||
return *reinterpret_cast<Type*>(m_storage);
|
||||
}
|
||||
const Type& get() const
|
||||
{
|
||||
return *reinterpret_cast<const Type*>(m_storage);
|
||||
}
|
||||
};
|
||||
|
||||
class BreakImporter : public TreeXMLImporter
|
||||
{
|
||||
public:
|
||||
BreakImporter(StringOutputStream& comment)
|
||||
{
|
||||
comment << '\n';
|
||||
}
|
||||
static const char* name()
|
||||
{
|
||||
return "n";
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), name()));
|
||||
return *this;
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, name()));
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
class AttributeImporter : public TreeXMLImporter
|
||||
{
|
||||
StringOutputStream& m_comment;
|
||||
|
||||
public:
|
||||
AttributeImporter(StringOutputStream& comment, EntityClass* entityClass, const XMLElement& element) : m_comment(comment)
|
||||
{
|
||||
const char* type = element.name();
|
||||
const char* key = element.attribute("key");
|
||||
const char* name = element.attribute("name");
|
||||
const char* value = element.attribute("value");
|
||||
|
||||
ASSERT_MESSAGE(!string_empty(key), "key attribute not specified");
|
||||
ASSERT_MESSAGE(!string_empty(name), "name attribute not specified");
|
||||
|
||||
if(string_equal(type, "flag"))
|
||||
{
|
||||
std::size_t bit = atoi(element.attribute("bit"));
|
||||
ASSERT_MESSAGE(bit < MAX_FLAGS, "invalid flag bit");
|
||||
ASSERT_MESSAGE(string_empty(entityClass->flagnames[bit]), "non-unique flag bit");
|
||||
strcpy(entityClass->flagnames[bit], key);
|
||||
}
|
||||
|
||||
m_comment << key;
|
||||
m_comment << " : ";
|
||||
|
||||
EntityClass_insertAttribute(*entityClass, key, EntityClassAttribute(type, name, value));
|
||||
}
|
||||
~AttributeImporter()
|
||||
{
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), "attribute"));
|
||||
return *this;
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, "attribute"));
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return m_comment.write(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
bool attributeSupported(const char* name)
|
||||
{
|
||||
return string_equal(name, "real")
|
||||
|| string_equal(name, "integer")
|
||||
|| string_equal(name, "boolean")
|
||||
|| string_equal(name, "string")
|
||||
|| string_equal(name, "array")
|
||||
|| string_equal(name, "flag")
|
||||
|| string_equal(name, "real3")
|
||||
|| string_equal(name, "integer3")
|
||||
|| string_equal(name, "direction")
|
||||
|| string_equal(name, "angle")
|
||||
|| string_equal(name, "angles")
|
||||
|| string_equal(name, "color")
|
||||
|| string_equal(name, "target")
|
||||
|| string_equal(name, "targetname")
|
||||
|| string_equal(name, "sound")
|
||||
|| string_equal(name, "texture")
|
||||
|| string_equal(name, "model")
|
||||
|| string_equal(name, "skin")
|
||||
|| string_equal(name, "integer2");
|
||||
}
|
||||
|
||||
typedef std::map<CopiedString, ListAttributeType> ListAttributeTypes;
|
||||
|
||||
bool listAttributeSupported(ListAttributeTypes& listTypes, const char* name)
|
||||
{
|
||||
return listTypes.find(name) != listTypes.end();
|
||||
}
|
||||
|
||||
|
||||
class ClassImporter : public TreeXMLImporter
|
||||
{
|
||||
EntityClassCollector& m_collector;
|
||||
EntityClass* m_eclass;
|
||||
StringOutputStream m_comment;
|
||||
Storage<AttributeImporter> m_attribute;
|
||||
ListAttributeTypes& m_listTypes;
|
||||
|
||||
public:
|
||||
ClassImporter(EntityClassCollector& collector, ListAttributeTypes& listTypes, const XMLElement& element) : m_collector(collector), m_listTypes(listTypes)
|
||||
{
|
||||
m_eclass = Eclass_Alloc();
|
||||
m_eclass->free = &Eclass_Free;
|
||||
|
||||
const char* name = element.attribute("name");
|
||||
ASSERT_MESSAGE(!string_empty(name), "name attribute not specified for class");
|
||||
m_eclass->m_name = name;
|
||||
|
||||
const char* color = element.attribute("color");
|
||||
ASSERT_MESSAGE(!string_empty(name), "color attribute not specified for class " << name);
|
||||
string_parse_vector3(color, m_eclass->color);
|
||||
eclass_capture_state(m_eclass);
|
||||
|
||||
const char* model = element.attribute("model");
|
||||
if(!string_empty(model))
|
||||
{
|
||||
StringOutputStream buffer(256);
|
||||
buffer << PathCleaned(model);
|
||||
m_eclass->m_modelpath = buffer.c_str();
|
||||
}
|
||||
|
||||
const char* type = element.name();
|
||||
if(string_equal(type, "point"))
|
||||
{
|
||||
const char* box = element.attribute("box");
|
||||
ASSERT_MESSAGE(!string_empty(box), "box attribute not found for class " << name);
|
||||
m_eclass->fixedsize = true;
|
||||
string_parse_vector(box, &m_eclass->mins.x(), &m_eclass->mins.x() + 6);
|
||||
}
|
||||
}
|
||||
~ClassImporter()
|
||||
{
|
||||
m_eclass->m_comments = m_comment.c_str();
|
||||
m_collector.insert(m_eclass);
|
||||
|
||||
for(ListAttributeTypes::iterator i = m_listTypes.begin(); i != m_listTypes.end(); ++i)
|
||||
{
|
||||
m_collector.insert((*i).first.c_str(), (*i).second);
|
||||
}
|
||||
}
|
||||
static const char* name()
|
||||
{
|
||||
return "class";
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
if(attributeSupported(element.name()) || listAttributeSupported(m_listTypes, element.name()))
|
||||
{
|
||||
constructor(m_attribute.get(), makeReference(m_comment), m_eclass, element);
|
||||
return m_attribute.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), name()));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
if(attributeSupported(elementName) || listAttributeSupported(m_listTypes, elementName))
|
||||
{
|
||||
destructor(m_attribute.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, name()));
|
||||
}
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return m_comment.write(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
class ItemImporter : public TreeXMLImporter
|
||||
{
|
||||
public:
|
||||
ItemImporter(ListAttributeType& list, const XMLElement& element)
|
||||
{
|
||||
const char* name = element.attribute("name");
|
||||
const char* value = element.attribute("value");
|
||||
list.push_back(name, value);
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), "item"));
|
||||
return *this;
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, "item"));
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
bool isItem(const char* name)
|
||||
{
|
||||
return string_equal(name, "item");
|
||||
}
|
||||
|
||||
class ListAttributeImporter : public TreeXMLImporter
|
||||
{
|
||||
ListAttributeType* m_listType;
|
||||
Storage<ItemImporter> m_item;
|
||||
public:
|
||||
ListAttributeImporter(ListAttributeTypes& listTypes, const XMLElement& element)
|
||||
{
|
||||
const char* name = element.attribute("name");
|
||||
m_listType = &listTypes[name];
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
if(isItem(element.name()))
|
||||
{
|
||||
constructor(m_item.get(), makeReference(*m_listType), element);
|
||||
return m_item.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), "list"));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
if(isItem(elementName))
|
||||
{
|
||||
destructor(m_item.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, "list"));
|
||||
}
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
bool classSupported(const char* name)
|
||||
{
|
||||
return string_equal(name, "group")
|
||||
|| string_equal(name, "point");
|
||||
}
|
||||
|
||||
bool listSupported(const char* name)
|
||||
{
|
||||
return string_equal(name, "list");
|
||||
}
|
||||
|
||||
class ClassesImporter : public TreeXMLImporter
|
||||
{
|
||||
EntityClassCollector& m_collector;
|
||||
Storage<ClassImporter> m_class;
|
||||
Storage<ListAttributeImporter> m_list;
|
||||
ListAttributeTypes m_listTypes;
|
||||
|
||||
public:
|
||||
ClassesImporter(EntityClassCollector& collector) : m_collector(collector)
|
||||
{
|
||||
}
|
||||
static const char* name()
|
||||
{
|
||||
return "classes";
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
if(classSupported(element.name()))
|
||||
{
|
||||
constructor(m_class.get(), makeReference(m_collector), makeReference(m_listTypes), element);
|
||||
return m_class.get();
|
||||
}
|
||||
else if(listSupported(element.name()))
|
||||
{
|
||||
constructor(m_list.get(), makeReference(m_listTypes), element);
|
||||
return m_list.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), name()));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
if(classSupported(elementName))
|
||||
{
|
||||
destructor(m_class.get());
|
||||
}
|
||||
else if(listSupported(elementName))
|
||||
{
|
||||
destructor(m_list.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, name()));
|
||||
}
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
class EclassXMLImporter : public TreeXMLImporter
|
||||
{
|
||||
EntityClassCollector& m_collector;
|
||||
Storage<ClassesImporter> m_classes;
|
||||
|
||||
public:
|
||||
EclassXMLImporter(EntityClassCollector& collector) : m_collector(collector)
|
||||
{
|
||||
}
|
||||
static const char* name()
|
||||
{
|
||||
return "classes";
|
||||
}
|
||||
TreeXMLImporter& pushElement(const XMLElement& element)
|
||||
{
|
||||
if(string_equal(element.name(), ClassesImporter::name()))
|
||||
{
|
||||
constructor(m_classes.get(), makeReference(m_collector));
|
||||
return m_classes.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(element.name(), name()));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
void popElement(const char* elementName)
|
||||
{
|
||||
if(string_equal(elementName, ClassesImporter::name()))
|
||||
{
|
||||
destructor(m_classes.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_MESSAGE(PARSE_ERROR(elementName, name()));
|
||||
}
|
||||
}
|
||||
std::size_t write(const char* data, std::size_t length)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
class TreeXMLImporterStack : public XMLImporter
|
||||
{
|
||||
std::vector< Reference<TreeXMLImporter> > m_importers;
|
||||
public:
|
||||
TreeXMLImporterStack(TreeXMLImporter& importer)
|
||||
{
|
||||
m_importers.push_back(makeReference(importer));
|
||||
}
|
||||
void pushElement(const XMLElement& element)
|
||||
{
|
||||
m_importers.push_back(makeReference(m_importers.back().get().pushElement(element)));
|
||||
}
|
||||
void popElement(const char* name)
|
||||
{
|
||||
m_importers.pop_back();
|
||||
m_importers.back().get().popElement(name);
|
||||
}
|
||||
std::size_t write(const char* buffer, std::size_t length)
|
||||
{
|
||||
return m_importers.back().get().write(buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const char* GetExtension()
|
||||
{
|
||||
return "ent";
|
||||
}
|
||||
void ScanFile(EntityClassCollector& collector, const char *filename)
|
||||
{
|
||||
TextFileInputStream inputFile(filename);
|
||||
if(!inputFile.failed())
|
||||
{
|
||||
XMLStreamParser parser(inputFile);
|
||||
|
||||
EclassXMLImporter importer(collector);
|
||||
TreeXMLImporterStack stack(importer);
|
||||
parser.exportXML(stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class EntityClassXMLDependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EclassXMLAPI
|
||||
{
|
||||
EntityClassScanner m_eclassxml;
|
||||
public:
|
||||
typedef EntityClassScanner Type;
|
||||
STRING_CONSTANT(Name, "xml");
|
||||
|
||||
EclassXMLAPI()
|
||||
{
|
||||
m_eclassxml.scanFile = &ScanFile;
|
||||
m_eclassxml.getExtension = &GetExtension;
|
||||
}
|
||||
EntityClassScanner* getTable()
|
||||
{
|
||||
return &m_eclassxml;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EclassXMLAPI, EntityClassXMLDependencies> EclassXMLModule;
|
||||
typedef Static<EclassXMLModule> StaticEclassXMLModule;
|
||||
StaticRegisterModule staticRegisterEclassXML(StaticEclassXMLModule::instance());
|
||||
25
radiant/eclass_xml.h
Normal file
25
radiant/eclass_xml.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_ECLASS_XML_H)
|
||||
#define INCLUDED_ECLASS_XML_H
|
||||
|
||||
#endif
|
||||
438
radiant/entity.cpp
Normal file
438
radiant/entity.cpp
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
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 "entity.h"
|
||||
|
||||
#include "ientity.h"
|
||||
#include "iselection.h"
|
||||
#include "imodel.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iundo.h"
|
||||
#include "editable.h"
|
||||
|
||||
#include "eclasslib.h"
|
||||
#include "scenelib.h"
|
||||
#include "os/path.h"
|
||||
#include "os/file.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "gtkutil/filechooser.h"
|
||||
#include "gtkmisc.h"
|
||||
#include "select.h"
|
||||
#include "map.h"
|
||||
#include "preferences.h"
|
||||
#include "gtkdlgs.h"
|
||||
#include "mainframe.h"
|
||||
#include "qe3.h"
|
||||
#include "commands.h"
|
||||
|
||||
struct entity_globals_t
|
||||
{
|
||||
Vector3 color_entity;
|
||||
|
||||
entity_globals_t() :
|
||||
color_entity(0.0f, 0.0f, 0.0f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
entity_globals_t g_entity_globals;
|
||||
|
||||
class EntitySetKeyValueSelected : public scene::Graph::Walker
|
||||
{
|
||||
const char* m_key;
|
||||
const char* m_value;
|
||||
public:
|
||||
EntitySetKeyValueSelected(const char* key, const char* value)
|
||||
: m_key(key), m_value(value)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void post(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
Entity* entity = Node_getEntity(path.top());
|
||||
if(entity != 0
|
||||
&& (instance.childSelected() || Instance_getSelectable(instance)->isSelected()))
|
||||
{
|
||||
entity->setKeyValue(m_key, m_value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class EntitySetClassnameSelected : public scene::Graph::Walker
|
||||
{
|
||||
const char* m_classname;
|
||||
public:
|
||||
EntitySetClassnameSelected(const char* classname)
|
||||
: m_classname(classname)
|
||||
{
|
||||
}
|
||||
bool pre(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void post(const scene::Path& path, scene::Instance& instance) const
|
||||
{
|
||||
Entity* entity = Node_getEntity(path.top());
|
||||
if(entity != 0
|
||||
&& (instance.childSelected() || Instance_getSelectable(instance)->isSelected()))
|
||||
{
|
||||
NodeSmartReference node(GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert(m_classname, node_is_group(path.top()))));
|
||||
|
||||
EntityCopyingVisitor visitor(*Node_getEntity(node));
|
||||
|
||||
entity->forEachKeyValue(visitor);
|
||||
|
||||
NodeSmartReference child(path.top().get());
|
||||
NodeSmartReference parent(path.parent().get());
|
||||
Node_getTraversable(parent)->erase(child);
|
||||
if(Node_getTraversable(child) != 0
|
||||
&& Node_getTraversable(node) != 0
|
||||
&& node_is_group(node))
|
||||
{
|
||||
parentBrushes(child, node);
|
||||
}
|
||||
Node_getTraversable(parent)->insert(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Scene_EntitySetKeyValue_Selected(const char* key, const char* value)
|
||||
{
|
||||
GlobalSceneGraph().traverse(EntitySetKeyValueSelected(key, value));
|
||||
}
|
||||
|
||||
void Scene_EntitySetClassname_Selected(const char* classname)
|
||||
{
|
||||
GlobalSceneGraph().traverse(EntitySetClassnameSelected(classname));
|
||||
}
|
||||
|
||||
|
||||
class EntityUngroupVisitor : public SelectionSystem::Visitor
|
||||
{
|
||||
const scene::Path& m_parent;
|
||||
public:
|
||||
EntityUngroupVisitor(const scene::Path& parent) : m_parent(parent)
|
||||
{
|
||||
}
|
||||
void visit(scene::Instance& instance) const
|
||||
{
|
||||
if(Node_getEntity(instance.path().top()) != 0
|
||||
&& node_is_group(instance.path().top()))
|
||||
{
|
||||
if(m_parent.top().get_pointer() != instance.path().top().get_pointer())
|
||||
{
|
||||
parentBrushes(instance.path().top(), m_parent.top());
|
||||
Path_deleteTop(instance.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Entity_ungroupSelected()
|
||||
{
|
||||
UndoableCommand undo("ungroupSelectedEntities");
|
||||
|
||||
scene::Path world_path(makeReference(GlobalSceneGraph().root()));
|
||||
world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map)));
|
||||
|
||||
GlobalSelectionSystem().foreachSelected(EntityUngroupVisitor(world_path));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Entity_connectSelected()
|
||||
{
|
||||
if(GlobalSelectionSystem().countSelected() == 2)
|
||||
{
|
||||
GlobalEntityCreator().connectEntities(
|
||||
GlobalSelectionSystem().penultimateSelected().path(),
|
||||
GlobalSelectionSystem().ultimateSelected().path()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
globalErrorStream() << "entityConnectSelected: exactly two instances must be selected\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int g_iLastLightIntensity;
|
||||
|
||||
void Entity_createFromSelection(const char* name, const Vector3& origin)
|
||||
{
|
||||
#if 0
|
||||
if(string_equal_nocase(name, "worldspawn"))
|
||||
{
|
||||
gtk_MessageBox(GTK_WIDGET(MainFrame_getWindow()), "Can't create an entity with worldspawn.", "info");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
EntityClass* entityClass = GlobalEntityClassManager().findOrInsert(name, true);
|
||||
|
||||
bool isModel = string_equal_nocase(name, "misc_model")
|
||||
|| string_equal_nocase(name, "misc_gamemodel")
|
||||
|| string_equal_nocase(name, "model_static")
|
||||
|| (GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase(name, "func_static"));
|
||||
|
||||
if(!(entityClass->fixedsize || isModel) && Scene_countSelectedBrushes(GlobalSceneGraph()) == 0)
|
||||
{
|
||||
globalErrorStream() << "failed to create a group entity - no brushes are selected\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
NodeSmartReference node(GlobalEntityCreator().createEntity(entityClass));
|
||||
|
||||
Node_getTraversable(GlobalSceneGraph().root())->insert(node);
|
||||
|
||||
scene::Path entitypath(makeReference(GlobalSceneGraph().root()));
|
||||
entitypath.push(makeReference(node.get()));
|
||||
scene::Instance& instance = findInstance(entitypath);
|
||||
|
||||
if(entityClass->fixedsize)
|
||||
{
|
||||
Select_Delete();
|
||||
|
||||
Transformable* transform = Instance_getTransformable(instance);
|
||||
if(transform != 0)
|
||||
{
|
||||
transform->setType(TRANSFORM_PRIMITIVE);
|
||||
transform->setTranslation(origin);
|
||||
transform->freezeTransform();
|
||||
}
|
||||
|
||||
GlobalSelectionSystem().setSelectedAll(false);
|
||||
|
||||
Instance_setSelected(instance, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Scene_parentSelectedBrushesToEntity(GlobalSceneGraph(), node);
|
||||
Scene_forEachChildSelectable(SelectableSetSelected(true), instance.path());
|
||||
}
|
||||
|
||||
// tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box
|
||||
// see SF bug 105383
|
||||
|
||||
if (g_pGameDescription->mGameType == "hl")
|
||||
{
|
||||
// FIXME - Hydra: really we need a combined light AND color dialog for halflife.
|
||||
if (string_equal_nocase(name, "light")
|
||||
|| string_equal_nocase(name, "light_environment")
|
||||
|| string_equal_nocase(name, "light_spot"))
|
||||
{
|
||||
int intensity = g_iLastLightIntensity;
|
||||
|
||||
if (DoLightIntensityDlg (&intensity) == eIDOK)
|
||||
{
|
||||
g_iLastLightIntensity = intensity;
|
||||
char buf[30];
|
||||
sprintf( buf, "255 255 255 %d", intensity );
|
||||
Node_getEntity(node)->setKeyValue("_light", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(g_pGameDescription->mGameType != "doom3" && string_equal_nocase(name, "light"))
|
||||
{
|
||||
int intensity = g_iLastLightIntensity;
|
||||
|
||||
if (DoLightIntensityDlg (&intensity) == eIDOK)
|
||||
{
|
||||
g_iLastLightIntensity = intensity;
|
||||
char buf[10];
|
||||
sprintf( buf, "%d", intensity );
|
||||
Node_getEntity(node)->setKeyValue("light", buf);
|
||||
}
|
||||
}
|
||||
|
||||
if(isModel)
|
||||
{
|
||||
const char* model = misc_model_dialog(GTK_WIDGET(MainFrame_getWindow()));
|
||||
if(model != 0)
|
||||
{
|
||||
Node_getEntity(node)->setKeyValue("model", model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DoNormalisedColor(Vector3& color)
|
||||
{
|
||||
if(!color_dialog(GTK_WIDGET(MainFrame_getWindow()), color))
|
||||
return false;
|
||||
/*
|
||||
** scale colors so that at least one component is at 1.0F
|
||||
*/
|
||||
|
||||
float largest = 0.0F;
|
||||
|
||||
if ( color[0] > largest )
|
||||
largest = color[0];
|
||||
if ( color[1] > largest )
|
||||
largest = color[1];
|
||||
if ( color[2] > largest )
|
||||
largest = color[2];
|
||||
|
||||
if ( largest == 0.0F )
|
||||
{
|
||||
color[0] = 1.0F;
|
||||
color[1] = 1.0F;
|
||||
color[2] = 1.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
float scaler = 1.0F / largest;
|
||||
|
||||
color[0] *= scaler;
|
||||
color[1] *= scaler;
|
||||
color[2] *= scaler;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Entity_setColour()
|
||||
{
|
||||
if(GlobalSelectionSystem().countSelected() != 0)
|
||||
{
|
||||
const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
|
||||
Entity* entity = Node_getEntity(path.top());
|
||||
if(entity != 0)
|
||||
{
|
||||
const char* strColor = entity->getKeyValue("_color");
|
||||
if(!string_empty(strColor))
|
||||
{
|
||||
Vector3 rgb;
|
||||
if (string_parse_vector3(strColor, rgb))
|
||||
{
|
||||
g_entity_globals.color_entity = rgb;
|
||||
}
|
||||
}
|
||||
|
||||
if(g_pGameDescription->mGameType == "doom3"
|
||||
? color_dialog(GTK_WIDGET(MainFrame_getWindow()), g_entity_globals.color_entity)
|
||||
: DoNormalisedColor(g_entity_globals.color_entity))
|
||||
{
|
||||
char buffer[128];
|
||||
sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0],
|
||||
g_entity_globals.color_entity[1],
|
||||
g_entity_globals.color_entity[2]);
|
||||
|
||||
Scene_EntitySetKeyValue_Selected("_color", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* misc_model_dialog(GtkWidget* parent)
|
||||
{
|
||||
StringOutputStream buffer(1024);
|
||||
|
||||
buffer << g_qeglobals.m_userGamePath.c_str() << "models/";
|
||||
|
||||
if(!file_readable(buffer.c_str()))
|
||||
{
|
||||
// just go to fsmain
|
||||
buffer.clear();
|
||||
buffer << g_qeglobals.m_userGamePath.c_str() << "/";
|
||||
}
|
||||
|
||||
const char *filename = file_dialog (parent, TRUE, "Choose Model", buffer.c_str(), ModelLoader::Name());
|
||||
if (filename != 0)
|
||||
{
|
||||
// use VFS to get the correct relative path
|
||||
const char* relative = path_make_relative(filename, GlobalFileSystem().findRoot(filename));
|
||||
if(relative == filename)
|
||||
{
|
||||
globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n";
|
||||
}
|
||||
return relative;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LightRadiiImport(EntityCreator& self, bool value)
|
||||
{
|
||||
self.setLightRadii(value);
|
||||
}
|
||||
typedef ReferenceCaller1<EntityCreator, bool, LightRadiiImport> LightRadiiImportCaller;
|
||||
|
||||
void LightRadiiExport(EntityCreator& self, const BoolImportCallback& importer)
|
||||
{
|
||||
importer(self.getLightRadii());
|
||||
}
|
||||
typedef ReferenceCaller1<EntityCreator, const BoolImportCallback&, LightRadiiExport> LightRadiiExportCaller;
|
||||
|
||||
void Entity_constructPreferences(PreferencesPage& page)
|
||||
{
|
||||
page.appendCheckBox(
|
||||
"Show", "Light Radii",
|
||||
LightRadiiImportCaller(GlobalEntityCreator()),
|
||||
LightRadiiExportCaller(GlobalEntityCreator())
|
||||
);
|
||||
}
|
||||
void Entity_constructPage(PreferenceGroup& group)
|
||||
{
|
||||
PreferencesPage page(group.createPage("Entities", "Entity Display Preferences"));
|
||||
Entity_constructPreferences(page);
|
||||
}
|
||||
void Entity_registerPreferencesPage()
|
||||
{
|
||||
PreferencesDialog_addDisplayPage(FreeCaller1<PreferenceGroup&, Entity_constructPage>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Entity_constructMenu(GtkMenu* menu)
|
||||
{
|
||||
create_menu_item_with_mnemonic(menu, "_Ungroup", "UngroupSelection");
|
||||
create_menu_item_with_mnemonic(menu, "_Connect", "ConnectSelection");
|
||||
create_menu_item_with_mnemonic(menu, "_Select Color...", "EntityColor");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void Entity_Construct()
|
||||
{
|
||||
GlobalCommands_insert("EntityColor", FreeCaller<Entity_setColour>(), Accelerator('K'));
|
||||
GlobalCommands_insert("ConnectSelection", FreeCaller<Entity_connectSelected>(), Accelerator('K', (GdkModifierType)GDK_CONTROL_MASK));
|
||||
GlobalCommands_insert("UngroupSelection", FreeCaller<Entity_ungroupSelected>());
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("SI_Colors5", Vector3ImportStringCaller(g_entity_globals.color_entity), Vector3ExportStringCaller(g_entity_globals.color_entity));
|
||||
GlobalPreferenceSystem().registerPreference("LastLightIntensity", IntImportStringCaller(g_iLastLightIntensity), IntExportStringCaller(g_iLastLightIntensity));
|
||||
|
||||
Entity_registerPreferencesPage();
|
||||
}
|
||||
|
||||
void Entity_Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
42
radiant/entity.h
Normal file
42
radiant/entity.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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_ENTITY_H)
|
||||
#define INCLUDED_ENTITY_H
|
||||
|
||||
template<typename Element> class BasicVector3;
|
||||
typedef BasicVector3<float> Vector3;
|
||||
void Entity_createFromSelection(const char* name, const Vector3& origin);
|
||||
|
||||
void Scene_EntitySetKeyValue_Selected(const char* key, const char* value);
|
||||
void Scene_EntitySetClassname_Selected(const char* classname);
|
||||
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
const char* misc_model_dialog(GtkWidget* parent);
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Entity_constructMenu(GtkMenu* menu);
|
||||
|
||||
void Entity_Construct();
|
||||
void Entity_Destroy();
|
||||
|
||||
#endif
|
||||
1748
radiant/entityinspector.cpp
Normal file
1748
radiant/entityinspector.cpp
Normal file
File diff suppressed because it is too large
Load Diff
31
radiant/entityinspector.h
Normal file
31
radiant/entityinspector.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_ENTITYINSPECTOR_H)
|
||||
#define INCLUDED_ENTITYINSPECTOR_H
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
GtkWidget* EntityInspector_constructWindow(GtkWindow* parent);
|
||||
void EntityInspector_construct();
|
||||
void EntityInspector_destroy();
|
||||
|
||||
#endif
|
||||
429
radiant/entitylist.cpp
Normal file
429
radiant/entitylist.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
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 "entitylist.h"
|
||||
|
||||
#include "iselection.h"
|
||||
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
#include <gtk/gtktreeselection.h>
|
||||
#include <gtk/gtkcellrenderertext.h>
|
||||
|
||||
#include "string/string.h"
|
||||
#include "scenelib.h"
|
||||
#include "nameable.h"
|
||||
#include "generic/callback.h"
|
||||
#include "generic/object.h"
|
||||
|
||||
#include "gtkutil/widget.h"
|
||||
#include "gtkutil/window.h"
|
||||
#include "gtkutil/idledraw.h"
|
||||
#include "gtkutil/accelerator.h"
|
||||
#include "gtkutil/closure.h"
|
||||
|
||||
#include "treemodel.h"
|
||||
|
||||
void RedrawEntityList();
|
||||
typedef FreeCaller<RedrawEntityList> RedrawEntityListCaller;
|
||||
|
||||
typedef struct _GtkTreeView GtkTreeView;
|
||||
|
||||
class EntityList
|
||||
{
|
||||
public:
|
||||
enum EDirty
|
||||
{
|
||||
eDefault,
|
||||
eSelection,
|
||||
eInsertRemove,
|
||||
};
|
||||
|
||||
EDirty m_dirty;
|
||||
|
||||
IdleDraw m_idleDraw;
|
||||
WindowPositionTracker m_positionTracker;
|
||||
|
||||
GtkWindow* m_window;
|
||||
GtkTreeView* m_tree_view;
|
||||
GraphTreeModel* m_tree_model;
|
||||
bool m_selection_disabled;
|
||||
|
||||
EntityList() :
|
||||
m_dirty(EntityList::eDefault),
|
||||
m_idleDraw(RedrawEntityListCaller()),
|
||||
m_window(0),
|
||||
m_selection_disabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool visible() const
|
||||
{
|
||||
return GTK_WIDGET_VISIBLE(GTK_WIDGET(m_window));
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
EntityList* g_EntityList;
|
||||
|
||||
inline EntityList& getEntityList()
|
||||
{
|
||||
ASSERT_NOTNULL(g_EntityList);
|
||||
return *g_EntityList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline Nameable* Node_getNameable(scene::Node& node)
|
||||
{
|
||||
return NodeTypeCast<Nameable>::cast(node);
|
||||
}
|
||||
|
||||
const char* node_get_name(scene::Node& node)
|
||||
{
|
||||
Nameable* nameable = Node_getNameable(node);
|
||||
return (nameable != 0)
|
||||
? nameable->name()
|
||||
: "node";
|
||||
}
|
||||
|
||||
template<typename value_type>
|
||||
inline void gtk_tree_model_get_pointer(GtkTreeModel* model, GtkTreeIter* iter, gint column, value_type** pointer)
|
||||
{
|
||||
GValue value = GValue_default();
|
||||
gtk_tree_model_get_value(model, iter, column, &value);
|
||||
*pointer = (value_type*)g_value_get_pointer(&value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void entitylist_treeviewcolumn_celldatafunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer data)
|
||||
{
|
||||
scene::Node* node;
|
||||
gtk_tree_model_get_pointer(model, iter, 0, &node);
|
||||
scene::Instance* instance;
|
||||
gtk_tree_model_get_pointer(model, iter, 1, &instance);
|
||||
if(node != 0)
|
||||
{
|
||||
gtk_cell_renderer_set_fixed_size(renderer, -1, -1);
|
||||
char* name = const_cast<char*>(node_get_name(*node));
|
||||
g_object_set(G_OBJECT(renderer), "text", name, "visible", TRUE, 0);
|
||||
|
||||
//globalOutputStream() << "rendering cell " << makeQuoted(name) << "\n";
|
||||
GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(getEntityList().m_tree_view));
|
||||
if(instance->childSelected())
|
||||
{
|
||||
g_object_set(G_OBJECT(renderer), "cell-background-gdk", &style->base[GTK_STATE_ACTIVE], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set(G_OBJECT(renderer), "cell-background-gdk", &style->base[GTK_STATE_NORMAL], 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_cell_renderer_set_fixed_size(renderer, -1, 0);
|
||||
g_object_set(G_OBJECT(renderer), "text", "", "visible", FALSE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean entitylist_tree_select(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
scene::Node* node;
|
||||
gtk_tree_model_get_pointer(model, &iter, 0, &node);
|
||||
scene::Instance* instance;
|
||||
gtk_tree_model_get_pointer(model, &iter, 1, &instance);
|
||||
Selectable* selectable = Instance_getSelectable(*instance);
|
||||
|
||||
if(node == 0)
|
||||
{
|
||||
if(path_currently_selected != FALSE)
|
||||
{
|
||||
getEntityList().m_selection_disabled = true;
|
||||
GlobalSelectionSystem().setSelectedAll(false);
|
||||
getEntityList().m_selection_disabled = false;
|
||||
}
|
||||
}
|
||||
else if(selectable != 0)
|
||||
{
|
||||
getEntityList().m_selection_disabled = true;
|
||||
selectable->setSelected(path_currently_selected == FALSE);
|
||||
getEntityList().m_selection_disabled = false;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean entitylist_tree_select_null(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void EntityList_ConnectSignals(GtkTreeView* view)
|
||||
{
|
||||
GtkTreeSelection* select = gtk_tree_view_get_selection(view);
|
||||
gtk_tree_selection_set_select_function(select, entitylist_tree_select, NULL, 0);
|
||||
}
|
||||
|
||||
void EntityList_DisconnectSignals(GtkTreeView* view)
|
||||
{
|
||||
GtkTreeSelection* select = gtk_tree_view_get_selection(view);
|
||||
gtk_tree_selection_set_select_function(select, entitylist_tree_select_null, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gboolean treemodel_update_selection(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer data)
|
||||
{
|
||||
GtkTreeView* view = reinterpret_cast<GtkTreeView*>(data);
|
||||
|
||||
scene::Instance* instance;
|
||||
gtk_tree_model_get_pointer(model, iter, 1, &instance);
|
||||
Selectable* selectable = Instance_getSelectable(*instance);
|
||||
|
||||
if(selectable != 0)
|
||||
{
|
||||
GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
|
||||
if(selectable->isSelected())
|
||||
{
|
||||
gtk_tree_selection_select_path(selection, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_tree_selection_unselect_path(selection, path);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void EntityList_UpdateSelection(GtkTreeModel* model, GtkTreeView* view)
|
||||
{
|
||||
EntityList_DisconnectSignals(view);
|
||||
gtk_tree_model_foreach(model, treemodel_update_selection, view);
|
||||
EntityList_ConnectSignals(view);
|
||||
}
|
||||
|
||||
|
||||
void RedrawEntityList()
|
||||
{
|
||||
switch(getEntityList().m_dirty)
|
||||
{
|
||||
case EntityList::eInsertRemove:
|
||||
case EntityList::eSelection:
|
||||
EntityList_UpdateSelection(GTK_TREE_MODEL(getEntityList().m_tree_model), getEntityList().m_tree_view);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
getEntityList().m_dirty = EntityList::eDefault;
|
||||
}
|
||||
|
||||
void entitylist_queue_draw()
|
||||
{
|
||||
getEntityList().m_idleDraw.queueDraw();
|
||||
}
|
||||
|
||||
void EntityList_SelectionUpdate()
|
||||
{
|
||||
if(getEntityList().m_selection_disabled)
|
||||
return;
|
||||
|
||||
if(getEntityList().m_dirty < EntityList::eSelection)
|
||||
getEntityList().m_dirty = EntityList::eSelection;
|
||||
entitylist_queue_draw();
|
||||
}
|
||||
|
||||
void EntityList_SelectionChanged(const Selectable& selectable)
|
||||
{
|
||||
EntityList_SelectionUpdate();
|
||||
}
|
||||
|
||||
void entitylist_treeview_rowcollapsed(GtkTreeView* view, GtkTreeIter* iter, GtkTreePath* path, gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
void entitylist_treeview_row_expanded(GtkTreeView* view, GtkTreeIter* iter, GtkTreePath* path, gpointer user_data)
|
||||
{
|
||||
EntityList_SelectionUpdate();
|
||||
}
|
||||
|
||||
|
||||
void EntityList_SetShown(bool shown)
|
||||
{
|
||||
widget_set_visible(GTK_WIDGET(getEntityList().m_window), shown);
|
||||
}
|
||||
|
||||
void EntityList_toggleShown()
|
||||
{
|
||||
EntityList_SetShown(!getEntityList().visible());
|
||||
}
|
||||
|
||||
gint graph_tree_model_compare_name(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
|
||||
{
|
||||
scene::Node* first;
|
||||
gtk_tree_model_get(model, a, 0, (gpointer*)&first, -1);
|
||||
scene::Node* second;
|
||||
gtk_tree_model_get(model, b, 0, (gpointer*)&second, -1);
|
||||
int result = 0;
|
||||
if(first != 0 && second != 0)
|
||||
{
|
||||
result = string_compare(node_get_name(*first), node_get_name(*second));
|
||||
}
|
||||
if(result == 0)
|
||||
{
|
||||
return (first < second) ? -1 : (second < first) ? 1 : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern GraphTreeModel* scene_graph_get_tree_model();
|
||||
void AttachEntityTreeModel()
|
||||
{
|
||||
getEntityList().m_tree_model = scene_graph_get_tree_model();
|
||||
|
||||
gtk_tree_view_set_model(getEntityList().m_tree_view, GTK_TREE_MODEL(getEntityList().m_tree_model));
|
||||
}
|
||||
|
||||
void DetachEntityTreeModel()
|
||||
{
|
||||
getEntityList().m_tree_model = 0;
|
||||
|
||||
gtk_tree_view_set_model(getEntityList().m_tree_view, 0);
|
||||
}
|
||||
|
||||
void EntityList_constructWindow(GtkWindow* main_window)
|
||||
{
|
||||
ASSERT_MESSAGE(getEntityList().m_window == 0, "error");
|
||||
|
||||
GtkWindow* window = create_persistent_floating_window("Entity List", main_window);
|
||||
|
||||
gtk_window_add_accel_group(window, global_accel);
|
||||
|
||||
getEntityList().m_positionTracker.connect(window);
|
||||
|
||||
|
||||
getEntityList().m_window = window;
|
||||
|
||||
{
|
||||
GtkScrolledWindow* scr = create_scrolled_window(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(scr));
|
||||
|
||||
{
|
||||
GtkWidget* view = gtk_tree_view_new();
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
|
||||
|
||||
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
|
||||
GtkTreeViewColumn* column = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_pack_start(column, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func(column, renderer, entitylist_treeviewcolumn_celldatafunc, 0, 0);
|
||||
|
||||
GtkTreeSelection* select = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
|
||||
gtk_tree_selection_set_mode(select, GTK_SELECTION_MULTIPLE);
|
||||
|
||||
g_signal_connect(G_OBJECT(view), "row_expanded", G_CALLBACK(entitylist_treeview_row_expanded), 0);
|
||||
g_signal_connect(G_OBJECT(view), "row_collapsed", G_CALLBACK(entitylist_treeview_rowcollapsed), 0);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
|
||||
|
||||
gtk_widget_show(view);
|
||||
gtk_container_add (GTK_CONTAINER(scr), view);
|
||||
getEntityList().m_tree_view = GTK_TREE_VIEW(view);
|
||||
}
|
||||
}
|
||||
|
||||
EntityList_ConnectSignals(getEntityList().m_tree_view);
|
||||
AttachEntityTreeModel();
|
||||
}
|
||||
|
||||
void EntityList_destroyWindow()
|
||||
{
|
||||
DetachEntityTreeModel();
|
||||
EntityList_DisconnectSignals(getEntityList().m_tree_view);
|
||||
destroy_floating_window(getEntityList().m_window);
|
||||
}
|
||||
|
||||
#include "preferencesystem.h"
|
||||
|
||||
#include "iselection.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
scene::Node* nullNode = 0;
|
||||
}
|
||||
|
||||
class NullSelectedInstance : public scene::Instance, public Selectable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
InstanceStaticCast<NullSelectedInstance, Selectable>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
NullSelectedInstance() : Instance(scene::Path(makeReference(*nullNode)), 0, this, StaticTypeCasts::instance().get())
|
||||
{
|
||||
}
|
||||
|
||||
void setSelected(bool select)
|
||||
{
|
||||
ERROR_MESSAGE("error");
|
||||
}
|
||||
bool isSelected() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
typedef LazyStatic<NullSelectedInstance> StaticNullSelectedInstance;
|
||||
|
||||
|
||||
void EntityList_Construct()
|
||||
{
|
||||
graph_tree_model_insert(scene_graph_get_tree_model(), StaticNullSelectedInstance::instance());
|
||||
|
||||
g_EntityList = new EntityList;
|
||||
|
||||
getEntityList().m_positionTracker.setPosition(c_default_window_pos);
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("EntityInfoDlg", WindowPositionTrackerImportStringCaller(getEntityList().m_positionTracker), WindowPositionTrackerExportStringCaller(getEntityList().m_positionTracker));
|
||||
|
||||
GlobalSelectionSystem().addSelectionChangeCallback(FreeCaller1<const Selectable&, EntityList_SelectionChanged>());
|
||||
}
|
||||
void EntityList_Destroy()
|
||||
{
|
||||
delete g_EntityList;
|
||||
|
||||
graph_tree_model_erase(scene_graph_get_tree_model(), StaticNullSelectedInstance::instance());
|
||||
}
|
||||
33
radiant/entitylist.h
Normal file
33
radiant/entitylist.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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_ENTITYLIST_H)
|
||||
#define INCLUDED_ENTITYLIST_H
|
||||
|
||||
void EntityList_Construct();
|
||||
void EntityList_Destroy();
|
||||
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
void EntityList_constructWindow(GtkWindow* main_window);
|
||||
void EntityList_destroyWindow();
|
||||
void EntityList_toggleShown();
|
||||
|
||||
#endif
|
||||
200
radiant/environment.cpp
Normal file
200
radiant/environment.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
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 "environment.h"
|
||||
|
||||
#include "stream/textstream.h"
|
||||
#include "string/string.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "debugging/debugging.h"
|
||||
#include "os/path.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
|
||||
int g_argc;
|
||||
char** g_argv;
|
||||
|
||||
void args_init(int argc, char* argv[])
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
for (k = i; k < argc; k++)
|
||||
if (argv[k] != 0)
|
||||
break;
|
||||
|
||||
if (k > i)
|
||||
{
|
||||
k -= i;
|
||||
for (j = i + k; j < argc; j++)
|
||||
argv[j-k] = argv[j];
|
||||
argc -= k;
|
||||
}
|
||||
}
|
||||
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
CopiedString home_path;
|
||||
CopiedString app_path;
|
||||
}
|
||||
|
||||
const char* environment_get_home_path()
|
||||
{
|
||||
return home_path.c_str();
|
||||
}
|
||||
|
||||
const char* environment_get_app_path()
|
||||
{
|
||||
return app_path.c_str();
|
||||
}
|
||||
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib/gutils.h>
|
||||
|
||||
const char* LINK_NAME =
|
||||
#if defined (__linux__)
|
||||
"/proc/self/exe"
|
||||
#else
|
||||
"/proc/curproc/file"
|
||||
#endif
|
||||
;
|
||||
|
||||
/// brief Returns the filename of the executable belonging to the current process, or 0 if not found.
|
||||
char* getexename(char *buf)
|
||||
{
|
||||
/* Now read the symbolic link */
|
||||
int ret = readlink(LINK_NAME, buf, PATH_MAX);
|
||||
|
||||
if(ret == -1)
|
||||
{
|
||||
globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted(g_argv[0]);
|
||||
const char* path = realpath(g_argv[0], buf);
|
||||
if(path == 0)
|
||||
{
|
||||
/* In case of an error, leave the handling up to the caller */
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure proper NUL termination */
|
||||
buf[ret] = 0;
|
||||
|
||||
/* delete the program name */
|
||||
*(strrchr(buf, '/')) = '\0';
|
||||
|
||||
// NOTE: we build app path with a trailing '/'
|
||||
// it's a general convention in Radiant to have the slash at the end of directories
|
||||
if (buf[strlen(buf)-1] != '/')
|
||||
{
|
||||
strcat(buf, "/");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void environment_init(int argc, char* argv[])
|
||||
{
|
||||
// Give away unnecessary root privileges.
|
||||
// Important: must be done before calling gtk_init().
|
||||
char *loginname;
|
||||
struct passwd *pw;
|
||||
seteuid(getuid());
|
||||
if (geteuid() == 0 && (loginname = getlogin()) != 0 &&
|
||||
(pw = getpwnam(loginname)) != 0)
|
||||
setuid(pw->pw_uid);
|
||||
|
||||
args_init(argc, argv);
|
||||
|
||||
{
|
||||
StringOutputStream home(256);
|
||||
home << DirectoryCleaned(g_get_home_dir()) << ".radiant/";
|
||||
Q_mkdir(home.c_str());
|
||||
home_path = home.c_str();
|
||||
}
|
||||
{
|
||||
char real[PATH_MAX];
|
||||
app_path = getexename(real);
|
||||
ASSERT_MESSAGE(!string_empty(app_path.c_str()), "failed to deduce app path");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <shfolder.h>
|
||||
|
||||
void environment_init(int argc, char* argv[])
|
||||
{
|
||||
args_init(argc, argv);
|
||||
|
||||
{
|
||||
char appdata[MAX_PATH+1];
|
||||
SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, appdata);
|
||||
|
||||
StringOutputStream home(256);
|
||||
if(string_empty(appdata))
|
||||
{
|
||||
ERROR_MESSAGE("Application Data folder not available.\n"
|
||||
"Please install shfolder redistributable package.\n"
|
||||
"Radiant will use C:\\ for user preferences.\n");
|
||||
home << "C:";
|
||||
}
|
||||
else
|
||||
{
|
||||
home << PathCleaned(appdata);
|
||||
}
|
||||
home << "/RadiantSettings/";
|
||||
Q_mkdir(home.c_str());
|
||||
home_path = home.c_str();
|
||||
}
|
||||
{
|
||||
// get path to the editor
|
||||
char filename[MAX_PATH+1];
|
||||
GetModuleFileName(0, filename, MAX_PATH);
|
||||
char* last_separator = strrchr(filename, '\\');
|
||||
if(last_separator != 0)
|
||||
{
|
||||
*(last_separator+1) = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
filename[0] = '\0';
|
||||
}
|
||||
StringOutputStream app(256);
|
||||
app << PathCleaned(filename);
|
||||
app_path = app.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
29
radiant/environment.h
Normal file
29
radiant/environment.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_ENVIRONMENT_H)
|
||||
#define INCLUDED_ENVIRONMENT_H
|
||||
|
||||
void environment_init(int argc, char* argv[]);
|
||||
const char* environment_get_home_path();
|
||||
const char* environment_get_app_path();
|
||||
|
||||
#endif
|
||||
141
radiant/error.cpp
Normal file
141
radiant/error.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
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 "error.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "igl.h"
|
||||
|
||||
#include "gtkutil/messagebox.h"
|
||||
#include "console.h"
|
||||
#include "preferences.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Error
|
||||
|
||||
For abnormal program terminations
|
||||
=================
|
||||
*/
|
||||
|
||||
/*!
|
||||
\todo
|
||||
FIXME the prompt wether to do prefs dialog, may not even be possible
|
||||
if the crash happens before the game is loaded
|
||||
*/
|
||||
|
||||
void Error (const char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char text[4096];
|
||||
|
||||
va_start (argptr,error);
|
||||
vsprintf (text, error,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
strcat( text, "\n" );
|
||||
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
if (errno != 0)
|
||||
{
|
||||
strcat( text, "errno: " );
|
||||
strcat( text, strerror (errno));
|
||||
strcat( text, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
if (GetLastError() != 0)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
0,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
0
|
||||
);
|
||||
strcat( text, "GetLastError: " );
|
||||
/*
|
||||
Gtk will only crunch 0<=char<=127
|
||||
this is a bit hackish, but I didn't find useful functions in win32 API for this
|
||||
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516
|
||||
*/
|
||||
TCHAR *scan, *next = (TCHAR*)lpMsgBuf;
|
||||
do
|
||||
{
|
||||
scan = next;
|
||||
text[strlen(text)+1] = '\0';
|
||||
if ((scan[0] >= 0) && (scan[0] <= 127))
|
||||
text[strlen(text)] = char(scan[0]);
|
||||
else
|
||||
text[strlen(text)] = '?';
|
||||
next = CharNext(scan);
|
||||
} while (next != scan);
|
||||
strcat( text, "\n");
|
||||
LocalFree( lpMsgBuf );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// we need to have a current context to call glError()
|
||||
if (g_glwindow_globals.d_glBase != 0)
|
||||
{
|
||||
// glGetError .. can record several errors, clears after calling
|
||||
//++timo TODO: be able to deal with several errors if necessary, for now I'm just warning about pending error messages
|
||||
// NOTE: forget that, most boards don't seem to follow the OpenGL standard
|
||||
GLenum iGLError = glGetError();
|
||||
if (iGLError != GL_NO_ERROR)
|
||||
{
|
||||
// use our own gluErrorString
|
||||
strcat( text, "gluErrorString: " );
|
||||
strcat( text, (char*)gluErrorString( iGLError ) );
|
||||
strcat( text, "\n" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
strcat (text, "An unrecoverable error has occured.\n");
|
||||
|
||||
ERROR_MESSAGE(text);
|
||||
|
||||
// force close logging if necessary
|
||||
Sys_LogFile(false);
|
||||
|
||||
_exit (1);
|
||||
}
|
||||
27
radiant/error.h
Normal file
27
radiant/error.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
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_ERROR_H)
|
||||
#define INCLUDED_ERROR_H
|
||||
|
||||
void Error(const char *error, ...);
|
||||
|
||||
#endif
|
||||
372
radiant/feedback.cpp
Normal file
372
radiant/feedback.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// classes used for describing geometry information from q3map feedback
|
||||
//
|
||||
|
||||
#include "feedback.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "igl.h"
|
||||
#include "iselection.h"
|
||||
|
||||
#include <gtk/gtktreeview.h>
|
||||
#include <gtk/gtktreeselection.h>
|
||||
#include <gtk/gtkliststore.h>
|
||||
#include <gtk/gtkcellrenderertext.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
|
||||
#include "map.h"
|
||||
#include "dialog.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
|
||||
CDbgDlg g_DbgDlg;
|
||||
|
||||
void Feedback_draw2D(VIEWTYPE viewType)
|
||||
{
|
||||
g_DbgDlg.draw2D(viewType);
|
||||
}
|
||||
|
||||
void CSelectMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "select"))
|
||||
{
|
||||
// read the message
|
||||
ESelectState = SELECT_MESSAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read the brush
|
||||
ASSERT_MESSAGE(string_equal(reinterpret_cast<const char*>(name), "brush"), "FEEDBACK PARSE ERROR");
|
||||
ASSERT_MESSAGE(ESelectState == SELECT_MESSAGE, "FEEDBACK PARSE ERROR");
|
||||
ESelectState = SELECT_BRUSH;
|
||||
globalOutputStream() << message.c_str() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void CSelectMsg::saxEndElement(message_info_t *ctx, const xmlChar *name)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "select"))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void CSelectMsg::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len)
|
||||
{
|
||||
if(ESelectState == SELECT_MESSAGE)
|
||||
{
|
||||
message.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
brush.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
}
|
||||
|
||||
IGL2DWindow* CSelectMsg::Highlight()
|
||||
{
|
||||
GlobalSelectionSystem().setSelectedAll(false);
|
||||
int entitynum, brushnum;
|
||||
if(sscanf(reinterpret_cast<const char*>(brush.c_str()), "%i %i", &entitynum, &brushnum) == 2)
|
||||
{
|
||||
SelectBrush (entitynum, brushnum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CPointMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "pointmsg"))
|
||||
{
|
||||
// read the message
|
||||
EPointState = POINT_MESSAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read the brush
|
||||
ASSERT_MESSAGE(string_equal(reinterpret_cast<const char*>(name), "point"), "FEEDBACK PARSE ERROR");
|
||||
ASSERT_MESSAGE(EPointState == POINT_MESSAGE, "FEEDBACK PARSE ERROR");
|
||||
EPointState = POINT_POINT;
|
||||
globalOutputStream() << message.c_str() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void CPointMsg::saxEndElement (message_info_t *ctx, const xmlChar *name)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "pointmsg"))
|
||||
{
|
||||
}
|
||||
else if(string_equal(reinterpret_cast<const char*>(name), "point"))
|
||||
{
|
||||
sscanf(point.c_str(), "%g %g %g", &(pt[0]), &(pt[1]), &(pt[2]));
|
||||
point.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CPointMsg::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)
|
||||
{
|
||||
if(EPointState == POINT_MESSAGE)
|
||||
{
|
||||
message.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MESSAGE(EPointState == POINT_POINT, "FEEDBACK PARSE ERROR");
|
||||
point.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
}
|
||||
|
||||
IGL2DWindow* CPointMsg::Highlight()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void CPointMsg::DropHighlight()
|
||||
{
|
||||
}
|
||||
|
||||
void CPointMsg::Draw2D( VIEWTYPE vt )
|
||||
{
|
||||
int nDim1 = (vt == YZ) ? 1 : 0;
|
||||
int nDim2 = (vt == XY) ? 1 : 2;
|
||||
glPointSize(4);
|
||||
glColor3f(1.0f,0.0f,0.0f);
|
||||
glBegin (GL_POINTS);
|
||||
glVertex2f (pt[nDim1], pt[nDim2]);
|
||||
glEnd();
|
||||
glBegin (GL_LINE_LOOP);
|
||||
glVertex2f (pt[nDim1]-8, pt[nDim2]-8);
|
||||
glVertex2f (pt[nDim1]+8, pt[nDim2]-8);
|
||||
glVertex2f (pt[nDim1]+8, pt[nDim2]+8);
|
||||
glVertex2f (pt[nDim1]-8, pt[nDim2]+8);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void CWindingMsg::saxStartElement(message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "windingmsg"))
|
||||
{
|
||||
// read the message
|
||||
EPointState = WINDING_MESSAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read the brush
|
||||
ASSERT_MESSAGE(string_equal(reinterpret_cast<const char*>(name), "winding"), "FEEDBACK PARSE ERROR");
|
||||
ASSERT_MESSAGE(EPointState == WINDING_MESSAGE, "FEEDBACK PARSE ERROR");
|
||||
EPointState = WINDING_WINDING;
|
||||
globalOutputStream() << message.c_str() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void CWindingMsg::saxEndElement(message_info_t *ctx, const xmlChar *name)
|
||||
{
|
||||
if(string_equal(reinterpret_cast<const char*>(name), "windingmsg"))
|
||||
{
|
||||
}
|
||||
else if(string_equal(reinterpret_cast<const char*>(name), "winding"))
|
||||
{
|
||||
const char* c = winding.c_str();
|
||||
sscanf(c, "%i ", &numpoints);
|
||||
|
||||
int i = 0;
|
||||
for(; i < numpoints; i++)
|
||||
{
|
||||
c = strchr(c + 1, '(');
|
||||
if(c) // even if we are given the number of points when the cycle begins .. don't trust it too much
|
||||
sscanf(c, "(%g %g %g)", &wt[i][0], &wt[i][1], &wt[i][2]);
|
||||
else
|
||||
break;
|
||||
}
|
||||
numpoints = i;
|
||||
}
|
||||
}
|
||||
|
||||
void CWindingMsg::saxCharacters(message_info_t *ctx, const xmlChar *ch, int len)
|
||||
{
|
||||
if(EPointState == WINDING_MESSAGE)
|
||||
{
|
||||
message.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MESSAGE(EPointState == WINDING_WINDING, "FEEDBACK PARSE ERROR");
|
||||
winding.write(reinterpret_cast<const char*>(ch), len);
|
||||
}
|
||||
}
|
||||
|
||||
IGL2DWindow* CWindingMsg::Highlight()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void CWindingMsg::DropHighlight()
|
||||
{
|
||||
}
|
||||
|
||||
void CWindingMsg::Draw2D( VIEWTYPE vt )
|
||||
{
|
||||
int i;
|
||||
|
||||
int nDim1 = (vt == YZ) ? 1 : 0;
|
||||
int nDim2 = (vt == XY) ? 1 : 2;
|
||||
glColor3f(1.0f,0.f,0.0f);
|
||||
|
||||
glPointSize(4);
|
||||
glBegin (GL_POINTS);
|
||||
for(i = 0; i < numpoints; i++)
|
||||
glVertex2f (wt[i][nDim1], wt[i][nDim2]);
|
||||
glEnd();
|
||||
glPointSize(1);
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(0.133f,0.4f,1.0f,0.5f);
|
||||
glBegin (GL_POLYGON);
|
||||
for(i = 0; i < numpoints; i++)
|
||||
glVertex2f (wt[i][nDim1], wt[i][nDim2]);
|
||||
glEnd();
|
||||
glDisable (GL_BLEND);
|
||||
}
|
||||
|
||||
// triggered when the user selects an entry in the feedback box
|
||||
static void feedback_selection_changed(GtkTreeSelection* selection, gpointer data)
|
||||
{
|
||||
g_DbgDlg.DropHighlight();
|
||||
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter selected;
|
||||
if(gtk_tree_selection_get_selected(selection, &model, &selected))
|
||||
{
|
||||
GtkTreePath* path = gtk_tree_model_get_path(model, &selected);
|
||||
g_DbgDlg.SetHighlight(gtk_tree_path_get_indices(path)[0]);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
void CDbgDlg::DropHighlight()
|
||||
{
|
||||
if(m_pHighlight != 0)
|
||||
{
|
||||
m_pHighlight->DropHighlight();
|
||||
m_pHighlight = 0;
|
||||
m_pDraw2D = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CDbgDlg::SetHighlight(gint row)
|
||||
{
|
||||
ISAXHandler *h = GetElement(row);
|
||||
if(h != NULL)
|
||||
{
|
||||
m_pDraw2D = h->Highlight();
|
||||
m_pHighlight = h;
|
||||
}
|
||||
}
|
||||
|
||||
ISAXHandler *CDbgDlg::GetElement (std::size_t row)
|
||||
{
|
||||
return static_cast<ISAXHandler *>(g_ptr_array_index(m_pFeedbackElements, gint(row)));
|
||||
}
|
||||
|
||||
void CDbgDlg::Init()
|
||||
{
|
||||
DropHighlight();
|
||||
|
||||
// free all the ISAXHandler*, clean it
|
||||
while (m_pFeedbackElements->len)
|
||||
{
|
||||
static_cast<ISAXHandler *>(g_ptr_array_index (m_pFeedbackElements, 0))->Release();
|
||||
g_ptr_array_remove_index (m_pFeedbackElements, 0);
|
||||
}
|
||||
|
||||
if(m_clist != NULL)
|
||||
gtk_list_store_clear (m_clist);
|
||||
}
|
||||
|
||||
void CDbgDlg::Push (ISAXHandler *pHandler)
|
||||
{
|
||||
// push in the list
|
||||
g_ptr_array_add (m_pFeedbackElements, (void *)pHandler);
|
||||
|
||||
if(GetWidget() == 0)
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
// put stuff in the list
|
||||
gtk_list_store_clear (m_clist);
|
||||
for(std::size_t i = 0; i < static_cast<std::size_t>(m_pFeedbackElements->len); ++i)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_list_store_append(m_clist, &iter);
|
||||
gtk_list_store_set(m_clist, &iter, 0, GetElement(i)->getName(), -1);
|
||||
}
|
||||
|
||||
ShowDlg();
|
||||
}
|
||||
|
||||
GtkWindow* CDbgDlg::BuildDialog()
|
||||
{
|
||||
GtkWindow* window = create_floating_window("Q3Map debug window", MainFrame_getWindow());
|
||||
|
||||
GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_widget_show (scr);
|
||||
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (scr));
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
|
||||
|
||||
{
|
||||
GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
|
||||
|
||||
GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
|
||||
|
||||
{
|
||||
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
|
||||
GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
|
||||
}
|
||||
|
||||
{
|
||||
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
|
||||
gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
|
||||
g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(feedback_selection_changed), NULL);
|
||||
}
|
||||
|
||||
gtk_widget_show(view);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER (scr), view);
|
||||
|
||||
g_object_unref(G_OBJECT(store));
|
||||
|
||||
m_clist = store;
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
186
radiant/feedback.h
Normal file
186
radiant/feedback.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// classes used for describing geometry information from q3map feedback
|
||||
//
|
||||
|
||||
#ifndef __Q3MAP_FEEDBACK__
|
||||
#define __Q3MAP_FEEDBACK__
|
||||
|
||||
#include "math/vector.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include <glib/gstring.h>
|
||||
#include "xmlstuff.h"
|
||||
#include "dialog.h"
|
||||
#include "xywindow.h"
|
||||
|
||||
// we use these classes to let plugins draw inside the Radiant windows
|
||||
// 2D window like YZ XZ XY
|
||||
class IGL2DWindow
|
||||
{
|
||||
public:
|
||||
// Increment the number of references to this object
|
||||
virtual void IncRef() = 0;
|
||||
// Decrement the reference count
|
||||
virtual void DecRef() = 0;
|
||||
virtual void Draw2D( VIEWTYPE vt ) = 0;
|
||||
};
|
||||
|
||||
// 3D window
|
||||
class IGL3DWindow
|
||||
{
|
||||
public:
|
||||
// Increment the number of references to this object
|
||||
virtual void IncRef() = 0;
|
||||
// Decrement the reference count
|
||||
virtual void DecRef() = 0;
|
||||
virtual void Draw3D() = 0;
|
||||
};
|
||||
|
||||
// a select message with a brush/entity select information
|
||||
class CSelectMsg : public ISAXHandler
|
||||
{
|
||||
enum { SELECT_MESSAGE, SELECT_BRUSH } ESelectState;
|
||||
StringOutputStream message;
|
||||
StringOutputStream brush;
|
||||
public:
|
||||
CSelectMsg() { ESelectState = SELECT_MESSAGE; }
|
||||
// SAX interface
|
||||
void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
|
||||
void saxEndElement (message_info_t *ctx, const xmlChar *name);
|
||||
void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
|
||||
// for use in the dialog window
|
||||
const char* getName() { return message.c_str(); }
|
||||
IGL2DWindow* Highlight();
|
||||
void DropHighlight() { }
|
||||
};
|
||||
|
||||
class CPointMsg : public ISAXHandler, public IGL2DWindow
|
||||
{
|
||||
enum { POINT_MESSAGE, POINT_POINT } EPointState;
|
||||
StringOutputStream message;
|
||||
StringOutputStream point;
|
||||
Vector3 pt;
|
||||
int refCount;
|
||||
public:
|
||||
CPointMsg() { EPointState = POINT_MESSAGE; refCount = 0; }
|
||||
// SAX interface
|
||||
void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
|
||||
void saxEndElement (message_info_t *ctx, const xmlChar *name);
|
||||
void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
|
||||
// for use in the dialog window
|
||||
const char* getName() { return message.c_str(); }
|
||||
IGL2DWindow* Highlight();
|
||||
void DropHighlight();
|
||||
|
||||
// IGL2DWindow interface --------------------------------
|
||||
// Increment the number of references to this object
|
||||
void IncRef() { refCount++; }
|
||||
// Decrement the reference count
|
||||
void DecRef() { refCount--; if (refCount <= 0) delete this; }
|
||||
void Draw2D( VIEWTYPE vt );
|
||||
};
|
||||
|
||||
class CWindingMsg : public ISAXHandler, public IGL2DWindow
|
||||
{
|
||||
enum { WINDING_MESSAGE, WINDING_WINDING } EPointState;
|
||||
StringOutputStream message;
|
||||
StringOutputStream winding;
|
||||
Vector3 wt[256];
|
||||
int numpoints;
|
||||
int refCount;
|
||||
public:
|
||||
CWindingMsg() { EPointState = WINDING_MESSAGE; refCount = 0; numpoints = 0; }
|
||||
// SAX interface
|
||||
void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
|
||||
void saxEndElement (message_info_t *ctx, const xmlChar *name);
|
||||
void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
|
||||
// for use in the dialog window
|
||||
const char* getName() { return message.c_str(); }
|
||||
IGL2DWindow* Highlight();
|
||||
void DropHighlight();
|
||||
|
||||
// IGL2DWindow interface --------------------------------
|
||||
// Increment the number of references to this object
|
||||
void IncRef() { refCount++; }
|
||||
// Decrement the reference count
|
||||
void DecRef() { refCount--; if (refCount <= 0) delete this; }
|
||||
void Draw2D( VIEWTYPE vt );
|
||||
};
|
||||
|
||||
typedef struct _GtkListStore GtkListStore;
|
||||
|
||||
class CDbgDlg : public Dialog
|
||||
{
|
||||
GPtrArray *m_pFeedbackElements;
|
||||
// the list widget we use in the dialog
|
||||
GtkListStore* m_clist;
|
||||
ISAXHandler *m_pHighlight;
|
||||
IGL2DWindow* m_pDraw2D;
|
||||
public:
|
||||
CDbgDlg()
|
||||
{
|
||||
m_pFeedbackElements = g_ptr_array_new();
|
||||
m_pHighlight = NULL;
|
||||
m_pDraw2D = NULL;
|
||||
}
|
||||
// refresh items
|
||||
void Push (ISAXHandler *);
|
||||
// clean the debug window, release all ISAXHanlders we have
|
||||
void Init();
|
||||
ISAXHandler *GetElement(std::size_t row);
|
||||
void SetHighlight(gint row);
|
||||
void DropHighlight();
|
||||
void draw2D(VIEWTYPE viewType)
|
||||
{
|
||||
if(m_pDraw2D != 0)
|
||||
{
|
||||
m_pDraw2D->Draw2D(viewType);
|
||||
}
|
||||
}
|
||||
void destroyWindow()
|
||||
{
|
||||
if(GetWidget() != 0)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
// void HideDlg();
|
||||
protected:
|
||||
GtkWindow* BuildDialog();
|
||||
};
|
||||
|
||||
extern CDbgDlg g_DbgDlg;
|
||||
|
||||
void Feedback_draw2D(VIEWTYPE viewType);
|
||||
|
||||
#endif
|
||||
139
radiant/filetypes.cpp
Normal file
139
radiant/filetypes.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
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 "filetypes.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "ifiletypes.h"
|
||||
|
||||
#include "string/string.h"
|
||||
#include "os/path.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class RadiantFileTypeRegistry : public IFileTypeRegistry
|
||||
{
|
||||
struct filetype_copy_t
|
||||
{
|
||||
filetype_copy_t(const char* moduleName, const filetype_t other)
|
||||
: m_moduleName(moduleName), m_name(other.name), m_pattern(other.pattern)
|
||||
{
|
||||
}
|
||||
const char* getModuleName() const
|
||||
{
|
||||
return m_moduleName.c_str();
|
||||
}
|
||||
filetype_t getType() const
|
||||
{
|
||||
return filetype_t(m_name.c_str(), m_pattern.c_str());
|
||||
}
|
||||
private:
|
||||
CopiedString m_moduleName;
|
||||
CopiedString m_name;
|
||||
CopiedString m_pattern;
|
||||
};
|
||||
typedef std::vector<filetype_copy_t> filetype_list_t;
|
||||
std::map<CopiedString, filetype_list_t> m_typelists;
|
||||
public:
|
||||
RadiantFileTypeRegistry()
|
||||
{
|
||||
addType("*", "*", filetype_t("All Files", "*.*"));
|
||||
}
|
||||
void addType(const char* moduleType, const char* moduleName, filetype_t type)
|
||||
{
|
||||
m_typelists[moduleType].push_back(filetype_copy_t(moduleName, type));
|
||||
}
|
||||
void getTypeList(const char* moduleType, IFileTypeList* typelist)
|
||||
{
|
||||
filetype_list_t& list_ref = m_typelists[moduleType];
|
||||
for(filetype_list_t::iterator i = list_ref.begin(); i != list_ref.end(); ++i)
|
||||
{
|
||||
typelist->addType((*i).getModuleName(), (*i).getType());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static RadiantFileTypeRegistry g_patterns;
|
||||
|
||||
IFileTypeRegistry* GetFileTypeRegistry()
|
||||
{
|
||||
return &g_patterns;
|
||||
}
|
||||
|
||||
const char* findModuleName(IFileTypeRegistry* registry, const char* moduleType, const char* extension)
|
||||
{
|
||||
class SearchFileTypeList : public IFileTypeList
|
||||
{
|
||||
char m_pattern[128];
|
||||
const char* m_moduleName;
|
||||
public:
|
||||
SearchFileTypeList(const char* ext)
|
||||
: m_moduleName("")
|
||||
{
|
||||
m_pattern[0] = '*';
|
||||
m_pattern[1] = '.';
|
||||
strncpy(m_pattern + 2, ext, 125);
|
||||
m_pattern[127] = '\0';
|
||||
}
|
||||
void addType(const char* moduleName, filetype_t type)
|
||||
{
|
||||
if(extension_equal(m_pattern, type.pattern))
|
||||
{
|
||||
m_moduleName = moduleName;
|
||||
}
|
||||
}
|
||||
|
||||
const char* getModuleName()
|
||||
{
|
||||
return m_moduleName;
|
||||
}
|
||||
} search(extension);
|
||||
registry->getTypeList(moduleType, &search);
|
||||
return search.getModuleName();
|
||||
}
|
||||
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
class FiletypesAPI
|
||||
{
|
||||
IFileTypeRegistry* m_filetypes;
|
||||
public:
|
||||
typedef IFileTypeRegistry Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
FiletypesAPI()
|
||||
{
|
||||
m_filetypes = GetFileTypeRegistry();
|
||||
}
|
||||
IFileTypeRegistry* getTable()
|
||||
{
|
||||
return m_filetypes;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<FiletypesAPI> FiletypesModule;
|
||||
typedef Static<FiletypesModule> StaticFiletypesModule;
|
||||
StaticRegisterModule staticRegisterFiletypes(StaticFiletypesModule::instance());
|
||||
|
||||
|
||||
29
radiant/filetypes.h
Normal file
29
radiant/filetypes.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_FILETYPES_H)
|
||||
#define INCLUDED_FILETYPES_H
|
||||
|
||||
class IFileTypeRegistry;
|
||||
IFileTypeRegistry* GetFileTypeRegistry();
|
||||
const char* findModuleName(IFileTypeRegistry* registry, const char* moduleType, const char* extension);
|
||||
|
||||
#endif
|
||||
288
radiant/filters.cpp
Normal file
288
radiant/filters.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
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 "debugging/debugging.h"
|
||||
|
||||
#include "ifilter.h"
|
||||
|
||||
#include "scenelib.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include "gtkutil/widget.h"
|
||||
#include "gtkutil/menu.h"
|
||||
#include "gtkmisc.h"
|
||||
#include "mainframe.h"
|
||||
#include "commands.h"
|
||||
#include "preferences.h"
|
||||
|
||||
struct filters_globals_t
|
||||
{
|
||||
std::size_t exclude;
|
||||
|
||||
filters_globals_t() :
|
||||
exclude(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
filters_globals_t g_filters_globals;
|
||||
|
||||
inline bool filter_active(int mask)
|
||||
{
|
||||
return (g_filters_globals.exclude & mask) > 0;
|
||||
}
|
||||
|
||||
class FilterWrapper
|
||||
{
|
||||
public:
|
||||
FilterWrapper(Filter& filter, int mask) : m_filter(filter), m_mask(mask)
|
||||
{
|
||||
}
|
||||
void update()
|
||||
{
|
||||
m_filter.setActive(filter_active(m_mask));
|
||||
}
|
||||
private:
|
||||
Filter& m_filter;
|
||||
int m_mask;
|
||||
};
|
||||
|
||||
typedef std::list<FilterWrapper> Filters;
|
||||
Filters g_filters;
|
||||
|
||||
typedef std::set<Filterable*> Filterables;
|
||||
Filterables g_filterables;
|
||||
|
||||
void UpdateFilters()
|
||||
{
|
||||
{
|
||||
for(Filters::iterator i = g_filters.begin(); i != g_filters.end(); ++i)
|
||||
{
|
||||
(*i).update();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for(Filterables::iterator i = g_filterables.begin(); i != g_filterables.end(); ++i)
|
||||
{
|
||||
(*i)->updateFiltered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BasicFilterSystem : public FilterSystem
|
||||
{
|
||||
public:
|
||||
void addFilter(Filter& filter, int mask)
|
||||
{
|
||||
g_filters.push_back(FilterWrapper(filter, mask));
|
||||
g_filters.back().update();
|
||||
}
|
||||
void registerFilterable(Filterable& filterable)
|
||||
{
|
||||
ASSERT_MESSAGE(g_filterables.find(&filterable) == g_filterables.end(), "filterable already registered");
|
||||
filterable.updateFiltered();
|
||||
g_filterables.insert(&filterable);
|
||||
}
|
||||
void unregisterFilterable(Filterable& filterable)
|
||||
{
|
||||
ASSERT_MESSAGE(g_filterables.find(&filterable) != g_filterables.end(), "filterable not registered");
|
||||
g_filterables.erase(&filterable);
|
||||
}
|
||||
};
|
||||
|
||||
BasicFilterSystem g_FilterSystem;
|
||||
|
||||
FilterSystem& GetFilterSystem()
|
||||
{
|
||||
return g_FilterSystem;
|
||||
}
|
||||
|
||||
void PerformFiltering()
|
||||
{
|
||||
UpdateFilters();
|
||||
SceneChangeNotify();
|
||||
}
|
||||
|
||||
class ToggleFilterFlag
|
||||
{
|
||||
const unsigned int m_mask;
|
||||
public:
|
||||
ToggleItem m_item;
|
||||
|
||||
ToggleFilterFlag(unsigned int mask) : m_mask(mask), m_item(ActiveCaller(*this))
|
||||
{
|
||||
}
|
||||
ToggleFilterFlag(const ToggleFilterFlag& other) : m_mask(other.m_mask), m_item(ActiveCaller(*this))
|
||||
{
|
||||
}
|
||||
void active(const BoolImportCallback& importCallback)
|
||||
{
|
||||
importCallback((g_filters_globals.exclude & m_mask) != 0);
|
||||
}
|
||||
typedef MemberCaller1<ToggleFilterFlag, const BoolImportCallback&, &ToggleFilterFlag::active> ActiveCaller;
|
||||
void toggle()
|
||||
{
|
||||
g_filters_globals.exclude ^= m_mask;
|
||||
m_item.update();
|
||||
PerformFiltering();
|
||||
}
|
||||
typedef MemberCaller<ToggleFilterFlag, &ToggleFilterFlag::toggle> ToggleCaller;
|
||||
};
|
||||
|
||||
|
||||
typedef std::list<ToggleFilterFlag> ToggleFilterFlags;
|
||||
ToggleFilterFlags g_filter_items;
|
||||
|
||||
void add_filter_command(unsigned int flag, const char* command, const Accelerator& accelerator)
|
||||
{
|
||||
g_filter_items.push_back(ToggleFilterFlag(flag));
|
||||
GlobalToggles_insert(command, ToggleFilterFlag::ToggleCaller(g_filter_items.back()), ToggleItem::AddCallbackCaller(g_filter_items.back().m_item), accelerator);
|
||||
}
|
||||
|
||||
void Filters_constructMenu(GtkMenu* menu_in_menu)
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "World", "FilterWorldBrushes");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Entities", "FilterEntities");
|
||||
if(g_pGameDescription->mGameType == "doom3")
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Visportals", "FilterVisportals");
|
||||
}
|
||||
else
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Areaportals", "FilterAreaportals");
|
||||
}
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Translucent", "FilterTranslucent");
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Liquids", "FilterLiquids");
|
||||
}
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Caulk", "FilterCaulk");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Clips", "FilterClips");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Paths", "FilterPaths");
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Clusterportals", "FilterClusterportals");
|
||||
}
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Lights", "FilterLights");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Structural", "FilterStructural");
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Lightgrid", "FilterLightgrid");
|
||||
}
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Patches", "FilterPatches");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Details", "FilterDetails");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Hints", "FilterHintsSkips");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Models", "FilterModels");
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Triggers", "FilterTriggers");
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu_in_menu, "Botclips", "FilterBotClips");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void ConstructFilters()
|
||||
{
|
||||
GlobalPreferenceSystem().registerPreference("SI_Exclude", SizeImportStringCaller(g_filters_globals.exclude), SizeExportStringCaller(g_filters_globals.exclude));
|
||||
|
||||
add_filter_command(EXCLUDE_WORLD, "FilterWorldBrushes", Accelerator('1', (GdkModifierType)GDK_MOD1_MASK));
|
||||
add_filter_command(EXCLUDE_ENT, "FilterEntities", Accelerator('2', (GdkModifierType)GDK_MOD1_MASK));
|
||||
if(g_pGameDescription->mGameType == "doom3")
|
||||
{
|
||||
add_filter_command(EXCLUDE_VISPORTALS, "FilterVisportals", Accelerator('3', (GdkModifierType)GDK_MOD1_MASK));
|
||||
}
|
||||
else
|
||||
{
|
||||
add_filter_command(EXCLUDE_AREAPORTALS, "FilterAreaportals", Accelerator('3', (GdkModifierType)GDK_MOD1_MASK));
|
||||
}
|
||||
add_filter_command(EXCLUDE_TRANSLUCENT, "FilterTranslucent", Accelerator('4', (GdkModifierType)GDK_MOD1_MASK));
|
||||
add_filter_command(EXCLUDE_LIQUIDS, "FilterLiquids", Accelerator('5', (GdkModifierType)GDK_MOD1_MASK));
|
||||
add_filter_command(EXCLUDE_CAULK, "FilterCaulk", Accelerator('6', (GdkModifierType)GDK_MOD1_MASK ));
|
||||
add_filter_command(EXCLUDE_CLIP, "FilterClips", Accelerator('7', (GdkModifierType)GDK_MOD1_MASK));
|
||||
add_filter_command(EXCLUDE_PATHS, "FilterPaths", Accelerator('8', (GdkModifierType)GDK_MOD1_MASK));
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
add_filter_command(EXCLUDE_CLUSTERPORTALS, "FilterClusterportals", Accelerator('9', (GdkModifierType)GDK_MOD1_MASK));
|
||||
}
|
||||
add_filter_command(EXCLUDE_LIGHTS, "FilterLights", Accelerator('0', (GdkModifierType)GDK_MOD1_MASK));
|
||||
add_filter_command(EXCLUDE_STRUCTURAL, "FilterStructural", Accelerator('D', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
add_filter_command(EXCLUDE_LIGHTGRID, "FilterLightgrid", accelerator_null());
|
||||
}
|
||||
add_filter_command(EXCLUDE_CURVES, "FilterPatches", Accelerator('P', (GdkModifierType)GDK_CONTROL_MASK));
|
||||
add_filter_command(EXCLUDE_DETAILS, "FilterDetails", Accelerator('D', (GdkModifierType)GDK_CONTROL_MASK));
|
||||
add_filter_command(EXCLUDE_HINTSSKIPS, "FilterHintsSkips", Accelerator('H', (GdkModifierType)GDK_CONTROL_MASK));
|
||||
add_filter_command(EXCLUDE_MODELS, "FilterModels", Accelerator('M', (GdkModifierType)GDK_SHIFT_MASK));
|
||||
add_filter_command(EXCLUDE_TRIGGERS, "FilterTriggers", Accelerator('T', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
|
||||
if(g_pGameDescription->mGameType != "doom3")
|
||||
{
|
||||
add_filter_command(EXCLUDE_BOTCLIP, "FilterBotClips", Accelerator('M', (GdkModifierType)GDK_MOD1_MASK));
|
||||
}
|
||||
|
||||
PerformFiltering();
|
||||
}
|
||||
|
||||
void DestroyFilters()
|
||||
{
|
||||
g_filters.clear();
|
||||
}
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
class FilterAPI
|
||||
{
|
||||
FilterSystem* m_filter;
|
||||
public:
|
||||
typedef FilterSystem Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
FilterAPI()
|
||||
{
|
||||
ConstructFilters();
|
||||
|
||||
m_filter = &GetFilterSystem();
|
||||
}
|
||||
~FilterAPI()
|
||||
{
|
||||
DestroyFilters();
|
||||
}
|
||||
FilterSystem* getTable()
|
||||
{
|
||||
return m_filter;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<FilterAPI> FilterModule;
|
||||
typedef Static<FilterModule> StaticFilterModule;
|
||||
StaticRegisterModule staticRegisterFilter(StaticFilterModule::instance());
|
||||
|
||||
|
||||
28
radiant/filters.h
Normal file
28
radiant/filters.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_FILTERS_H)
|
||||
#define INCLUDED_FILTERS_H
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Filters_constructMenu(GtkMenu* menu_in_menu);
|
||||
|
||||
#endif
|
||||
299
radiant/findtexturedialog.cpp
Normal file
299
radiant/findtexturedialog.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
//
|
||||
// Find/Replace textures dialogs
|
||||
//
|
||||
// Leonardo Zide (leo@lokigames.com)
|
||||
//
|
||||
|
||||
#include "findtexturedialog.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "ishaders.h"
|
||||
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
#include <gtk/gtkvbox.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtktable.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtktogglebutton.h>
|
||||
#include <gtk/gtkcheckbutton.h>
|
||||
#include <gtk/gtkmenuitem.h>
|
||||
#include <gtk/gtkarrow.h>
|
||||
|
||||
#include "gtkutil/window.h"
|
||||
#include "stream/stringstream.h"
|
||||
|
||||
#include "commands.h"
|
||||
#include "dialog.h"
|
||||
#include "select.h"
|
||||
#include "textureentry.h"
|
||||
|
||||
|
||||
|
||||
class FindTextureDialog : public Dialog
|
||||
{
|
||||
public:
|
||||
static void setReplaceStr(const char* name);
|
||||
static void setFindStr(const char* name);
|
||||
static bool isOpen();
|
||||
static void show();
|
||||
static void updateTextures(const char* name);
|
||||
|
||||
FindTextureDialog();
|
||||
virtual ~FindTextureDialog();
|
||||
GtkWindow* BuildDialog();
|
||||
|
||||
void constructWindow(GtkWindow* parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
Create();
|
||||
}
|
||||
void destroyWindow()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
bool m_bSelectedOnly;
|
||||
CopiedString m_strFind;
|
||||
CopiedString m_strReplace;
|
||||
};
|
||||
|
||||
FindTextureDialog g_FindTextureDialog;
|
||||
static bool g_bFindActive = true;
|
||||
|
||||
namespace
|
||||
{
|
||||
void FindTextureDialog_apply()
|
||||
{
|
||||
StringOutputStream find(256);
|
||||
find << "textures/" << g_FindTextureDialog.m_strFind.c_str();
|
||||
StringOutputStream replace(256);
|
||||
replace << "textures/" << g_FindTextureDialog.m_strReplace.c_str();
|
||||
FindReplaceTextures(find.c_str(), replace.c_str(), g_FindTextureDialog.m_bSelectedOnly);
|
||||
}
|
||||
|
||||
static void OnApply(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
g_FindTextureDialog.exportData();
|
||||
FindTextureDialog_apply();
|
||||
}
|
||||
|
||||
static void OnFind(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
g_FindTextureDialog.exportData();
|
||||
FindTextureDialog_apply();
|
||||
}
|
||||
|
||||
static void OnOK(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
g_FindTextureDialog.exportData();
|
||||
FindTextureDialog_apply();
|
||||
g_FindTextureDialog.HideDlg();
|
||||
}
|
||||
|
||||
static void OnClose(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
g_FindTextureDialog.HideDlg();
|
||||
}
|
||||
|
||||
|
||||
static gint find_focus_in (GtkWidget* widget, GdkEventFocus *event, gpointer data)
|
||||
{
|
||||
g_bFindActive = true;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint replace_focus_in (GtkWidget* widget, GdkEventFocus *event, gpointer data)
|
||||
{
|
||||
g_bFindActive = false;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// FindTextureDialog class
|
||||
|
||||
FindTextureDialog::FindTextureDialog()
|
||||
{
|
||||
m_bSelectedOnly = FALSE;
|
||||
}
|
||||
|
||||
FindTextureDialog::~FindTextureDialog()
|
||||
{
|
||||
}
|
||||
|
||||
GtkWindow* FindTextureDialog::BuildDialog()
|
||||
{
|
||||
GtkWidget* vbox, *hbox, *table, *label;
|
||||
GtkWidget* button, *check, *entry;
|
||||
|
||||
GtkWindow* dlg = create_floating_window("Find / Replace Texture(s)", m_parent);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 5);
|
||||
gtk_widget_show (hbox);
|
||||
gtk_container_add(GTK_CONTAINER(dlg), GTK_WIDGET(hbox));
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 5);
|
||||
gtk_widget_show (vbox);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
|
||||
|
||||
table = gtk_table_new (2, 2, FALSE);
|
||||
gtk_widget_show (table);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), TRUE, TRUE, 0);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 5);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 5);
|
||||
|
||||
label = gtk_label_new ("Find:");
|
||||
gtk_widget_show (label);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
|
||||
(GtkAttachOptions) (GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
||||
|
||||
label = gtk_label_new ("Replace:");
|
||||
gtk_widget_show (label);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
|
||||
(GtkAttachOptions) (GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
|
||||
|
||||
entry = gtk_entry_new();
|
||||
gtk_widget_show (entry);
|
||||
gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
|
||||
(GtkAttachOptions) (GTK_EXPAND|GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
g_signal_connect(G_OBJECT(entry), "focus_in_event",
|
||||
G_CALLBACK(find_focus_in), 0);
|
||||
AddDialogData(*GTK_ENTRY(entry), m_strFind);
|
||||
GlobalTextureEntryCompletion::instance().connect(GTK_ENTRY(entry));
|
||||
|
||||
entry = gtk_entry_new();
|
||||
gtk_widget_show (entry);
|
||||
gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
|
||||
(GtkAttachOptions) (GTK_EXPAND|GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
g_signal_connect(G_OBJECT(entry), "focus_in_event",
|
||||
G_CALLBACK(replace_focus_in), 0);
|
||||
AddDialogData(*GTK_ENTRY(entry), m_strReplace);
|
||||
GlobalTextureEntryCompletion::instance().connect(GTK_ENTRY(entry));
|
||||
|
||||
check = gtk_check_button_new_with_label ("Within selected brushes only");
|
||||
gtk_widget_show (check);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), check, TRUE, TRUE, 0);
|
||||
AddDialogData(*GTK_TOGGLE_BUTTON(check), m_bSelectedOnly);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 5);
|
||||
gtk_widget_show (vbox);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
|
||||
|
||||
button = gtk_button_new_with_label ("Apply");
|
||||
gtk_widget_show (button);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
|
||||
g_signal_connect(G_OBJECT(button), "clicked",
|
||||
G_CALLBACK(OnApply), 0);
|
||||
gtk_widget_set_usize (button, 60, -2);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_widget_show (button);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
|
||||
g_signal_connect(G_OBJECT(button), "clicked",
|
||||
G_CALLBACK(OnClose), 0);
|
||||
gtk_widget_set_usize (button, 60, -2);
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void FindTextureDialog::updateTextures(const char* name)
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
if (g_bFindActive)
|
||||
{
|
||||
setFindStr(name + 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
setReplaceStr(name + 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FindTextureDialog::isOpen()
|
||||
{
|
||||
return GTK_WIDGET_VISIBLE(g_FindTextureDialog.GetWidget()) == TRUE;
|
||||
}
|
||||
|
||||
void FindTextureDialog::setFindStr(const char* name)
|
||||
{
|
||||
g_FindTextureDialog.exportData();
|
||||
g_FindTextureDialog.m_strFind = name;
|
||||
g_FindTextureDialog.importData();
|
||||
}
|
||||
|
||||
void FindTextureDialog::setReplaceStr(const char* name)
|
||||
{
|
||||
g_FindTextureDialog.exportData();
|
||||
g_FindTextureDialog.m_strReplace = name;
|
||||
g_FindTextureDialog.importData();
|
||||
}
|
||||
|
||||
void FindTextureDialog::show()
|
||||
{
|
||||
g_FindTextureDialog.ShowDlg();
|
||||
}
|
||||
|
||||
|
||||
void FindTextureDialog_constructWindow(GtkWindow* main_window)
|
||||
{
|
||||
g_FindTextureDialog.constructWindow(main_window);
|
||||
}
|
||||
|
||||
void FindTextureDialog_destroyWindow()
|
||||
{
|
||||
g_FindTextureDialog.destroyWindow();
|
||||
}
|
||||
|
||||
bool FindTextureDialog_isOpen()
|
||||
{
|
||||
return g_FindTextureDialog.isOpen();
|
||||
}
|
||||
|
||||
void FindTextureDialog_selectTexture(const char* name)
|
||||
{
|
||||
g_FindTextureDialog.updateTextures(name);
|
||||
}
|
||||
|
||||
void FindTextureDialog_Construct()
|
||||
{
|
||||
GlobalCommands_insert("FindReplaceTextures", FreeCaller<FindTextureDialog::show>());
|
||||
}
|
||||
|
||||
void FindTextureDialog_Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
34
radiant/findtexturedialog.h
Normal file
34
radiant/findtexturedialog.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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_FINDTEXTUREDIALOG_H)
|
||||
#define INCLUDED_FINDTEXTUREDIALOG_H
|
||||
|
||||
void FindTextureDialog_Construct();
|
||||
void FindTextureDialog_Destroy();
|
||||
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
void FindTextureDialog_constructWindow(GtkWindow* main_window);
|
||||
void FindTextureDialog_destroyWindow();
|
||||
bool FindTextureDialog_isOpen();
|
||||
void FindTextureDialog_selectTexture(const char* name);
|
||||
|
||||
#endif
|
||||
55
radiant/glwidget.cpp
Normal file
55
radiant/glwidget.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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 "glwidget.h"
|
||||
|
||||
#include "igtkgl.h"
|
||||
#include "modulesystem.h"
|
||||
#include "gtkutil/glwidget.h"
|
||||
|
||||
class GtkGLAPI
|
||||
{
|
||||
_QERGtkGLTable m_gtkgl;
|
||||
public:
|
||||
typedef _QERGtkGLTable Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
GtkGLAPI()
|
||||
{
|
||||
m_gtkgl.glwidget_new = &glwidget_new;
|
||||
m_gtkgl.glwidget_swap_buffers = &glwidget_swap_buffers;
|
||||
m_gtkgl.glwidget_make_current = &glwidget_make_current;
|
||||
m_gtkgl.glwidget_destroy_context = &glwidget_destroy_context;
|
||||
m_gtkgl.glwidget_create_context = &glwidget_create_context;
|
||||
}
|
||||
_QERGtkGLTable* getTable()
|
||||
{
|
||||
return &m_gtkgl;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<GtkGLAPI> GtkGLModule;
|
||||
typedef Static<GtkGLModule> StaticGtkGLModule;
|
||||
StaticRegisterModule staticRegisterGtkGL(StaticGtkGLModule::instance());
|
||||
|
||||
25
radiant/glwidget.h
Normal file
25
radiant/glwidget.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_GLWIDGET_H)
|
||||
#define INCLUDED_GLWIDGET_H
|
||||
|
||||
#endif
|
||||
270
radiant/grid.cpp
Normal file
270
radiant/grid.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
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 "grid.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "preferencesystem.h"
|
||||
|
||||
#include "gtkutil/widget.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include "gtkmisc.h"
|
||||
#include "commands.h"
|
||||
#include "preferences.h"
|
||||
|
||||
|
||||
|
||||
std::vector<Callback> g_gridChange_callbacks;
|
||||
|
||||
void AddGridChangeCallback(const Callback& callback)
|
||||
{
|
||||
g_gridChange_callbacks.push_back(callback);
|
||||
callback();
|
||||
}
|
||||
|
||||
void GridChangeNotify()
|
||||
{
|
||||
std::for_each(g_gridChange_callbacks.begin(), g_gridChange_callbacks.end(), CallbackInvoke());
|
||||
}
|
||||
|
||||
enum GridPower
|
||||
{
|
||||
GRIDPOWER_0125 = -3,
|
||||
GRIDPOWER_025 = -2,
|
||||
GRIDPOWER_05 = -1,
|
||||
GRIDPOWER_1 = 0,
|
||||
GRIDPOWER_2 = 1,
|
||||
GRIDPOWER_4 = 2,
|
||||
GRIDPOWER_8 = 3,
|
||||
GRIDPOWER_16 = 4,
|
||||
GRIDPOWER_32 = 5,
|
||||
GRIDPOWER_64 = 6,
|
||||
GRIDPOWER_128 = 7,
|
||||
GRIDPOWER_256 = 8,
|
||||
};
|
||||
|
||||
|
||||
typedef const char* GridName;
|
||||
// this must match the GridPower enumeration
|
||||
const GridName g_gridnames[] = {
|
||||
"0.125",
|
||||
"0.25",
|
||||
"0.5",
|
||||
"1",
|
||||
"2",
|
||||
"4",
|
||||
"8",
|
||||
"16",
|
||||
"32",
|
||||
"64",
|
||||
"128",
|
||||
"256",
|
||||
};
|
||||
|
||||
inline GridPower GridPower_forGridDefault(int gridDefault)
|
||||
{
|
||||
return static_cast<GridPower>(gridDefault - 3);
|
||||
}
|
||||
|
||||
inline int GridDefault_forGridPower(GridPower gridPower)
|
||||
{
|
||||
return gridPower + 3;
|
||||
}
|
||||
|
||||
int g_grid_default = GridDefault_forGridPower(GRIDPOWER_8);
|
||||
|
||||
int g_grid_power = GridPower_forGridDefault(g_grid_default);
|
||||
|
||||
int Grid_getPower()
|
||||
{
|
||||
return g_grid_power;
|
||||
}
|
||||
|
||||
inline float GridSize_forGridPower(int gridPower)
|
||||
{
|
||||
return pow(2.0f, gridPower);
|
||||
}
|
||||
|
||||
float g_gridsize = GridSize_forGridPower(g_grid_power);
|
||||
|
||||
float GetGridSize()
|
||||
{
|
||||
return g_gridsize;
|
||||
}
|
||||
|
||||
|
||||
void setGridPower(GridPower power);
|
||||
|
||||
class GridMenuItem
|
||||
{
|
||||
GridPower m_id;
|
||||
|
||||
GridMenuItem(const GridMenuItem& other); // NOT COPYABLE
|
||||
GridMenuItem& operator=(const GridMenuItem& other); // NOT ASSIGNABLE
|
||||
public:
|
||||
ToggleItem m_item;
|
||||
|
||||
GridMenuItem(GridPower id) : m_id(id), m_item(ExportCaller(*this))
|
||||
{
|
||||
}
|
||||
void set()
|
||||
{
|
||||
g_grid_power = m_id;
|
||||
m_item.update();
|
||||
setGridPower(m_id);
|
||||
}
|
||||
typedef MemberCaller<GridMenuItem, &GridMenuItem::set> SetCaller;
|
||||
void active(const BoolImportCallback& importCallback)
|
||||
{
|
||||
importCallback(g_grid_power == m_id);
|
||||
}
|
||||
typedef MemberCaller1<GridMenuItem, const BoolImportCallback&, &GridMenuItem::active> ExportCaller;
|
||||
};
|
||||
|
||||
GridMenuItem g_gridMenu0125(GRIDPOWER_0125);
|
||||
GridMenuItem g_gridMenu025(GRIDPOWER_025);
|
||||
GridMenuItem g_gridMenu05(GRIDPOWER_05);
|
||||
GridMenuItem g_gridMenu1(GRIDPOWER_1);
|
||||
GridMenuItem g_gridMenu2(GRIDPOWER_2);
|
||||
GridMenuItem g_gridMenu4(GRIDPOWER_4);
|
||||
GridMenuItem g_gridMenu8(GRIDPOWER_8);
|
||||
GridMenuItem g_gridMenu16(GRIDPOWER_16);
|
||||
GridMenuItem g_gridMenu32(GRIDPOWER_32);
|
||||
GridMenuItem g_gridMenu64(GRIDPOWER_64);
|
||||
GridMenuItem g_gridMenu128(GRIDPOWER_128);
|
||||
GridMenuItem g_gridMenu256(GRIDPOWER_256);
|
||||
|
||||
void setGridPower(GridPower power)
|
||||
{
|
||||
g_gridsize = GridSize_forGridPower(power);
|
||||
|
||||
g_gridMenu0125.m_item.update();
|
||||
g_gridMenu025.m_item.update();
|
||||
g_gridMenu05.m_item.update();
|
||||
g_gridMenu1.m_item.update();
|
||||
g_gridMenu2.m_item.update();
|
||||
g_gridMenu4.m_item.update();
|
||||
g_gridMenu8.m_item.update();
|
||||
g_gridMenu16.m_item.update();
|
||||
g_gridMenu32.m_item.update();
|
||||
g_gridMenu64.m_item.update();
|
||||
g_gridMenu128.m_item.update();
|
||||
g_gridMenu256.m_item.update();
|
||||
GridChangeNotify();
|
||||
}
|
||||
|
||||
void GridPrev()
|
||||
{
|
||||
if(g_grid_power > GRIDPOWER_0125)
|
||||
{
|
||||
setGridPower(static_cast<GridPower>(--g_grid_power));
|
||||
}
|
||||
}
|
||||
|
||||
void GridNext()
|
||||
{
|
||||
if(g_grid_power < GRIDPOWER_256)
|
||||
{
|
||||
setGridPower(static_cast<GridPower>(++g_grid_power));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Grid_registerCommands()
|
||||
{
|
||||
GlobalCommands_insert("GridDown", FreeCaller<GridPrev>(), Accelerator('['));
|
||||
GlobalCommands_insert("GridUp", FreeCaller<GridNext>(), Accelerator(']'));
|
||||
|
||||
GlobalToggles_insert("SetGrid0.125", GridMenuItem::SetCaller(g_gridMenu0125), ToggleItem::AddCallbackCaller(g_gridMenu0125.m_item));
|
||||
GlobalToggles_insert("SetGrid0.25", GridMenuItem::SetCaller(g_gridMenu025), ToggleItem::AddCallbackCaller(g_gridMenu025.m_item));
|
||||
GlobalToggles_insert("SetGrid0.5", GridMenuItem::SetCaller(g_gridMenu05), ToggleItem::AddCallbackCaller(g_gridMenu05.m_item));
|
||||
GlobalToggles_insert("SetGrid1", GridMenuItem::SetCaller(g_gridMenu1), ToggleItem::AddCallbackCaller(g_gridMenu1.m_item), Accelerator('1'));
|
||||
GlobalToggles_insert("SetGrid2", GridMenuItem::SetCaller(g_gridMenu2), ToggleItem::AddCallbackCaller(g_gridMenu2.m_item), Accelerator('2'));
|
||||
GlobalToggles_insert("SetGrid4", GridMenuItem::SetCaller(g_gridMenu4), ToggleItem::AddCallbackCaller(g_gridMenu4.m_item), Accelerator('3'));
|
||||
GlobalToggles_insert("SetGrid8", GridMenuItem::SetCaller(g_gridMenu8), ToggleItem::AddCallbackCaller(g_gridMenu8.m_item), Accelerator('4'));
|
||||
GlobalToggles_insert("SetGrid16", GridMenuItem::SetCaller(g_gridMenu16), ToggleItem::AddCallbackCaller(g_gridMenu16.m_item), Accelerator('5'));
|
||||
GlobalToggles_insert("SetGrid32", GridMenuItem::SetCaller(g_gridMenu32), ToggleItem::AddCallbackCaller(g_gridMenu32.m_item), Accelerator('6'));
|
||||
GlobalToggles_insert("SetGrid64", GridMenuItem::SetCaller(g_gridMenu64), ToggleItem::AddCallbackCaller(g_gridMenu64.m_item), Accelerator('7'));
|
||||
GlobalToggles_insert("SetGrid128", GridMenuItem::SetCaller(g_gridMenu128), ToggleItem::AddCallbackCaller(g_gridMenu128.m_item), Accelerator('8'));
|
||||
GlobalToggles_insert("SetGrid256", GridMenuItem::SetCaller(g_gridMenu256), ToggleItem::AddCallbackCaller(g_gridMenu256.m_item), Accelerator('9'));
|
||||
}
|
||||
|
||||
|
||||
void Grid_constructMenu(GtkMenu* menu)
|
||||
{
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid0.125", "SetGrid0.125");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid0.25", "SetGrid0.25");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid0.5", "SetGrid0.5");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid1", "SetGrid1");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid2", "SetGrid2");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid4", "SetGrid4");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid8", "SetGrid8");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid16", "SetGrid16");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid32", "SetGrid32");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid64", "SetGrid64");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid128", "SetGrid128");
|
||||
create_check_menu_item_with_mnemonic(menu, "Grid256", "SetGrid256");
|
||||
}
|
||||
|
||||
void Grid_registerShortcuts()
|
||||
{
|
||||
command_connect_accelerator("ToggleGrid");
|
||||
command_connect_accelerator("GridDown");
|
||||
command_connect_accelerator("GridUp");
|
||||
}
|
||||
|
||||
void Grid_constructPreferences(PreferencesPage& page)
|
||||
{
|
||||
page.appendCombo(
|
||||
"Default grid spacing",
|
||||
g_grid_default,
|
||||
ARRAY_RANGE(g_gridnames)
|
||||
);
|
||||
}
|
||||
void Grid_constructPage(PreferenceGroup& group)
|
||||
{
|
||||
PreferencesPage page(group.createPage("Grid", "Grid Settings"));
|
||||
Grid_constructPreferences(page);
|
||||
}
|
||||
void Grid_registerPreferencesPage()
|
||||
{
|
||||
PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, Grid_constructPage>());
|
||||
}
|
||||
|
||||
void Grid_construct()
|
||||
{
|
||||
Grid_registerPreferencesPage();
|
||||
|
||||
g_grid_default = GridDefault_forGridPower(GRIDPOWER_8);
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("GridDefault", IntImportStringCaller(g_grid_default), IntExportStringCaller(g_grid_default));
|
||||
|
||||
g_grid_power = GridPower_forGridDefault(g_grid_default);
|
||||
g_gridsize = GridSize_forGridPower(g_grid_power);
|
||||
}
|
||||
|
||||
void Grid_destroy()
|
||||
{
|
||||
}
|
||||
40
radiant/grid.h
Normal file
40
radiant/grid.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_GRID_H)
|
||||
#define INCLUDED_GRID_H
|
||||
|
||||
float GetGridSize();
|
||||
int Grid_getPower();
|
||||
|
||||
class Callback;
|
||||
void AddGridChangeCallback(const Callback& callback);
|
||||
|
||||
void Grid_registerCommands();
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Grid_constructMenu(GtkMenu* menu);
|
||||
|
||||
void Grid_registerShortcuts();
|
||||
|
||||
void Grid_construct();
|
||||
void Grid_destroy();
|
||||
|
||||
#endif
|
||||
232
radiant/groupdialog.cpp
Normal file
232
radiant/groupdialog.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
//
|
||||
// Floating dialog that contains a notebook with at least Entities and Group tabs
|
||||
// I merged the 2 MS Windows dialogs in a single class
|
||||
//
|
||||
// Leonardo Zide (leo@lokigames.com)
|
||||
//
|
||||
|
||||
#include "groupdialog.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtk/gtknotebook.h>
|
||||
#include <gtk/gtktextview.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
|
||||
#include "gtkutil/widget.h"
|
||||
#include "gtkutil/accelerator.h"
|
||||
#include "entityinspector.h"
|
||||
#include "gtkmisc.h"
|
||||
#include "multimon.h"
|
||||
#include "console.h"
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include "gtkutil/window.h"
|
||||
|
||||
class GroupDlg
|
||||
{
|
||||
public:
|
||||
GtkWidget* m_pNotebook;
|
||||
GtkWindow* m_window;
|
||||
|
||||
GroupDlg();
|
||||
void Create(GtkWindow* parent);
|
||||
|
||||
void Show()
|
||||
{
|
||||
// workaround for strange gtk behaviour - modifying the contents of a window while it is not visible causes the window position to change without sending a configure_event
|
||||
m_position_tracker.sync(m_window);
|
||||
gtk_widget_show(GTK_WIDGET(m_window));
|
||||
}
|
||||
void Hide()
|
||||
{
|
||||
gtk_widget_hide(GTK_WIDGET(m_window));
|
||||
}
|
||||
|
||||
WindowPositionTracker m_position_tracker;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
GroupDlg g_GroupDlg;
|
||||
|
||||
std::size_t g_current_page;
|
||||
std::vector<StringExportCallback> g_pages;
|
||||
}
|
||||
|
||||
void GroupDialog_updatePageTitle(GtkWindow* window, std::size_t pageIndex)
|
||||
{
|
||||
if(pageIndex < g_pages.size())
|
||||
{
|
||||
g_pages[pageIndex](PointerCaller1<GtkWindow, const char*, gtk_window_set_title>(window));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean switch_page(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
|
||||
{
|
||||
GroupDialog_updatePageTitle(GTK_WINDOW(data), page_num);
|
||||
g_current_page = page_num;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GroupDlg::GroupDlg() : m_window(0)
|
||||
{
|
||||
m_position_tracker.setPosition(c_default_window_pos);
|
||||
}
|
||||
|
||||
void GroupDlg::Create(GtkWindow* parent)
|
||||
{
|
||||
ASSERT_MESSAGE(m_window == 0, "dialog already created");
|
||||
|
||||
GtkWindow* window = create_persistent_floating_window("Entities", parent);
|
||||
|
||||
global_accel_connect_window(window);
|
||||
|
||||
window_connect_focus_in_clear_focus_widget(window);
|
||||
|
||||
m_window = window;
|
||||
|
||||
#ifdef WIN32
|
||||
if( g_multimon_globals.m_bStartOnPrimMon )
|
||||
{
|
||||
WindowPosition pos(m_position_tracker.getPosition());
|
||||
PositionWindowOnPrimaryScreen(pos);
|
||||
m_position_tracker.setPosition(pos);
|
||||
}
|
||||
#endif
|
||||
m_position_tracker.connect(window);
|
||||
|
||||
{
|
||||
GtkWidget* notebook = gtk_notebook_new();
|
||||
gtk_widget_show(notebook);
|
||||
gtk_container_add (GTK_CONTAINER (window), notebook);
|
||||
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
|
||||
m_pNotebook = notebook;
|
||||
|
||||
g_signal_connect(G_OBJECT(notebook), "switch_page", G_CALLBACK(switch_page), window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GtkWidget* GroupDialog_addPage(const char* tabLabel, GtkWidget* widget, const StringExportCallback& title)
|
||||
{
|
||||
GtkWidget* w = gtk_label_new(tabLabel);
|
||||
gtk_widget_show(w);
|
||||
GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), gtk_notebook_insert_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), widget, w, -1));
|
||||
g_pages.push_back(title);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
bool GroupDialog_isShown()
|
||||
{
|
||||
return widget_is_visible(GTK_WIDGET(g_GroupDlg.m_window));
|
||||
}
|
||||
void GroupDialog_setShown(bool shown)
|
||||
{
|
||||
shown ? g_GroupDlg.Show() : g_GroupDlg.Hide();
|
||||
}
|
||||
void GroupDialog_ToggleShow()
|
||||
{
|
||||
GroupDialog_setShown(!GroupDialog_isShown());
|
||||
}
|
||||
|
||||
void GroupDialog_constructWindow(GtkWindow* main_window)
|
||||
{
|
||||
g_GroupDlg.Create(main_window);
|
||||
}
|
||||
void GroupDialog_destroyWindow()
|
||||
{
|
||||
ASSERT_NOTNULL(g_GroupDlg.m_window);
|
||||
destroy_floating_window(g_GroupDlg.m_window);
|
||||
g_GroupDlg.m_window = 0;
|
||||
}
|
||||
|
||||
|
||||
GtkWindow* GroupDialog_getWindow()
|
||||
{
|
||||
return g_GroupDlg.m_window;
|
||||
}
|
||||
void GroupDialog_show()
|
||||
{
|
||||
g_GroupDlg.Show();
|
||||
}
|
||||
|
||||
GtkWidget* GroupDialog_getPage()
|
||||
{
|
||||
return gtk_notebook_get_nth_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), gint(g_current_page));
|
||||
}
|
||||
|
||||
void GroupDialog_setPage(GtkWidget* page)
|
||||
{
|
||||
g_current_page = gtk_notebook_page_num(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), page);
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), gint(g_current_page));
|
||||
}
|
||||
|
||||
void GroupDialog_showPage(GtkWidget* page)
|
||||
{
|
||||
if(GroupDialog_getPage() == page)
|
||||
{
|
||||
GroupDialog_ToggleShow();
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_show(GTK_WIDGET(g_GroupDlg.m_window));
|
||||
GroupDialog_setPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
void GroupDialog_cycle()
|
||||
{
|
||||
g_current_page = (g_current_page + 1) % g_pages.size();
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(g_GroupDlg.m_pNotebook), gint(g_current_page));
|
||||
}
|
||||
|
||||
void GroupDialog_updatePageTitle(GtkWidget* page)
|
||||
{
|
||||
if(GroupDialog_getPage() == page)
|
||||
{
|
||||
GroupDialog_updatePageTitle(g_GroupDlg.m_window, g_current_page);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "preferencesystem.h"
|
||||
|
||||
void GroupDialog_Construct()
|
||||
{
|
||||
GlobalPreferenceSystem().registerPreference("EntityWnd", WindowPositionTrackerImportStringCaller(g_GroupDlg.m_position_tracker), WindowPositionTrackerExportStringCaller(g_GroupDlg.m_position_tracker));
|
||||
|
||||
GlobalCommands_insert("ViewEntityInfo", FreeCaller<GroupDialog_ToggleShow>(), Accelerator('N'));
|
||||
}
|
||||
void GroupDialog_Destroy()
|
||||
{
|
||||
}
|
||||
48
radiant/groupdialog.h
Normal file
48
radiant/groupdialog.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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_GROUPDIALOG_H)
|
||||
#define INCLUDED_GROUPDIALOG_H
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
|
||||
void GroupDialog_Construct();
|
||||
void GroupDialog_Destroy();
|
||||
|
||||
void GroupDialog_constructWindow(GtkWindow* main_window);
|
||||
void GroupDialog_destroyWindow();
|
||||
GtkWindow* GroupDialog_getWindow();
|
||||
void GroupDialog_show();
|
||||
|
||||
inline void RawStringExport(const char* string, const StringImportCallback& importer)
|
||||
{
|
||||
importer(string);
|
||||
}
|
||||
typedef ConstPointerCaller1<char, const StringImportCallback&, RawStringExport> RawStringExportCaller;
|
||||
GtkWidget* GroupDialog_addPage(const char* tabLabel, GtkWidget* widget, const StringExportCallback& title);
|
||||
|
||||
void GroupDialog_showPage(GtkWidget* page);
|
||||
void GroupDialog_updatePageTitle(GtkWidget* page);
|
||||
|
||||
#endif
|
||||
1074
radiant/gtkdlgs.cpp
Normal file
1074
radiant/gtkdlgs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
57
radiant/gtkdlgs.h
Normal file
57
radiant/gtkdlgs.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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_GTKDLGS_H)
|
||||
#define INCLUDED_GTKDLGS_H
|
||||
|
||||
#include "qerplugin.h"
|
||||
|
||||
EMessageBoxReturn DoLightIntensityDlg (int *intensity);
|
||||
EMessageBoxReturn DoTextureLayout (float *fx, float *fy);
|
||||
void DoTextEditor (const char* filename, int cursorpos);
|
||||
|
||||
void DoProjectSettings();
|
||||
|
||||
void DoTextureListDlg();
|
||||
void DoFind();
|
||||
void DoSides(int type, int axis);
|
||||
void DoAbout();
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
extern bool g_TextEditor_useWin32Editor;
|
||||
#else
|
||||
#include "string/stringfwd.h"
|
||||
extern bool g_TextEditor_useCustomEditor;
|
||||
extern CopiedString g_TextEditor_editorCommand;
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
164
radiant/gtkmisc.cpp
Normal file
164
radiant/gtkmisc.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Small functions to help with GTK
|
||||
//
|
||||
|
||||
#include "gtkmisc.h"
|
||||
|
||||
#include <gtk/gtkcolorseldialog.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
|
||||
#include "math/vector.h"
|
||||
#include "os/path.h"
|
||||
|
||||
#include "gtkutil/dialog.h"
|
||||
#include "gtkutil/filechooser.h"
|
||||
#include "gtkutil/menu.h"
|
||||
#include "gtkutil/toolbar.h"
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Misc stuff
|
||||
|
||||
void command_connect_accelerator(const char* name)
|
||||
{
|
||||
const Command& command = GlobalCommands_find(name);
|
||||
GlobalShortcuts_register(name);
|
||||
command_connect_accelerator(command.m_accelerator, command.m_callback);
|
||||
}
|
||||
|
||||
void command_disconnect_accelerator(const char* name)
|
||||
{
|
||||
const Command& command = GlobalCommands_find(name);
|
||||
command_disconnect_accelerator(command.m_accelerator, command.m_callback);
|
||||
}
|
||||
|
||||
void toggle_add_accelerator(const char* name)
|
||||
{
|
||||
const Toggle& toggle = GlobalToggles_find(name);
|
||||
GlobalShortcuts_register(name);
|
||||
command_connect_accelerator(toggle.m_command.m_accelerator, toggle.m_command.m_callback);
|
||||
}
|
||||
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const char* commandName)
|
||||
{
|
||||
GlobalShortcuts_register(commandName);
|
||||
const Toggle& toggle = GlobalToggles_find(commandName);
|
||||
command_connect_accelerator(toggle.m_command.m_accelerator, toggle.m_command.m_callback);
|
||||
return create_check_menu_item_with_mnemonic(menu, mnemonic, toggle);
|
||||
}
|
||||
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu* menu, const char *mnemonic, const char* commandName)
|
||||
{
|
||||
GlobalShortcuts_register(commandName);
|
||||
const Command& command = GlobalCommands_find(commandName);
|
||||
command_connect_accelerator(command.m_accelerator, command.m_callback);
|
||||
return create_menu_item_with_mnemonic(menu, mnemonic, command);
|
||||
}
|
||||
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const char* commandName)
|
||||
{
|
||||
return toolbar_append_button(toolbar, description, icon, GlobalCommands_find(commandName));
|
||||
}
|
||||
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const char* commandName)
|
||||
{
|
||||
return toolbar_append_toggle_button(toolbar, description, icon, GlobalToggles_find(commandName));
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// File dialog
|
||||
|
||||
bool color_dialog (GtkWidget *parent, Vector3& color, const char* title)
|
||||
{
|
||||
GtkWidget* dlg;
|
||||
double clr[3];
|
||||
ModalDialog dialog;
|
||||
|
||||
clr[0] = color[0];
|
||||
clr[1] = color[1];
|
||||
clr[2] = color[2];
|
||||
|
||||
dlg = gtk_color_selection_dialog_new (title);
|
||||
gtk_color_selection_set_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), clr);
|
||||
g_signal_connect(G_OBJECT(dlg), "delete_event", G_CALLBACK(dialog_delete_callback), &dialog);
|
||||
g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(dlg)->ok_button), "clicked", G_CALLBACK(dialog_button_ok), &dialog);
|
||||
g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(dlg)->cancel_button), "clicked", G_CALLBACK(dialog_button_cancel), &dialog);
|
||||
|
||||
if (parent != 0)
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (parent));
|
||||
|
||||
bool ok = modal_dialog_show(GTK_WINDOW(dlg), dialog) == eIDOK;
|
||||
if(ok)
|
||||
{
|
||||
GdkColor gdkcolor;
|
||||
gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dlg)->colorsel), &gdkcolor);
|
||||
clr[0] = gdkcolor.red / 65535.0;
|
||||
clr[1] = gdkcolor.green / 65535.0;
|
||||
clr[2] = gdkcolor.blue / 65535.0;
|
||||
|
||||
color[0] = (float)clr[0];
|
||||
color[1] = (float)clr[1];
|
||||
color[2] = (float)clr[2];
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dlg);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void button_clicked_entry_browse_file(GtkWidget* widget, GtkEntry* entry)
|
||||
{
|
||||
const char *filename = file_dialog(gtk_widget_get_toplevel(widget), TRUE, "Choose File", gtk_entry_get_text(entry));
|
||||
|
||||
if(filename != 0)
|
||||
{
|
||||
gtk_entry_set_text(entry, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void button_clicked_entry_browse_directory(GtkWidget* widget, GtkEntry* entry)
|
||||
{
|
||||
const char* text = gtk_entry_get_text(entry);
|
||||
char *dir = dir_dialog(gtk_widget_get_toplevel(widget), "Choose Directory", path_is_absolute(text) ? text : "" );
|
||||
|
||||
if(dir != 0)
|
||||
{
|
||||
gchar* converted = g_filename_to_utf8(dir, -1, 0, 0, 0);
|
||||
gtk_entry_set_text(entry, converted);
|
||||
g_free(dir);
|
||||
g_free(converted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
75
radiant/gtkmisc.h
Normal file
75
radiant/gtkmisc.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
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_GTKMISC_H)
|
||||
#define INCLUDED_GTKMISC_H
|
||||
|
||||
#include <gtk/gtkmain.h>
|
||||
|
||||
inline void process_gui()
|
||||
{
|
||||
while(gtk_events_pending())
|
||||
{
|
||||
gtk_main_iteration();
|
||||
}
|
||||
}
|
||||
|
||||
void command_connect_accelerator(const char* commandName);
|
||||
void command_disconnect_accelerator(const char* commandName);
|
||||
void toggle_add_accelerator(const char* commandName);
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
typedef struct _GtkMenuItem GtkMenuItem;
|
||||
typedef struct _GtkCheckMenuItem GtkCheckMenuItem;
|
||||
|
||||
// this also sets up the shortcut using command_connect_accelerator
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu *menu, const char *mnemonic, const char* commandName);
|
||||
// this also sets up the shortcut using command_connect_accelerator
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const char* commandName);
|
||||
|
||||
typedef struct _GtkButton GtkButton;
|
||||
typedef struct _GtkToggleButton GtkToggleButton;
|
||||
typedef struct _GtkToolbar GtkToolbar;
|
||||
|
||||
// this DOES NOT set up the shortcut using command_connect_accelerator
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const char* commandName);
|
||||
// this DOES NOT set up the shortcut using command_connect_accelerator
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const char* commandName);
|
||||
|
||||
|
||||
template<typename Element> class BasicVector3;
|
||||
typedef BasicVector3<float> Vector3;
|
||||
bool color_dialog (GtkWidget *parent, Vector3& color, const char* title = "Choose Color");
|
||||
|
||||
typedef struct _GtkEntry GtkEntry;
|
||||
void button_clicked_entry_browse_file(GtkWidget* widget, GtkEntry* entry);
|
||||
void button_clicked_entry_browse_directory(GtkWidget* widget, GtkEntry* entry);
|
||||
|
||||
#endif
|
||||
138
radiant/help.cpp
Normal file
138
radiant/help.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
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 "help.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include "libxml/parser.h"
|
||||
#include "generic/callback.h"
|
||||
#include "gtkutil/menu.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "os/file.h"
|
||||
|
||||
#include "url.h"
|
||||
#include "preferences.h"
|
||||
#include "mainframe.h"
|
||||
|
||||
/*!
|
||||
the urls to fire up in the game packs help menus
|
||||
*/
|
||||
namespace
|
||||
{
|
||||
std::list<CopiedString> mHelpURLs;
|
||||
}
|
||||
|
||||
/*!
|
||||
needed for hooking in Gtk+
|
||||
*/
|
||||
void HandleHelpCommand(CopiedString& str)
|
||||
{
|
||||
OpenURL(str.c_str());
|
||||
}
|
||||
|
||||
void process_xlink(const char* filename, const char *menu_name, const char *base_url, GtkMenu *menu)
|
||||
{
|
||||
if(file_exists(filename))
|
||||
{
|
||||
xmlDocPtr pDoc = xmlParseFile(filename);
|
||||
if (pDoc)
|
||||
{
|
||||
globalOutputStream() << "Processing .xlink file '" << filename << "'\n";
|
||||
// create sub menu
|
||||
GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic(menu, menu_name);
|
||||
// start walking the nodes, find the 'links' one
|
||||
xmlNodePtr pNode = pDoc->children;
|
||||
while (pNode && strcmp((const char*)pNode->name, "links"))
|
||||
pNode=pNode->next;
|
||||
if (pNode)
|
||||
{
|
||||
pNode = pNode->children;
|
||||
while(pNode)
|
||||
{
|
||||
if(!strcmp((const char*)pNode->name, "item"))
|
||||
{
|
||||
// process the URL
|
||||
CopiedString url;
|
||||
|
||||
xmlChar* prop = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>("url"));
|
||||
ASSERT_NOTNULL(prop);
|
||||
if(strstr(reinterpret_cast<const char*>(prop), "http://"))
|
||||
{
|
||||
// complete URL
|
||||
url = reinterpret_cast<const char*>(prop);
|
||||
}
|
||||
else
|
||||
{
|
||||
// relative URL
|
||||
StringOutputStream full(256);
|
||||
full << base_url << reinterpret_cast<const char*>(prop);
|
||||
url = full.c_str();
|
||||
}
|
||||
|
||||
mHelpURLs.push_back(url);
|
||||
|
||||
xmlFree(prop);
|
||||
|
||||
prop = xmlGetProp(pNode, reinterpret_cast<const xmlChar*>("name"));
|
||||
ASSERT_NOTNULL(prop);
|
||||
create_menu_item_with_mnemonic(menu_in_menu, reinterpret_cast<const char*>(prop), ReferenceCaller<CopiedString, HandleHelpCommand>(mHelpURLs.back()));
|
||||
xmlFree(prop);
|
||||
}
|
||||
pNode=pNode->next;
|
||||
}
|
||||
}
|
||||
xmlFreeDoc(pDoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "'" << filename << "' parse failed\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalOutputStream() << "'" << filename << "' not found\n";
|
||||
}
|
||||
}
|
||||
|
||||
void create_game_help_menu(GtkMenu *menu)
|
||||
{
|
||||
StringOutputStream filename(256);
|
||||
filename << AppPath_get() << "global.xlink";
|
||||
process_xlink(filename.c_str(), "General", AppPath_get(), menu);
|
||||
|
||||
#if 1
|
||||
filename.clear();
|
||||
filename << g_pGameDescription->mGameToolsPath.c_str() << "game.xlink";
|
||||
process_xlink(filename.c_str(), g_pGameDescription->getRequiredKeyValue("name"), g_pGameDescription->mGameToolsPath.c_str(), menu);
|
||||
#else
|
||||
for(std::list<CGameDescription *>::iterator iGame = g_GamesDialog.mGames.begin(); iGame != g_GamesDialog.mGames.end(); ++iGame)
|
||||
{
|
||||
filename.clear();
|
||||
filename << (*iGame)->mGameToolsPath.c_str() << "game.xlink";
|
||||
process_xlink(filename.c_str(), (*iGame)->getRequiredKeyValue("name"), (*iGame)->mGameToolsPath.c_str(), menu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
28
radiant/help.h
Normal file
28
radiant/help.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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_HELP_H)
|
||||
#define INCLUDED_HELP_H
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void create_game_help_menu(GtkMenu *menu);
|
||||
|
||||
#endif
|
||||
70
radiant/image.cpp
Normal file
70
radiant/image.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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 "modulesystem.h"
|
||||
#include "iimage.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
|
||||
#include "generic/reference.h"
|
||||
#include "os/path.h"
|
||||
#include "stream/stringstream.h"
|
||||
|
||||
|
||||
typedef Modules<_QERPlugImageTable> ImageModules;
|
||||
ImageModules& Textures_getImageModules();
|
||||
|
||||
/// \brief Returns a new image for the first file matching \p name in one of the available texture formats, or 0 if no file is found.
|
||||
Image* QERApp_LoadImage(void* environment, const char* name)
|
||||
{
|
||||
Image* image = 0;
|
||||
class LoadImageVisitor : public ImageModules::Visitor
|
||||
{
|
||||
const char* m_name;
|
||||
Image*& m_image;
|
||||
public:
|
||||
LoadImageVisitor(const char* name, Image*& image)
|
||||
: m_name(name), m_image(image)
|
||||
{
|
||||
}
|
||||
void visit(const char* name, const _QERPlugImageTable& table)
|
||||
{
|
||||
if(m_image == 0)
|
||||
{
|
||||
StringOutputStream fullname(256);
|
||||
fullname << m_name << '.' << name;
|
||||
ArchiveFile* file = GlobalFileSystem().openFile(fullname.c_str());
|
||||
if(file != 0)
|
||||
{
|
||||
m_image = table.loadImage(*file);
|
||||
file->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
} visitor(name, image);
|
||||
|
||||
Textures_getImageModules().foreachModule(visitor);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
28
radiant/image.h
Normal file
28
radiant/image.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_IMAGE_H)
|
||||
#define INCLUDED_IMAGE_H
|
||||
|
||||
class Image;
|
||||
Image* QERApp_LoadImage(void* environment, const char* name);
|
||||
|
||||
#endif
|
||||
621
radiant/main.cpp
Normal file
621
radiant/main.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
/*! \mainpage GtkRadiant Documentation Index
|
||||
|
||||
\section intro_sec Introduction
|
||||
|
||||
This documentation is generated from comments in the source code.
|
||||
|
||||
\section links_sec Useful Links
|
||||
|
||||
\link include/itextstream.h include/itextstream.h \endlink - Global output and error message streams, similar to std::cout and std::cerr. \n
|
||||
|
||||
FileInputStream - similar to std::ifstream (binary mode) \n
|
||||
FileOutputStream - similar to std::ofstream (binary mode) \n
|
||||
TextFileInputStream - similar to std::ifstream (text mode) \n
|
||||
TextFileOutputStream - similar to std::ofstream (text mode) \n
|
||||
StringOutputStream - similar to std::stringstream \n
|
||||
|
||||
\link string/string.h string/string.h \endlink - C-style string comparison and memory management. \n
|
||||
\link os/path.h os/path.h \endlink - Path manipulation for radiant's standard path format \n
|
||||
\link os/file.h os/file.h \endlink - OS file-system access. \n
|
||||
|
||||
::CopiedString - automatic string memory management \n
|
||||
Array - automatic array memory management \n
|
||||
HashTable - generic hashtable, similar to std::hash_map \n
|
||||
|
||||
\link math/vector.h math/vector.h \endlink - Vectors \n
|
||||
\link math/matrix.h math/matrix.h \endlink - Matrices \n
|
||||
\link math/quaternion.h math/quaternion.h \endlink - Quaternions \n
|
||||
\link math/plane.h math/plane.h \endlink - Planes \n
|
||||
\link math/aabb.h math/aabb.h \endlink - AABBs \n
|
||||
|
||||
Callback MemberCaller FunctionCaller - callbacks similar to using boost::function with boost::bind \n
|
||||
SmartPointer SmartReference - smart-pointer and smart-reference similar to Loki's SmartPtr \n
|
||||
|
||||
\link generic/bitfield.h generic/bitfield.h \endlink - Type-safe bitfield \n
|
||||
\link generic/enumeration.h generic/enumeration.h \endlink - Type-safe enumeration \n
|
||||
|
||||
DefaultAllocator - Memory allocation using new/delete, compliant with std::allocator interface \n
|
||||
|
||||
\link debugging/debugging.h debugging/debugging.h \endlink - Debugging macros \n
|
||||
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "iundo.h"
|
||||
|
||||
#include <gtk/gtkmain.h>
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "os/file.h"
|
||||
#include "os/path.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "stream/textfilestream.h"
|
||||
|
||||
#include "gtkutil/messagebox.h"
|
||||
#include "gtkutil/image.h"
|
||||
#include "console.h"
|
||||
#include "texwindow.h"
|
||||
#include "map.h"
|
||||
#include "mainframe.h"
|
||||
#include "commands.h"
|
||||
#include "preferences.h"
|
||||
#include "environment.h"
|
||||
#include "referencecache.h"
|
||||
#include "stacktrace.h"
|
||||
|
||||
void show_splash();
|
||||
void hide_splash();
|
||||
|
||||
void error_redirect (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
|
||||
{
|
||||
gboolean in_recursion;
|
||||
gboolean is_fatal;
|
||||
char buf[256];
|
||||
|
||||
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
|
||||
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
|
||||
log_level = (GLogLevelFlags) (log_level & G_LOG_LEVEL_MASK);
|
||||
|
||||
if (!message)
|
||||
message = "(0) message";
|
||||
|
||||
if (domain)
|
||||
strcpy (buf, domain);
|
||||
else
|
||||
strcpy (buf, "**");
|
||||
strcat (buf, "-");
|
||||
|
||||
switch (log_level)
|
||||
{
|
||||
case G_LOG_LEVEL_ERROR:
|
||||
if (in_recursion)
|
||||
strcat (buf, "ERROR (recursed) **: ");
|
||||
else
|
||||
strcat (buf, "ERROR **: ");
|
||||
break;
|
||||
case G_LOG_LEVEL_CRITICAL:
|
||||
if (in_recursion)
|
||||
strcat (buf, "CRITICAL (recursed) **: ");
|
||||
else
|
||||
strcat (buf, "CRITICAL **: ");
|
||||
break;
|
||||
case G_LOG_LEVEL_WARNING:
|
||||
if (in_recursion)
|
||||
strcat (buf, "WARNING (recursed) **: ");
|
||||
else
|
||||
strcat (buf, "WARNING **: ");
|
||||
break;
|
||||
case G_LOG_LEVEL_MESSAGE:
|
||||
if (in_recursion)
|
||||
strcat (buf, "Message (recursed): ");
|
||||
else
|
||||
strcat (buf, "Message: ");
|
||||
break;
|
||||
case G_LOG_LEVEL_INFO:
|
||||
if (in_recursion)
|
||||
strcat (buf, "INFO (recursed): ");
|
||||
else
|
||||
strcat (buf, "INFO: ");
|
||||
break;
|
||||
case G_LOG_LEVEL_DEBUG:
|
||||
if (in_recursion)
|
||||
strcat (buf, "DEBUG (recursed): ");
|
||||
else
|
||||
strcat (buf, "DEBUG: ");
|
||||
break;
|
||||
default:
|
||||
/* we are used for a log level that is not defined by GLib itself,
|
||||
* try to make the best out of it.
|
||||
*/
|
||||
if (in_recursion)
|
||||
strcat (buf, "LOG (recursed:");
|
||||
else
|
||||
strcat (buf, "LOG (");
|
||||
if (log_level)
|
||||
{
|
||||
gchar string[] = "0x00): ";
|
||||
gchar *p = string + 2;
|
||||
guint i;
|
||||
|
||||
i = g_bit_nth_msf (log_level, -1);
|
||||
*p = i >> 4;
|
||||
p++;
|
||||
*p = '0' + (i & 0xf);
|
||||
if (*p > '9')
|
||||
*p += 'A' - '9' - 1;
|
||||
|
||||
strcat (buf, string);
|
||||
} else
|
||||
strcat (buf, "): ");
|
||||
}
|
||||
|
||||
strcat (buf, message);
|
||||
if (is_fatal)
|
||||
strcat (buf, "\naborting...\n");
|
||||
else
|
||||
strcat (buf, "\n");
|
||||
|
||||
printf ("%s\n", buf);
|
||||
|
||||
ERROR_MESSAGE("GTK+ error: " << buf);
|
||||
}
|
||||
|
||||
#if defined (_DEBUG) && defined (WIN32) && defined (_MSC_VER)
|
||||
#include "crtdbg.h"
|
||||
#endif
|
||||
|
||||
void crt_init()
|
||||
{
|
||||
#if defined (_DEBUG) && defined (WIN32) && defined (_MSC_VER)
|
||||
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||
#endif
|
||||
}
|
||||
|
||||
class Lock
|
||||
{
|
||||
bool m_locked;
|
||||
public:
|
||||
Lock() : m_locked(false)
|
||||
{
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
m_locked = false;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
};
|
||||
|
||||
class ScopedLock
|
||||
{
|
||||
Lock& m_lock;
|
||||
public:
|
||||
ScopedLock(Lock& lock) : m_lock(lock)
|
||||
{
|
||||
m_lock.lock();
|
||||
}
|
||||
~ScopedLock()
|
||||
{
|
||||
m_lock.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
class PopupDebugMessageHandler : public DebugMessageHandler
|
||||
{
|
||||
StringOutputStream m_buffer;
|
||||
Lock m_lock;
|
||||
public:
|
||||
TextOutputStream& getOutputStream()
|
||||
{
|
||||
if(!m_lock.locked())
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
return globalErrorStream();
|
||||
}
|
||||
bool handleMessage()
|
||||
{
|
||||
getOutputStream() << "----------------\n";
|
||||
write_stack_trace(getOutputStream());
|
||||
getOutputStream() << "----------------\n";
|
||||
if(!m_lock.locked())
|
||||
{
|
||||
ScopedLock lock(m_lock);
|
||||
#if defined _DEBUG
|
||||
m_buffer << "Break into the debugger?\n";
|
||||
globalErrorStream() << m_buffer.c_str();
|
||||
bool handled = gtk_MessageBox(0, m_buffer.c_str(), "Radiant - Runtime Error", eMB_YESNO, eMB_ICONERROR) == eIDNO;
|
||||
m_buffer.clear();
|
||||
return handled;
|
||||
#else
|
||||
m_buffer << "Please report this error to the developers\n";
|
||||
globalErrorStream() << m_buffer.c_str();
|
||||
gtk_MessageBox(0, m_buffer.c_str(), "Radiant - Runtime Error", eMB_OK, eMB_ICONERROR);
|
||||
m_buffer.clear();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Static<PopupDebugMessageHandler> GlobalPopupDebugMessageHandler;
|
||||
|
||||
void streams_init()
|
||||
{
|
||||
GlobalErrorStream::instance().setOutputStream(getSysPrintErrorStream());
|
||||
GlobalOutputStream::instance().setOutputStream(getSysPrintOutputStream());
|
||||
}
|
||||
|
||||
void paths_init()
|
||||
{
|
||||
const char* home = environment_get_home_path();
|
||||
Q_mkdir(home);
|
||||
|
||||
{
|
||||
StringOutputStream path(256);
|
||||
path << home << RADIANT_VERSION << '/';
|
||||
g_strSettingsPath = path.c_str();
|
||||
}
|
||||
|
||||
Q_mkdir(g_strSettingsPath.c_str());
|
||||
|
||||
g_strAppPath = environment_get_app_path();
|
||||
|
||||
// radiant is installed in the parent dir of "tools/"
|
||||
// NOTE: this is not very easy for debugging
|
||||
// maybe add options to lookup in several places?
|
||||
// (for now I had to create symlinks)
|
||||
{
|
||||
StringOutputStream path(256);
|
||||
path << g_strAppPath.c_str() << "bitmaps/";
|
||||
BitmapsPath_set(path.c_str());
|
||||
}
|
||||
|
||||
// we will set this right after the game selection is done
|
||||
g_strGameToolsPath = g_strAppPath;
|
||||
}
|
||||
|
||||
bool check_version_file(const char* filename, const char* version)
|
||||
{
|
||||
TextFileInputStream file(filename);
|
||||
if(!file.failed())
|
||||
{
|
||||
char buf[10];
|
||||
buf[file.read(buf, 9)] = '\0';
|
||||
|
||||
// chomp it (the hard way)
|
||||
int chomp = 0;
|
||||
while(buf[chomp] >= '0' && buf[chomp] <= '9')
|
||||
chomp++;
|
||||
buf[chomp] = '\0';
|
||||
|
||||
return string_equal(buf, version);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_version()
|
||||
{
|
||||
// a safe check to avoid people running broken installations
|
||||
// (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing)
|
||||
// make something idiot proof and someone will make better idiots, this may be overkill
|
||||
// let's leave it disabled in debug mode in any case
|
||||
// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
|
||||
#ifndef _DEBUG
|
||||
#define CHECK_VERSION
|
||||
#endif
|
||||
#ifdef CHECK_VERSION
|
||||
// locate and open RADIANT_MAJOR and RADIANT_MINOR
|
||||
bool bVerIsGood = true;
|
||||
{
|
||||
StringOutputStream ver_file_name(256);
|
||||
ver_file_name << AppPath_get() << "RADIANT_MAJOR";
|
||||
bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MAJOR_VERSION);
|
||||
}
|
||||
{
|
||||
StringOutputStream ver_file_name(256);
|
||||
ver_file_name << AppPath_get() << "RADIANT_MINOR";
|
||||
bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MINOR_VERSION);
|
||||
}
|
||||
|
||||
if (!bVerIsGood)
|
||||
{
|
||||
StringOutputStream msg(256);
|
||||
msg << "This editor binary (" RADIANT_VERSION ") doesn't match what the latest setup has configured in this directory\n"
|
||||
"Make sure you run the right/latest editor binary you installed\n"
|
||||
<< AppPath_get();
|
||||
gtk_MessageBox(0, msg.c_str(), "Radiant", eMB_OK, eMB_ICONDEFAULT);
|
||||
}
|
||||
return bVerIsGood;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void create_global_pid()
|
||||
{
|
||||
/*!
|
||||
the global prefs loading / game selection dialog might fail for any reason we don't know about
|
||||
we need to catch when it happens, to cleanup the stateful prefs which might be killing it
|
||||
and to turn on console logging for lookup of the problem
|
||||
this is the first part of the two step .pid system
|
||||
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
|
||||
*/
|
||||
StringOutputStream g_pidFile(256); ///< the global .pid file (only for global part of the startup)
|
||||
|
||||
g_pidFile << SettingsPath_get() << "radiant.pid";
|
||||
|
||||
FILE *pid;
|
||||
pid = fopen (g_pidFile.c_str(), "r");
|
||||
if (pid != 0)
|
||||
{
|
||||
fclose (pid);
|
||||
|
||||
if (remove (g_pidFile.c_str()) == -1)
|
||||
{
|
||||
StringOutputStream msg(256);
|
||||
msg << "WARNING: Could not delete " << g_pidFile.c_str();
|
||||
gtk_MessageBox (0, msg.c_str(), "Radiant", eMB_OK, eMB_ICONERROR );
|
||||
}
|
||||
|
||||
// in debug, never prompt to clean registry, turn console logging auto after a failed start
|
||||
#if !defined(_DEBUG)
|
||||
StringOutputStream msg(256);
|
||||
msg << "Radiant failed to start properly the last time it was run.\n"
|
||||
"The failure may be related to current global preferences.\n"
|
||||
"Do you want to reset global preferences to defaults?";
|
||||
|
||||
if (gtk_MessageBox (0, msg.c_str(), "Radiant - Startup Failure", eMB_YESNO, eMB_ICONQUESTION) == eIDYES)
|
||||
{
|
||||
g_GamesDialog.Reset();
|
||||
}
|
||||
|
||||
msg.clear();
|
||||
msg << "Logging console output to " << SettingsPath_get() << "radiant.log\nRefer to the log if Radiant fails to start again.";
|
||||
|
||||
gtk_MessageBox (0, msg.c_str(), "Radiant - Console Log", eMB_OK);
|
||||
#endif
|
||||
|
||||
// set without saving, the class is not in a coherent state yet
|
||||
// just do the value change and call to start logging, CGamesDialog will pickup when relevant
|
||||
g_GamesDialog.m_bForceLogConsole = true;
|
||||
Sys_LogFile(true);
|
||||
}
|
||||
|
||||
// create a primary .pid for global init run
|
||||
pid = fopen (g_pidFile.c_str(), "w");
|
||||
if (pid)
|
||||
fclose (pid);
|
||||
}
|
||||
|
||||
void remove_global_pid()
|
||||
{
|
||||
StringOutputStream g_pidFile(256);
|
||||
g_pidFile << SettingsPath_get() << "radiant.pid";
|
||||
|
||||
// close the primary
|
||||
if (remove (g_pidFile.c_str()) == -1)
|
||||
{
|
||||
StringOutputStream msg(256);
|
||||
msg << "WARNING: Could not delete " << g_pidFile.c_str();
|
||||
gtk_MessageBox (0, msg.c_str(), "Radiant", eMB_OK, eMB_ICONERROR );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
now the secondary game dependant .pid file
|
||||
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
|
||||
*/
|
||||
void create_local_pid()
|
||||
{
|
||||
StringOutputStream g_pidGameFile(256); ///< the game-specific .pid file
|
||||
g_pidGameFile << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << "/radiant-game.pid";
|
||||
|
||||
FILE *pid = fopen (g_pidGameFile.c_str(), "r");
|
||||
if (pid != 0)
|
||||
{
|
||||
fclose (pid);
|
||||
if (remove (g_pidGameFile.c_str()) == -1)
|
||||
{
|
||||
StringOutputStream msg;
|
||||
msg << "WARNING: Could not delete " << g_pidGameFile.c_str();
|
||||
gtk_MessageBox (0, msg.c_str(), "Radiant", eMB_OK, eMB_ICONERROR );
|
||||
}
|
||||
|
||||
// in debug, never prompt to clean registry, turn console logging auto after a failed start
|
||||
#if !defined(_DEBUG)
|
||||
StringOutputStream msg;
|
||||
msg << "Radiant failed to start properly the last time it was run.\n"
|
||||
"The failure may be caused by current preferences.\n"
|
||||
"Do you want to reset all preferences to defaults?";
|
||||
|
||||
if (gtk_MessageBox (0, msg.c_str(), "Radiant - Startup Failure", eMB_YESNO, eMB_ICONQUESTION) == eIDYES)
|
||||
{
|
||||
Preferences_Reset();
|
||||
}
|
||||
|
||||
msg.clear();
|
||||
msg << "Logging console output to " << SettingsPath_get() << "radiant.log\nRefer to the log if Radiant fails to start again.";
|
||||
|
||||
gtk_MessageBox (0, msg.c_str(), "Radiant - Console Log", eMB_OK);
|
||||
#endif
|
||||
|
||||
// force console logging on! (will go in prefs too)
|
||||
g_GamesDialog.m_bForceLogConsole = true;
|
||||
Sys_LogFile(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create one, will remove right after entering message loop
|
||||
pid = fopen (g_pidGameFile.c_str(), "w");
|
||||
if (pid)
|
||||
fclose (pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
now the secondary game dependant .pid file
|
||||
http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
|
||||
*/
|
||||
void remove_local_pid()
|
||||
{
|
||||
StringOutputStream g_pidGameFile(256);
|
||||
g_pidGameFile << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << "/radiant-game.pid";
|
||||
remove(g_pidGameFile.c_str());
|
||||
}
|
||||
|
||||
void user_shortcuts_init()
|
||||
{
|
||||
StringOutputStream path(256);
|
||||
path << SettingsPath_get() << g_pGameDescription->mGameFile.c_str() << '/';
|
||||
LoadCommandMap(path.c_str());
|
||||
SaveCommandMap(path.c_str());
|
||||
}
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
crt_init();
|
||||
|
||||
streams_init();
|
||||
|
||||
gtk_disable_setlocale();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// redirect Gtk warnings to the console
|
||||
g_log_set_handler ("Gdk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
|
||||
G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, 0);
|
||||
g_log_set_handler ("Gtk", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
|
||||
G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, 0);
|
||||
g_log_set_handler ("GtkGLExt", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
|
||||
G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, 0);
|
||||
g_log_set_handler ("GLib", (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
|
||||
G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, 0);
|
||||
g_log_set_handler (0, (GLogLevelFlags)(G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING|
|
||||
G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG), error_redirect, 0);
|
||||
|
||||
GlobalDebugMessageHandler::instance().setHandler(GlobalPopupDebugMessageHandler::instance());
|
||||
|
||||
environment_init(argc, argv);
|
||||
|
||||
paths_init();
|
||||
|
||||
if(!check_version())
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
show_splash();
|
||||
|
||||
create_global_pid();
|
||||
|
||||
GlobalPreferences_Init();
|
||||
|
||||
g_GamesDialog.Init();
|
||||
|
||||
g_strGameToolsPath = g_pGameDescription->mGameToolsPath;
|
||||
|
||||
remove_global_pid();
|
||||
|
||||
create_local_pid();
|
||||
|
||||
g_Preferences.Init();
|
||||
|
||||
// in a very particular post-.pid startup
|
||||
// we may have the console turned on and want to keep it that way
|
||||
// so we use a latching system
|
||||
if (g_GamesDialog.m_bForceLogConsole)
|
||||
{
|
||||
Sys_LogFile(true);
|
||||
g_Console_enableLogging = true;
|
||||
g_GamesDialog.m_bForceLogConsole = false;
|
||||
}
|
||||
|
||||
|
||||
Radiant_Initialise();
|
||||
|
||||
global_accel_init();
|
||||
|
||||
user_shortcuts_init();
|
||||
|
||||
g_pParentWnd = 0;
|
||||
g_pParentWnd = new MainFrame();
|
||||
|
||||
hide_splash();
|
||||
|
||||
if (g_bLoadLastMap && !g_strLastMap.empty())
|
||||
{
|
||||
Map_LoadFile(g_strLastMap.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Map_New();
|
||||
}
|
||||
|
||||
// load up shaders now that we have the map loaded
|
||||
// eviltypeguy
|
||||
TextureBrowser_ShowStartupShaders(GlobalTextureBrowser());
|
||||
|
||||
|
||||
remove_local_pid();
|
||||
|
||||
gtk_main();
|
||||
|
||||
// avoid saving prefs when the app is minimized
|
||||
if (g_pParentWnd->IsSleeping())
|
||||
{
|
||||
globalOutputStream() << "Shutdown while sleeping, not saving prefs\n";
|
||||
g_preferences_globals.disable_ini = true;
|
||||
}
|
||||
|
||||
Map_Free();
|
||||
|
||||
if (!Map_Unnamed(g_map))
|
||||
{
|
||||
g_strLastMap = Map_Name(g_map);
|
||||
}
|
||||
|
||||
delete g_pParentWnd;
|
||||
|
||||
global_accel_destroy();
|
||||
|
||||
Radiant_Shutdown();
|
||||
|
||||
// close the log file if any
|
||||
Sys_LogFile(false);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
25
radiant/main.h
Normal file
25
radiant/main.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
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_MAIN_H)
|
||||
#define INCLUDED_MAIN_H
|
||||
|
||||
#endif
|
||||
3532
radiant/mainframe.cpp
Normal file
3532
radiant/mainframe.cpp
Normal file
File diff suppressed because it is too large
Load Diff
279
radiant/mainframe.h
Normal file
279
radiant/mainframe.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
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_MAINFRAME_H)
|
||||
#define INCLUDED_MAINFRAME_H
|
||||
|
||||
#include "gtkutil/window.h"
|
||||
#include "gtkutil/idledraw.h"
|
||||
#include "gtkutil/widget.h"
|
||||
#include "string/string.h"
|
||||
|
||||
class IPlugIn;
|
||||
class IToolbarButton;
|
||||
|
||||
class XYWnd;
|
||||
class CamWnd;
|
||||
class ZWnd;
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
|
||||
const int c_command_status = 0;
|
||||
const int c_position_status = 1;
|
||||
const int c_brushcount_status = 2;
|
||||
const int c_texture_status = 3;
|
||||
const int c_grid_status = 4;
|
||||
const int c_count_status = 5;
|
||||
|
||||
class MainFrame
|
||||
{
|
||||
public:
|
||||
enum EViewStyle
|
||||
{
|
||||
eRegular = 0,
|
||||
eFloating = 1,
|
||||
eSplit = 2,
|
||||
eRegularLeft = 3,
|
||||
};
|
||||
|
||||
MainFrame();
|
||||
~MainFrame();
|
||||
|
||||
GtkWindow* m_window;
|
||||
|
||||
CopiedString m_command_status;
|
||||
CopiedString m_position_status;
|
||||
CopiedString m_brushcount_status;
|
||||
CopiedString m_texture_status;
|
||||
CopiedString m_grid_status;
|
||||
private:
|
||||
|
||||
void Create();
|
||||
void SaveWindowInfo();
|
||||
void Shutdown();
|
||||
|
||||
GtkWidget* m_vSplit;
|
||||
GtkWidget* m_hSplit;
|
||||
GtkWidget* m_vSplit2;
|
||||
|
||||
XYWnd* m_pXYWnd;
|
||||
XYWnd* m_pYZWnd;
|
||||
XYWnd* m_pXZWnd;
|
||||
CamWnd* m_pCamWnd;
|
||||
ZWnd* m_pZWnd;
|
||||
XYWnd* m_pActiveXY;
|
||||
|
||||
bool m_bSleeping;
|
||||
|
||||
GtkWidget *m_pStatusLabel[c_count_status];
|
||||
|
||||
|
||||
EViewStyle m_nCurrentStyle;
|
||||
WindowPositionTracker m_position_tracker;
|
||||
|
||||
IdleDraw m_idleRedrawStatusText;
|
||||
|
||||
public:
|
||||
|
||||
bool IsSleeping()
|
||||
{
|
||||
return m_bSleeping;
|
||||
}
|
||||
void OnSleep();
|
||||
|
||||
void SetStatusText(CopiedString& status_text, const char* pText);
|
||||
void UpdateStatusText();
|
||||
void RedrawStatusText();
|
||||
typedef MemberCaller<MainFrame, &MainFrame::RedrawStatusText> RedrawStatusTextCaller;
|
||||
|
||||
void SetGridStatus();
|
||||
typedef MemberCaller<MainFrame, &MainFrame::SetGridStatus> SetGridStatusCaller;
|
||||
|
||||
void SetActiveXY(XYWnd* p);
|
||||
XYWnd* ActiveXY()
|
||||
{
|
||||
return m_pActiveXY;
|
||||
};
|
||||
XYWnd* GetXYWnd()
|
||||
{
|
||||
return m_pXYWnd;
|
||||
}
|
||||
XYWnd* GetXZWnd()
|
||||
{
|
||||
return m_pXZWnd;
|
||||
}
|
||||
XYWnd* GetYZWnd()
|
||||
{
|
||||
return m_pYZWnd;
|
||||
}
|
||||
ZWnd* GetZWnd()
|
||||
{
|
||||
return m_pZWnd;
|
||||
}
|
||||
CamWnd* GetCamWnd()
|
||||
{
|
||||
return m_pCamWnd;
|
||||
}
|
||||
|
||||
void ReleaseContexts();
|
||||
void CreateContexts();
|
||||
|
||||
EViewStyle CurrentStyle()
|
||||
{
|
||||
return m_nCurrentStyle;
|
||||
};
|
||||
bool FloatingGroupDialog()
|
||||
{
|
||||
return CurrentStyle() == eFloating || CurrentStyle() == eSplit;
|
||||
};
|
||||
};
|
||||
|
||||
extern MainFrame* g_pParentWnd;
|
||||
|
||||
GtkWindow* MainFrame_getWindow();
|
||||
|
||||
enum EMouseButtonMode
|
||||
{
|
||||
ETwoButton = 0,
|
||||
EThreeButton = 1,
|
||||
};
|
||||
|
||||
struct glwindow_globals_t
|
||||
{
|
||||
int m_nMouseType;
|
||||
|
||||
glwindow_globals_t() :
|
||||
m_nMouseType(EThreeButton)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void GLWindow_Construct();
|
||||
void GLWindow_Destroy();
|
||||
|
||||
extern glwindow_globals_t g_glwindow_globals;
|
||||
template<typename Value>
|
||||
class LatchedValue;
|
||||
typedef LatchedValue<bool> LatchedBool;
|
||||
extern LatchedBool g_Layout_enableDetachableMenus;
|
||||
|
||||
void deleteSelection();
|
||||
|
||||
|
||||
void Sys_Status(const char* status);
|
||||
|
||||
|
||||
void ScreenUpdates_Disable(const char* message, const char* title = "");
|
||||
void ScreenUpdates_Enable();
|
||||
bool ScreenUpdates_Enabled();
|
||||
void ScreenUpdates_process();
|
||||
|
||||
class ScopeDisableScreenUpdates
|
||||
{
|
||||
public:
|
||||
ScopeDisableScreenUpdates(const char* message, const char* title = "")
|
||||
{
|
||||
ScreenUpdates_Disable(message, title);
|
||||
}
|
||||
~ScopeDisableScreenUpdates()
|
||||
{
|
||||
ScreenUpdates_Enable();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void EnginePath_Realise();
|
||||
void EnginePath_Unrealise();
|
||||
|
||||
class ModuleObserver;
|
||||
|
||||
void Radiant_attachEnginePathObserver(ModuleObserver& observer);
|
||||
void Radiant_detachEnginePathObserver(ModuleObserver& observer);
|
||||
|
||||
void Radiant_attachGameToolsPathObserver(ModuleObserver& observer);
|
||||
void Radiant_detachGameToolsPathObserver(ModuleObserver& observer);
|
||||
|
||||
extern CopiedString g_strEnginePath;
|
||||
void EnginePath_verify();
|
||||
const char* EnginePath_get();
|
||||
const char* QERApp_GetGamePath();
|
||||
|
||||
extern CopiedString g_strAppPath;
|
||||
const char* AppPath_get();
|
||||
|
||||
extern CopiedString g_strSettingsPath;
|
||||
const char* SettingsPath_get();
|
||||
|
||||
const char* const g_pluginsDir = "plugins/"; ///< name of plugins directory, always sub-directory of toolspath
|
||||
const char* const g_modulesDir = "modules/"; ///< name of modules directory, always sub-directory of toolspath
|
||||
|
||||
extern CopiedString g_strGameToolsPath;
|
||||
const char* GameToolsPath_get();
|
||||
|
||||
void Radiant_Initialise();
|
||||
void Radiant_Shutdown();
|
||||
|
||||
void SaveMapAs();
|
||||
|
||||
|
||||
void XY_UpdateAllWindows();
|
||||
void UpdateAllWindows();
|
||||
|
||||
|
||||
void ClipperChangeNotify();
|
||||
|
||||
void DefaultMode();
|
||||
|
||||
const char* basegame_get();
|
||||
const char* gamename_get();
|
||||
void gamename_set(const char* gamename);
|
||||
void Radiant_attachGameNameObserver(ModuleObserver& observer);
|
||||
void Radiant_detachGameNameObserver(ModuleObserver& observer);
|
||||
const char* gamemode_get();
|
||||
void gamemode_set(const char* gamemode);
|
||||
void Radiant_attachGameModeObserver(ModuleObserver& observer);
|
||||
void Radiant_detachGameModeObserver(ModuleObserver& observer);
|
||||
|
||||
|
||||
|
||||
void VFS_Construct();
|
||||
void VFS_Destroy();
|
||||
|
||||
void HomePaths_Construct();
|
||||
void HomePaths_Destroy();
|
||||
void Radiant_attachHomePathsObserver(ModuleObserver& observer);
|
||||
void Radiant_detachHomePathsObserver(ModuleObserver& observer);
|
||||
|
||||
|
||||
void MainFrame_Construct();
|
||||
void MainFrame_Destroy();
|
||||
|
||||
|
||||
extern float (*GridStatus_getGridSize)();
|
||||
extern int (*GridStatus_getRotateIncrement)();
|
||||
extern int (*GridStatus_getFarClipDistance)();
|
||||
extern bool (*GridStatus_getTextureLockEnabled)();
|
||||
void GridStatus_onTextureLockEnabledChanged();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
2297
radiant/map.cpp
Normal file
2297
radiant/map.cpp
Normal file
File diff suppressed because it is too large
Load Diff
169
radiant/map.h
Normal file
169
radiant/map.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
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_MAP_H)
|
||||
#define INCLUDED_MAP_H
|
||||
|
||||
#include "iscenegraph.h"
|
||||
#include "generic/callback.h"
|
||||
#include "string/stringfwd.h"
|
||||
|
||||
class Map;
|
||||
extern Map g_map;
|
||||
|
||||
class MapFormat;
|
||||
|
||||
void Map_addValidCallback(Map& map, const Callback& callback);
|
||||
bool Map_Valid(const Map& map);
|
||||
|
||||
class DeferredDraw
|
||||
{
|
||||
Callback m_draw;
|
||||
bool m_defer;
|
||||
bool m_deferred;
|
||||
public:
|
||||
DeferredDraw(const Callback& draw) : m_draw(draw), m_defer(false), m_deferred(false)
|
||||
{
|
||||
}
|
||||
void defer()
|
||||
{
|
||||
m_defer = true;
|
||||
}
|
||||
void draw()
|
||||
{
|
||||
if(m_defer)
|
||||
{
|
||||
m_deferred = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_draw();
|
||||
}
|
||||
}
|
||||
void flush()
|
||||
{
|
||||
if(m_defer && m_deferred)
|
||||
{
|
||||
m_draw();
|
||||
}
|
||||
m_deferred = false;
|
||||
m_defer = false;
|
||||
}
|
||||
};
|
||||
|
||||
inline void DeferredDraw_onMapValidChanged(DeferredDraw& self)
|
||||
{
|
||||
if(Map_Valid(g_map))
|
||||
{
|
||||
self.flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.defer();
|
||||
}
|
||||
}
|
||||
typedef ReferenceCaller<DeferredDraw, DeferredDraw_onMapValidChanged> DeferredDrawOnMapValidChangedCaller;
|
||||
|
||||
|
||||
|
||||
const char* Map_Name(const Map& map);
|
||||
const MapFormat& Map_getFormat(const Map& map);
|
||||
bool Map_Unnamed(const Map& map);
|
||||
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
class Graph;
|
||||
}
|
||||
|
||||
scene::Node* Map_GetWorldspawn(const Map& map);
|
||||
scene::Node* Map_FindWorldspawn(Map& map);
|
||||
scene::Node& Map_FindOrInsertWorldspawn(Map& map);
|
||||
|
||||
template<typename Element> class BasicVector3;
|
||||
typedef BasicVector3<float> Vector3;
|
||||
|
||||
extern Vector3 region_mins, region_maxs;
|
||||
extern bool region_active;
|
||||
|
||||
// used to be #defines, multiple engine support suggests we should go towards dynamic
|
||||
extern float g_MaxWorldCoord;
|
||||
extern float g_MinWorldCoord;
|
||||
|
||||
void Map_LoadFile(const char* filename);
|
||||
bool Map_SaveFile(const char* filename);
|
||||
|
||||
void Map_New();
|
||||
void Map_Free();
|
||||
|
||||
void Map_RegionOff();
|
||||
|
||||
bool Map_SaveRegion(const char* filename);
|
||||
|
||||
class TextInputStream;
|
||||
class TextOutputStream;
|
||||
|
||||
void Map_ImportSelected(TextInputStream& in, const MapFormat& format);
|
||||
void Map_ExportSelected(TextOutputStream& out, const MapFormat& format);
|
||||
|
||||
bool Map_Modified(const Map& map);
|
||||
void Map_SetModified(Map& map, bool modified);
|
||||
|
||||
bool Map_Save();
|
||||
bool Map_SaveAs();
|
||||
|
||||
scene::Node& Node_Clone(scene::Node& node);
|
||||
|
||||
void DoMapInfo();
|
||||
|
||||
void Scene_parentSelectedBrushesToEntity(scene::Graph& graph, scene::Node& parent);
|
||||
std::size_t Scene_countSelectedBrushes(scene::Graph& graph);
|
||||
|
||||
void Scene_parentSelected();
|
||||
|
||||
void OnUndoSizeChanged();
|
||||
|
||||
void NewMap();
|
||||
void OpenMap();
|
||||
void ImportMap();
|
||||
void SaveMapAs();
|
||||
void SaveMap();
|
||||
void ExportMap();
|
||||
void SaveRegion();
|
||||
|
||||
|
||||
void Map_Traverse(scene::Node& root, const scene::Traversable::Walker& walker);
|
||||
|
||||
|
||||
void SelectBrush (int entitynum, int brushnum);
|
||||
|
||||
extern CopiedString g_strLastMap;
|
||||
extern bool g_bLoadLastMap;
|
||||
|
||||
void Map_Construct();
|
||||
void Map_Destroy();
|
||||
|
||||
|
||||
void Map_gatherNamespaced(scene::Node& root);
|
||||
void Map_mergeClonedNames();
|
||||
|
||||
#endif
|
||||
254
radiant/mru.cpp
Normal file
254
radiant/mru.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
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 "mru.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
|
||||
#include "os/file.h"
|
||||
#include "generic/callback.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "convert.h"
|
||||
|
||||
#include "gtkutil/menu.h"
|
||||
#include "map.h"
|
||||
#include "qe3.h"
|
||||
|
||||
#define MRU_MAX 4
|
||||
namespace {
|
||||
GtkMenuItem *MRU_items[MRU_MAX];
|
||||
std::size_t MRU_used;
|
||||
typedef CopiedString MRU_filename_t;
|
||||
MRU_filename_t MRU_filenames[MRU_MAX];
|
||||
typedef const char* MRU_key_t;
|
||||
MRU_key_t MRU_keys[MRU_MAX] = { "File0", "File1", "File2", "File3" };
|
||||
}
|
||||
|
||||
inline const char* MRU_GetText(std::size_t index)
|
||||
{
|
||||
return MRU_filenames[index].c_str();
|
||||
}
|
||||
|
||||
class EscapedMnemonic
|
||||
{
|
||||
StringBuffer m_buffer;
|
||||
public:
|
||||
EscapedMnemonic(std::size_t capacity) : m_buffer(capacity)
|
||||
{
|
||||
m_buffer.push_back('_');
|
||||
}
|
||||
const char* c_str() const
|
||||
{
|
||||
return m_buffer.c_str();
|
||||
}
|
||||
void push_back(char c) // not escaped
|
||||
{
|
||||
m_buffer.push_back(c);
|
||||
}
|
||||
std::size_t write(const char* buffer, std::size_t length)
|
||||
{
|
||||
for(const char* end = buffer + length; buffer != end; ++buffer)
|
||||
{
|
||||
if(*buffer == '_')
|
||||
{
|
||||
m_buffer.push_back('_');
|
||||
}
|
||||
|
||||
m_buffer.push_back(*buffer);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline EscapedMnemonic& operator<<(EscapedMnemonic& ostream, const T& t)
|
||||
{
|
||||
return ostream_write(ostream, t);
|
||||
}
|
||||
|
||||
|
||||
void MRU_updateWidget(std::size_t index, const char *filename)
|
||||
{
|
||||
EscapedMnemonic mnemonic(64);
|
||||
mnemonic.push_back('_');
|
||||
mnemonic << Unsigned(index + 1) << "- " << ConvertLocaleToUTF8(filename);
|
||||
gtk_label_set_text_with_mnemonic(GTK_LABEL(gtk_bin_get_child(GTK_BIN(MRU_items[index]))), mnemonic.c_str());
|
||||
}
|
||||
|
||||
void MRU_SetText(std::size_t index, const char *filename)
|
||||
{
|
||||
MRU_filenames[index] = filename;
|
||||
MRU_updateWidget(index, filename);
|
||||
}
|
||||
|
||||
void MRU_AddFile (const char *str)
|
||||
{
|
||||
std::size_t i;
|
||||
const char* text;
|
||||
|
||||
// check if file is already in our list
|
||||
for (i = 0; i < MRU_used; i++)
|
||||
{
|
||||
text = MRU_GetText (i);
|
||||
|
||||
if (strcmp (text, str) == 0)
|
||||
{
|
||||
// reorder menu
|
||||
for(; i > 0; i--)
|
||||
MRU_SetText(i, MRU_GetText (i-1));
|
||||
|
||||
MRU_SetText(0, str);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (MRU_used < MRU_MAX)
|
||||
MRU_used++;
|
||||
|
||||
// move items down
|
||||
for (i = MRU_used-1; i > 0; i--)
|
||||
MRU_SetText (i, MRU_GetText (i-1));
|
||||
|
||||
MRU_SetText (0, str);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(MRU_items[0]), TRUE);
|
||||
gtk_widget_show(GTK_WIDGET(MRU_items[MRU_used-1]));
|
||||
}
|
||||
|
||||
void MRU_Init()
|
||||
{
|
||||
if(MRU_used > MRU_MAX)
|
||||
MRU_used = MRU_MAX;
|
||||
}
|
||||
|
||||
void MRU_AddWidget(GtkMenuItem *widget, std::size_t pos)
|
||||
{
|
||||
if(pos < MRU_MAX)
|
||||
{
|
||||
MRU_items[pos] = widget;
|
||||
if(pos < MRU_used)
|
||||
{
|
||||
MRU_updateWidget(pos, MRU_GetText(pos));
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(MRU_items[0]), TRUE);
|
||||
gtk_widget_show(GTK_WIDGET(MRU_items[pos]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MRU_Activate (std::size_t index)
|
||||
{
|
||||
char text[1024];
|
||||
strcpy(text, MRU_GetText(index));
|
||||
|
||||
if (file_readable(text)) //\todo Test 'map load succeeds' instead of 'file is readable'.
|
||||
{
|
||||
MRU_AddFile (text);
|
||||
Map_RegionOff();
|
||||
Map_Free();
|
||||
Map_LoadFile (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
MRU_used--;
|
||||
|
||||
for (std::size_t i = index; i < MRU_used; i++)
|
||||
MRU_SetText (i, MRU_GetText (i+1));
|
||||
|
||||
if (MRU_used == 0)
|
||||
{
|
||||
gtk_label_set_text(GTK_LABEL(GTK_BIN(MRU_items[0])->child), "Recent Files");
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(MRU_items[0]), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide(GTK_WIDGET(MRU_items[MRU_used]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LoadMRU
|
||||
{
|
||||
std::size_t m_number;
|
||||
public:
|
||||
LoadMRU(std::size_t number)
|
||||
: m_number(number)
|
||||
{
|
||||
}
|
||||
void load()
|
||||
{
|
||||
if (ConfirmModified("Open Map"))
|
||||
{
|
||||
MRU_Activate(m_number - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef MemberCaller<LoadMRU, &LoadMRU::load> LoadMRUCaller;
|
||||
|
||||
LoadMRU g_load_mru1(1);
|
||||
LoadMRU g_load_mru2(2);
|
||||
LoadMRU g_load_mru3(3);
|
||||
LoadMRU g_load_mru4(4);
|
||||
|
||||
void MRU_constructMenu(GtkMenu* menu)
|
||||
{
|
||||
{
|
||||
GtkMenuItem* item = create_menu_item_with_mnemonic(menu, "Recent Files", LoadMRUCaller(g_load_mru1));
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE);
|
||||
MRU_AddWidget(item, 0);
|
||||
}
|
||||
{
|
||||
GtkMenuItem* item = create_menu_item_with_mnemonic(menu, "2", LoadMRUCaller(g_load_mru2));
|
||||
gtk_widget_hide(GTK_WIDGET(item));
|
||||
MRU_AddWidget(item, 1);
|
||||
}
|
||||
{
|
||||
GtkMenuItem* item = create_menu_item_with_mnemonic(menu, "3", LoadMRUCaller(g_load_mru3));
|
||||
gtk_widget_hide(GTK_WIDGET(item));
|
||||
MRU_AddWidget(item, 2);
|
||||
}
|
||||
{
|
||||
GtkMenuItem* item = create_menu_item_with_mnemonic(menu, "4", LoadMRUCaller(g_load_mru4));
|
||||
gtk_widget_hide(GTK_WIDGET(item));
|
||||
MRU_AddWidget(item, 3);
|
||||
}
|
||||
}
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
void MRU_Construct()
|
||||
{
|
||||
GlobalPreferenceSystem().registerPreference("Count", SizeImportStringCaller(MRU_used), SizeExportStringCaller(MRU_used));
|
||||
|
||||
for(std::size_t i = 0; i != MRU_MAX; ++i)
|
||||
{
|
||||
GlobalPreferenceSystem().registerPreference(MRU_keys[i], CopiedStringImportStringCaller(MRU_filenames[i]), CopiedStringExportStringCaller(MRU_filenames[i]));
|
||||
}
|
||||
|
||||
MRU_Init();
|
||||
}
|
||||
void MRU_Destroy()
|
||||
{
|
||||
}
|
||||
33
radiant/mru.h
Normal file
33
radiant/mru.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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_MRU_H)
|
||||
#define INCLUDED_MRU_H
|
||||
|
||||
void MRU_AddFile (const char *str);
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void MRU_constructMenu(GtkMenu* menu);
|
||||
|
||||
void MRU_Construct();
|
||||
void MRU_Destroy();
|
||||
|
||||
#endif
|
||||
108
radiant/multimon.cpp
Normal file
108
radiant/multimon.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
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 "multimon.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "gtkutil/window.h"
|
||||
#include "preferences.h"
|
||||
|
||||
|
||||
multimon_globals_t g_multimon_globals;
|
||||
|
||||
LatchedBool g_Multimon_enableSysMenuPopups(false, "Floating windows sysmenu icons");
|
||||
|
||||
void MultiMonitor_constructPreferences(PreferencesPage& page)
|
||||
{
|
||||
GtkWidget* primary_monitor = page.appendCheckBox("Multi Monitor", "Start on Primary Monitor", g_multimon_globals.m_bStartOnPrimMon);
|
||||
GtkWidget* popup = page.appendCheckBox(
|
||||
"", "Disable system menu on popup windows",
|
||||
LatchedBoolImportCaller(g_Multimon_enableSysMenuPopups),
|
||||
BoolExportCaller(g_Multimon_enableSysMenuPopups.m_latched)
|
||||
);
|
||||
Widget_connectToggleDependency(popup, primary_monitor);
|
||||
}
|
||||
|
||||
#include "preferencesystem.h"
|
||||
#include "stringio.h"
|
||||
|
||||
#include <gdk/gdkdisplay.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
GdkRectangle primaryMonitor;
|
||||
}
|
||||
|
||||
void PositionWindowOnPrimaryScreen(WindowPosition& position)
|
||||
{
|
||||
if( position.w >= primaryMonitor.width - 12 )
|
||||
{
|
||||
position.w = primaryMonitor.width - 12;
|
||||
}
|
||||
if( position.h >= primaryMonitor.height - 24 )
|
||||
{
|
||||
position.h = primaryMonitor.height - 48;
|
||||
}
|
||||
if( position.x <= primaryMonitor.x || position.x + position.w >= (primaryMonitor.x + primaryMonitor.width) - 12 )
|
||||
{
|
||||
position.x = primaryMonitor.x + 6;
|
||||
}
|
||||
if( position.y <= primaryMonitor.y || position.y + position.h >= (primaryMonitor.y + primaryMonitor.height) - 48 )
|
||||
{
|
||||
position.y = primaryMonitor.y + 24;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMon_Construct()
|
||||
{
|
||||
// detect multiple monitors
|
||||
|
||||
GdkScreen* screen = gdk_display_get_default_screen(gdk_display_get_default());
|
||||
gint m = gdk_screen_get_n_monitors(screen);
|
||||
globalOutputStream() << "default screen has " << m << " monitors\n";
|
||||
for(int j = 0; j != m; ++j)
|
||||
{
|
||||
GdkRectangle geom;
|
||||
gdk_screen_get_monitor_geometry(screen, j, &geom);
|
||||
globalOutputStream() << "monitor " << j << " geometry: " << geom.x << ", " << geom.y << ", " << geom.width << ", " << geom.height << "\n";
|
||||
if(j == 0)
|
||||
{
|
||||
// I am making the assumption that monitor 0 is always the primary monitor on win32. Tested on WinXP with gtk+-2.4.
|
||||
primaryMonitor = geom;
|
||||
}
|
||||
}
|
||||
|
||||
if(m > 1)
|
||||
{
|
||||
g_multimon_globals.m_bStartOnPrimMon = true;
|
||||
}
|
||||
|
||||
GlobalPreferenceSystem().registerPreference("StartOnPrimMon", BoolImportStringCaller(g_multimon_globals.m_bStartOnPrimMon), BoolExportStringCaller(g_multimon_globals.m_bStartOnPrimMon));
|
||||
GlobalPreferenceSystem().registerPreference("NoSysMenuPopups", BoolImportStringCaller(g_Multimon_enableSysMenuPopups.m_latched), BoolExportStringCaller(g_Multimon_enableSysMenuPopups.m_latched));
|
||||
|
||||
g_Multimon_enableSysMenuPopups.useLatched();
|
||||
|
||||
PreferencesDialog_addInterfacePreferences(FreeCaller1<PreferencesPage&, MultiMonitor_constructPreferences>());
|
||||
}
|
||||
void MultiMon_Destroy()
|
||||
{
|
||||
}
|
||||
53
radiant/multimon.h
Normal file
53
radiant/multimon.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_MULTIMON_H)
|
||||
#define INCLUDED_MULTIMON_H
|
||||
|
||||
struct WindowPosition;
|
||||
|
||||
void PositionWindowOnPrimaryScreen(WindowPosition& position);
|
||||
|
||||
struct multimon_globals_t
|
||||
{
|
||||
bool m_bStartOnPrimMon;
|
||||
|
||||
multimon_globals_t() :
|
||||
m_bStartOnPrimMon(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern multimon_globals_t g_multimon_globals;
|
||||
|
||||
#if defined(WIN32)
|
||||
void MultiMon_Construct();
|
||||
void MultiMon_Destroy();
|
||||
#else
|
||||
inline void MultiMon_Construct()
|
||||
{
|
||||
}
|
||||
inline void MultiMon_Destroy()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
214
radiant/nullmodel.cpp
Normal file
214
radiant/nullmodel.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
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 "nullmodel.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "iscenegraph.h"
|
||||
#include "irender.h"
|
||||
#include "iselection.h"
|
||||
#include "iundo.h"
|
||||
#include "ientity.h"
|
||||
#include "ireference.h"
|
||||
#include "igl.h"
|
||||
#include "cullable.h"
|
||||
#include "renderable.h"
|
||||
#include "selectable.h"
|
||||
|
||||
#include "math/frustum.h"
|
||||
#include "scenelib.h"
|
||||
#include "instancelib.h"
|
||||
#include "entitylib.h"
|
||||
|
||||
class NullModel :
|
||||
public Bounded,
|
||||
public Cullable
|
||||
{
|
||||
Shader* m_state;
|
||||
AABB m_aabb_local;
|
||||
RenderableSolidAABB m_aabb_solid;
|
||||
RenderableWireframeAABB m_aabb_wire;
|
||||
public:
|
||||
NullModel() : m_aabb_local(Vector3(0, 0, 0), Vector3(8, 8, 8)), m_aabb_solid(m_aabb_local), m_aabb_wire(m_aabb_local)
|
||||
{
|
||||
m_state = GlobalShaderCache().capture("");
|
||||
}
|
||||
~NullModel()
|
||||
{
|
||||
GlobalShaderCache().release("");
|
||||
}
|
||||
|
||||
VolumeIntersectionValue intersectVolume(const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
return volume.TestAABB(m_aabb_local, localToWorld);
|
||||
}
|
||||
|
||||
const AABB& localAABB() const
|
||||
{
|
||||
return m_aabb_local;
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.SetState(m_state, Renderer::eFullMaterials);
|
||||
renderer.addRenderable(m_aabb_solid, localToWorld);
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.addRenderable(m_aabb_wire, 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class NullModelInstance : public scene::Instance, public Renderable, public SelectionTestable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
InstanceTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
InstanceContainedCast<NullModelInstance, Bounded>::install(m_casts);
|
||||
InstanceContainedCast<NullModelInstance, Cullable>::install(m_casts);
|
||||
InstanceStaticCast<NullModelInstance, Renderable>::install(m_casts);
|
||||
InstanceStaticCast<NullModelInstance, SelectionTestable>::install(m_casts);
|
||||
}
|
||||
InstanceTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
NullModel& m_nullmodel;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
Bounded& get(NullType<Bounded>)
|
||||
{
|
||||
return m_nullmodel;
|
||||
}
|
||||
Cullable& get(NullType<Cullable>)
|
||||
{
|
||||
return m_nullmodel;
|
||||
}
|
||||
|
||||
NullModelInstance(const scene::Path& path, scene::Instance* parent, NullModel& nullmodel) :
|
||||
Instance(path, parent, this, StaticTypeCasts::instance().get()),
|
||||
m_nullmodel(nullmodel)
|
||||
{
|
||||
}
|
||||
|
||||
void renderSolid(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_nullmodel.renderSolid(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
void renderWireframe(Renderer& renderer, const VolumeTest& volume) const
|
||||
{
|
||||
m_nullmodel.renderWireframe(renderer, volume, Instance::localToWorld());
|
||||
}
|
||||
|
||||
void testSelect(Selector& selector, SelectionTest& test)
|
||||
{
|
||||
m_nullmodel.testSelect(selector, test, Instance::localToWorld());
|
||||
}
|
||||
};
|
||||
|
||||
class NullModelNode : public scene::Node::Symbiot, public scene::Instantiable
|
||||
{
|
||||
class TypeCasts
|
||||
{
|
||||
NodeTypeCastTable m_casts;
|
||||
public:
|
||||
TypeCasts()
|
||||
{
|
||||
NodeStaticCast<NullModelNode, scene::Instantiable>::install(m_casts);
|
||||
}
|
||||
NodeTypeCastTable& get()
|
||||
{
|
||||
return m_casts;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
scene::Node m_node;
|
||||
InstanceSet m_instances;
|
||||
NullModel m_nullmodel;
|
||||
public:
|
||||
|
||||
typedef LazyStatic<TypeCasts> StaticTypeCasts;
|
||||
|
||||
NullModelNode() : m_node(this, this, StaticTypeCasts::instance().get())
|
||||
{
|
||||
m_node.m_isRoot = true;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
scene::Node& node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
scene::Instance* create(const scene::Path& path, scene::Instance* parent)
|
||||
{
|
||||
return new NullModelInstance(path, parent, m_nullmodel);
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
NodeSmartReference NewNullModel()
|
||||
{
|
||||
return NodeSmartReference((new NullModelNode)->node());
|
||||
}
|
||||
|
||||
void NullModel_construct()
|
||||
{
|
||||
}
|
||||
void NullModel_destroy()
|
||||
{
|
||||
}
|
||||
|
||||
37
radiant/nullmodel.h
Normal file
37
radiant/nullmodel.h
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
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_NULLMODEL_H)
|
||||
#define INCLUDED_NULLMODEL_H
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Node;
|
||||
}
|
||||
|
||||
#include "generic/referencecounted.h"
|
||||
typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;
|
||||
NodeSmartReference NewNullModel();
|
||||
|
||||
void NullModel_construct();
|
||||
void NullModel_destroy();
|
||||
|
||||
#endif
|
||||
51
radiant/parse.cpp
Normal file
51
radiant/parse.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
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 "parse.h"
|
||||
|
||||
#include "script/scripttokeniser.h"
|
||||
#include "script/scripttokenwriter.h"
|
||||
|
||||
class ScriptLibraryAPI
|
||||
{
|
||||
_QERScripLibTable m_scriptlibrary;
|
||||
public:
|
||||
typedef _QERScripLibTable Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
ScriptLibraryAPI()
|
||||
{
|
||||
m_scriptlibrary.m_pfnNewScriptTokeniser = &NewScriptTokeniser;
|
||||
m_scriptlibrary.m_pfnNewSimpleTokeniser = &NewSimpleTokeniser;
|
||||
m_scriptlibrary.m_pfnNewSimpleTokenWriter = &NewSimpleTokenWriter;
|
||||
}
|
||||
_QERScripLibTable* getTable()
|
||||
{
|
||||
return &m_scriptlibrary;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<ScriptLibraryAPI> ScriptLibraryModule;
|
||||
typedef Static<ScriptLibraryModule> StaticScriptLibraryModule;
|
||||
StaticRegisterModule staticRegisterScriptLibrary(StaticScriptLibraryModule::instance());
|
||||
25
radiant/parse.h
Normal file
25
radiant/parse.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_PARSE_H)
|
||||
#define INCLUDED_PARSE_H
|
||||
|
||||
#endif
|
||||
2793
radiant/patch.cpp
Normal file
2793
radiant/patch.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2064
radiant/patch.h
Normal file
2064
radiant/patch.h
Normal file
File diff suppressed because it is too large
Load Diff
1215
radiant/patchdialog.cpp
Normal file
1215
radiant/patchdialog.cpp
Normal file
File diff suppressed because it is too large
Load Diff
43
radiant/patchdialog.h
Normal file
43
radiant/patchdialog.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
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_PATCHDIALOG_H)
|
||||
#define INCLUDED_PATCHDIALOG_H
|
||||
|
||||
void PatchInspector_Construct();
|
||||
void PatchInspector_Destroy();
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
void PatchInspector_constructWindow(GtkWindow* main_window);
|
||||
void PatchInspector_destroyWindow();
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Graph;
|
||||
}
|
||||
|
||||
void Scene_PatchTranslateTexture_Selected(scene::Graph& graph, float s, float t);
|
||||
void Scene_PatchRotateTexture_Selected(scene::Graph& graph, float angle);
|
||||
void Scene_PatchScaleTexture_Selected(scene::Graph& graph, float s, float t);
|
||||
|
||||
|
||||
#endif
|
||||
1070
radiant/patchmanip.cpp
Normal file
1070
radiant/patchmanip.cpp
Normal file
File diff suppressed because it is too large
Load Diff
57
radiant/patchmanip.h
Normal file
57
radiant/patchmanip.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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_PATCHMANIP_H)
|
||||
#define INCLUDED_PATCHMANIP_H
|
||||
|
||||
#include "string/stringfwd.h"
|
||||
|
||||
void Patch_registerCommands();
|
||||
typedef struct _GtkToolbar GtkToolbar;
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
void Patch_constructToolbar(GtkToolbar* toolbar);
|
||||
void Patch_constructMenu(GtkMenu* menu);
|
||||
|
||||
namespace scene
|
||||
{
|
||||
class Graph;
|
||||
}
|
||||
|
||||
void Scene_PatchSetShader_Selected(scene::Graph& graph, const char* name);
|
||||
void Scene_PatchGetShader_Selected(scene::Graph& graph, CopiedString& name);
|
||||
void Scene_PatchSelectByShader(scene::Graph& graph, const char* name);
|
||||
void Scene_PatchFindReplaceShader(scene::Graph& graph, const char* find, const char* replace);
|
||||
void Scene_PatchFindReplaceShader_Selected(scene::Graph& graph, const char* find, const char* replace);
|
||||
|
||||
void Scene_PatchCapTexture_Selected(scene::Graph& graph);
|
||||
void Scene_PatchNaturalTexture_Selected(scene::Graph& graph);
|
||||
void Scene_PatchTileTexture_Selected(scene::Graph& graph, float s, float t);
|
||||
|
||||
void PatchFilters_construct();
|
||||
|
||||
void PatchPreferences_construct();
|
||||
|
||||
void Patch_registerPreferencesPage();
|
||||
|
||||
class PatchCreator;
|
||||
extern PatchCreator* g_patchCreator;
|
||||
|
||||
#endif
|
||||
221
radiant/patchmodule.cpp
Normal file
221
radiant/patchmodule.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
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 "patchmodule.h"
|
||||
|
||||
#include "qerplugin.h"
|
||||
#include "ipatch.h"
|
||||
|
||||
#include "patch.h"
|
||||
#include "patchmanip.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::size_t g_patchModuleCount = 0;
|
||||
}
|
||||
|
||||
void Patch_Construct(EPatchType type)
|
||||
{
|
||||
if(++g_patchModuleCount != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PatchFilters_construct();
|
||||
|
||||
PatchPreferences_construct();
|
||||
|
||||
Patch_registerPreferencesPage();
|
||||
|
||||
Patch::constructStatic(type);
|
||||
PatchInstance::constructStatic();
|
||||
|
||||
if(type == ePatchTypeDoom3)
|
||||
{
|
||||
MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 99;
|
||||
}
|
||||
else
|
||||
{
|
||||
MAX_PATCH_WIDTH = MAX_PATCH_HEIGHT = 15;
|
||||
}
|
||||
}
|
||||
|
||||
void Patch_Destroy()
|
||||
{
|
||||
if(--g_patchModuleCount != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Patch::destroyStatic();
|
||||
PatchInstance::destroyStatic();
|
||||
}
|
||||
|
||||
class Quake3PatchCreator : public PatchCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createPatch()
|
||||
{
|
||||
return (new PatchNodeQuake3())->node();
|
||||
}
|
||||
};
|
||||
|
||||
Quake3PatchCreator g_Quake3PatchCreator;
|
||||
|
||||
PatchCreator& GetQuake3PatchCreator()
|
||||
{
|
||||
return g_Quake3PatchCreator;
|
||||
}
|
||||
|
||||
class Doom3PatchCreator : public PatchCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createPatch()
|
||||
{
|
||||
return (new PatchNodeDoom3(true))->node();
|
||||
}
|
||||
};
|
||||
|
||||
Doom3PatchCreator g_Doom3PatchCreator;
|
||||
|
||||
PatchCreator& GetDoom3PatchCreator()
|
||||
{
|
||||
return g_Doom3PatchCreator;
|
||||
}
|
||||
|
||||
class Doom3PatchDef2Creator : public PatchCreator
|
||||
{
|
||||
public:
|
||||
scene::Node& createPatch()
|
||||
{
|
||||
return (new PatchNodeDoom3())->node();
|
||||
}
|
||||
};
|
||||
|
||||
Doom3PatchDef2Creator g_Doom3PatchDef2Creator;
|
||||
|
||||
PatchCreator& GetDoom3PatchDef2Creator()
|
||||
{
|
||||
return g_Doom3PatchDef2Creator;
|
||||
}
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
class PatchDependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalFilterModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class PatchQuake3API : public TypeSystemRef
|
||||
{
|
||||
PatchCreator* m_patchquake3;
|
||||
public:
|
||||
typedef PatchCreator Type;
|
||||
STRING_CONSTANT(Name, "quake3");
|
||||
|
||||
PatchQuake3API()
|
||||
{
|
||||
Patch_Construct(ePatchTypeQuake3);
|
||||
|
||||
m_patchquake3 = &GetQuake3PatchCreator();
|
||||
g_patchCreator = m_patchquake3;
|
||||
}
|
||||
~PatchQuake3API()
|
||||
{
|
||||
Patch_Destroy();
|
||||
}
|
||||
PatchCreator* getTable()
|
||||
{
|
||||
return m_patchquake3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<PatchQuake3API, PatchDependencies> PatchQuake3Module;
|
||||
typedef Static<PatchQuake3Module> StaticPatchQuake3Module;
|
||||
StaticRegisterModule staticRegisterPatchQuake3(StaticPatchQuake3Module::instance());
|
||||
|
||||
|
||||
|
||||
class PatchDoom3API : public TypeSystemRef
|
||||
{
|
||||
PatchCreator* m_patchdoom3;
|
||||
public:
|
||||
typedef PatchCreator Type;
|
||||
STRING_CONSTANT(Name, "doom3");
|
||||
|
||||
PatchDoom3API()
|
||||
{
|
||||
Patch_Construct(ePatchTypeDoom3);
|
||||
|
||||
m_patchdoom3 = &GetDoom3PatchCreator();
|
||||
}
|
||||
~PatchDoom3API()
|
||||
{
|
||||
Patch_Destroy();
|
||||
}
|
||||
PatchCreator* getTable()
|
||||
{
|
||||
return m_patchdoom3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<PatchDoom3API, PatchDependencies> PatchDoom3Module;
|
||||
typedef Static<PatchDoom3Module> StaticPatchDoom3Module;
|
||||
StaticRegisterModule staticRegisterPatchDoom3(StaticPatchDoom3Module::instance());
|
||||
|
||||
|
||||
class PatchDef2Doom3API : public TypeSystemRef
|
||||
{
|
||||
PatchCreator* m_patchdef2doom3;
|
||||
public:
|
||||
typedef PatchCreator Type;
|
||||
STRING_CONSTANT(Name, "def2doom3");
|
||||
|
||||
PatchDef2Doom3API()
|
||||
{
|
||||
Patch_Construct(ePatchTypeDoom3);
|
||||
|
||||
m_patchdef2doom3 = &GetDoom3PatchDef2Creator();
|
||||
g_patchCreator = m_patchdef2doom3;
|
||||
}
|
||||
~PatchDef2Doom3API()
|
||||
{
|
||||
Patch_Destroy();
|
||||
}
|
||||
PatchCreator* getTable()
|
||||
{
|
||||
return m_patchdef2doom3;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<PatchDef2Doom3API, PatchDependencies> PatchDef2Doom3Module;
|
||||
typedef Static<PatchDef2Doom3Module> StaticPatchDef2Doom3Module;
|
||||
StaticRegisterModule staticRegisterPatchDef2Doom3(StaticPatchDef2Doom3Module::instance());
|
||||
|
||||
|
||||
|
||||
25
radiant/patchmodule.h
Normal file
25
radiant/patchmodule.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_PATCHMODULE_H)
|
||||
#define INCLUDED_PATCHMODULE_H
|
||||
|
||||
#endif
|
||||
317
radiant/plugin.cpp
Normal file
317
radiant/plugin.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
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 "qerplugin.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "ishaders.h"
|
||||
#include "ientity.h"
|
||||
#include "ieclass.h"
|
||||
#include "irender.h"
|
||||
#include "iscenegraph.h"
|
||||
#include "iselection.h"
|
||||
#include "ifilter.h"
|
||||
#include "iscriplib.h"
|
||||
#include "igl.h"
|
||||
#include "iundo.h"
|
||||
#include "itextures.h"
|
||||
#include "ireference.h"
|
||||
#include "ifiletypes.h"
|
||||
#include "preferencesystem.h"
|
||||
#include "ibrush.h"
|
||||
#include "ipatch.h"
|
||||
#include "iimage.h"
|
||||
#include "itoolbar.h"
|
||||
#include "iplugin.h"
|
||||
#include "imap.h"
|
||||
#include "namespace.h"
|
||||
|
||||
#include "gtkutil/messagebox.h"
|
||||
#include "gtkutil/filechooser.h"
|
||||
#include "maplib.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "map.h"
|
||||
#include "qe3.h"
|
||||
#include "entityinspector.h"
|
||||
#include "entitylist.h"
|
||||
#include "points.h"
|
||||
#include "gtkmisc.h"
|
||||
#include "texwindow.h"
|
||||
#include "mainframe.h"
|
||||
#include "build.h"
|
||||
#include "mru.h"
|
||||
#include "multimon.h"
|
||||
#include "surfacedialog.h"
|
||||
#include "groupdialog.h"
|
||||
#include "patchdialog.h"
|
||||
#include "camwindow.h"
|
||||
#include "watchbsp.h"
|
||||
#include "xywindow.h"
|
||||
#include "entity.h"
|
||||
#include "select.h"
|
||||
#include "preferences.h"
|
||||
#include "autosave.h"
|
||||
#include "plugintoolbar.h"
|
||||
#include "findtexturedialog.h"
|
||||
#include "nullmodel.h"
|
||||
#include "grid.h"
|
||||
|
||||
#include "modulesystem/modulesmap.h"
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
const char* GameDescription_getKeyValue(const char* key)
|
||||
{
|
||||
return g_pGameDescription->getKeyValue(key);
|
||||
}
|
||||
|
||||
const char* GameDescription_getRequiredKeyValue(const char* key)
|
||||
{
|
||||
return g_pGameDescription->getRequiredKeyValue(key);
|
||||
}
|
||||
|
||||
class RadiantCoreAPI
|
||||
{
|
||||
_QERFuncTable_1 m_radiantcore;
|
||||
public:
|
||||
typedef _QERFuncTable_1 Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
RadiantCoreAPI()
|
||||
{
|
||||
m_radiantcore.getEnginePath = &EnginePath_get;
|
||||
m_radiantcore.getAppPath = &AppPath_get;
|
||||
m_radiantcore.getGameToolsPath = &GameToolsPath_get;
|
||||
m_radiantcore.getSettingsPath = &SettingsPath_get;
|
||||
|
||||
m_radiantcore.getGameName = &gamename_get;
|
||||
m_radiantcore.getGameMode = &gamemode_get;
|
||||
|
||||
m_radiantcore.getGameDescriptionKeyValue = &GameDescription_getKeyValue;
|
||||
m_radiantcore.getRequiredGameDescriptionKeyValue = &GameDescription_getRequiredKeyValue;
|
||||
|
||||
m_radiantcore.attachGameToolsPathObserver = Radiant_attachGameToolsPathObserver;
|
||||
m_radiantcore.detachGameToolsPathObserver = Radiant_detachGameToolsPathObserver;
|
||||
m_radiantcore.attachEnginePathObserver = Radiant_attachEnginePathObserver;
|
||||
m_radiantcore.detachEnginePathObserver = Radiant_detachEnginePathObserver;
|
||||
m_radiantcore.attachGameNameObserver = Radiant_attachGameNameObserver;
|
||||
m_radiantcore.detachGameNameObserver = Radiant_detachGameNameObserver;
|
||||
m_radiantcore.attachGameModeObserver = Radiant_attachGameModeObserver;
|
||||
m_radiantcore.detachGameModeObserver = Radiant_detachGameModeObserver;
|
||||
|
||||
m_radiantcore.m_pfnMessageBox = >k_MessageBox;
|
||||
m_radiantcore.m_pfnFileDialog = &file_dialog;
|
||||
m_radiantcore.m_pfnColorDialog = &color_dialog;
|
||||
m_radiantcore.m_pfnDirDialog = &dir_dialog;
|
||||
m_radiantcore.m_pfnNewImage = &new_plugin_image;
|
||||
}
|
||||
_QERFuncTable_1* getTable()
|
||||
{
|
||||
return &m_radiantcore;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<RadiantCoreAPI> RadiantCoreModule;
|
||||
typedef Static<RadiantCoreModule> StaticRadiantCoreModule;
|
||||
StaticRegisterModule staticRegisterRadiantCore(StaticRadiantCoreModule::instance());
|
||||
|
||||
|
||||
class RadiantDependencies :
|
||||
public GlobalRadiantModuleRef,
|
||||
public GlobalFileSystemModuleRef,
|
||||
public GlobalEntityModuleRef,
|
||||
public GlobalShadersModuleRef,
|
||||
public GlobalBrushModuleRef,
|
||||
public GlobalSceneGraphModuleRef,
|
||||
public GlobalShaderCacheModuleRef,
|
||||
public GlobalFiletypesModuleRef,
|
||||
public GlobalSelectionModuleRef,
|
||||
public GlobalReferenceModuleRef,
|
||||
public GlobalOpenGLModuleRef,
|
||||
public GlobalEntityClassManagerModuleRef,
|
||||
public GlobalUndoModuleRef,
|
||||
public GlobalScripLibModuleRef,
|
||||
public GlobalNamespaceModuleRef
|
||||
{
|
||||
ImageModulesRef m_image_modules;
|
||||
MapModulesRef m_map_modules;
|
||||
ToolbarModulesRef m_toolbar_modules;
|
||||
PluginModulesRef m_plugin_modules;
|
||||
|
||||
public:
|
||||
RadiantDependencies() :
|
||||
GlobalEntityModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entities")),
|
||||
GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")),
|
||||
GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")),
|
||||
GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")),
|
||||
m_image_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("texturetypes")),
|
||||
m_map_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("maptypes")),
|
||||
m_toolbar_modules("*"),
|
||||
m_plugin_modules("*")
|
||||
{
|
||||
}
|
||||
|
||||
ImageModules& getImageModules()
|
||||
{
|
||||
return m_image_modules.get();
|
||||
}
|
||||
MapModules& getMapModules()
|
||||
{
|
||||
return m_map_modules.get();
|
||||
}
|
||||
ToolbarModules& getToolbarModules()
|
||||
{
|
||||
return m_toolbar_modules.get();
|
||||
}
|
||||
PluginModules& getPluginModules()
|
||||
{
|
||||
return m_plugin_modules.get();
|
||||
}
|
||||
};
|
||||
|
||||
class Radiant : public TypeSystemRef
|
||||
{
|
||||
public:
|
||||
Radiant()
|
||||
{
|
||||
Preferences_Init();
|
||||
|
||||
GlobalFiletypes().addType("sound", "wav", filetype_t("PCM sound files", "*.wav"));
|
||||
|
||||
Selection_construct();
|
||||
HomePaths_Construct();
|
||||
VFS_Construct();
|
||||
Grid_construct();
|
||||
MultiMon_Construct();
|
||||
MRU_Construct();
|
||||
Pointfile_Construct();
|
||||
GLWindow_Construct();
|
||||
BuildMenu_Construct();
|
||||
Map_Construct();
|
||||
EntityList_Construct();
|
||||
MainFrame_Construct();
|
||||
GroupDialog_Construct();
|
||||
SurfaceInspector_Construct();
|
||||
PatchInspector_Construct();
|
||||
CamWnd_Construct();
|
||||
XYWindow_Construct();
|
||||
BuildMonitor_Construct();
|
||||
TextureBrowser_Construct();
|
||||
Entity_Construct();
|
||||
Autosave_Construct();
|
||||
EntityInspector_construct();
|
||||
FindTextureDialog_Construct();
|
||||
NullModel_construct();
|
||||
MapRoot_construct();
|
||||
|
||||
EnginePath_verify();
|
||||
EnginePath_Realise();
|
||||
}
|
||||
~Radiant()
|
||||
{
|
||||
EnginePath_Unrealise();
|
||||
|
||||
MapRoot_destroy();
|
||||
NullModel_destroy();
|
||||
FindTextureDialog_Destroy();
|
||||
EntityInspector_destroy();
|
||||
Autosave_Destroy();
|
||||
Entity_Destroy();
|
||||
TextureBrowser_Destroy();
|
||||
BuildMonitor_Destroy();
|
||||
XYWindow_Destroy();
|
||||
CamWnd_Destroy();
|
||||
PatchInspector_Destroy();
|
||||
SurfaceInspector_Destroy();
|
||||
GroupDialog_Destroy();
|
||||
MainFrame_Destroy();
|
||||
EntityList_Destroy();
|
||||
Map_Destroy();
|
||||
BuildMenu_Destroy();
|
||||
GLWindow_Destroy();
|
||||
Pointfile_Destroy();
|
||||
MRU_Destroy();
|
||||
MultiMon_Destroy();
|
||||
Grid_destroy();
|
||||
VFS_Destroy();
|
||||
HomePaths_Destroy();
|
||||
Selection_destroy();
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
bool g_RadiantInitialised = false;
|
||||
RadiantDependencies* g_RadiantDependencies;
|
||||
Radiant* g_Radiant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Radiant_Construct(ModuleServer& server)
|
||||
{
|
||||
GlobalModuleServer::instance().set(server);
|
||||
StaticModuleRegistryList().instance().registerModules();
|
||||
|
||||
g_RadiantDependencies = new RadiantDependencies();
|
||||
|
||||
g_RadiantInitialised = !server.getError();
|
||||
|
||||
if(g_RadiantInitialised)
|
||||
{
|
||||
g_Radiant = new Radiant;
|
||||
}
|
||||
|
||||
return g_RadiantInitialised;
|
||||
}
|
||||
void Radiant_Destroy()
|
||||
{
|
||||
if(g_RadiantInitialised)
|
||||
{
|
||||
delete g_Radiant;
|
||||
}
|
||||
|
||||
delete g_RadiantDependencies;
|
||||
}
|
||||
|
||||
ImageModules& Radiant_getImageModules()
|
||||
{
|
||||
return g_RadiantDependencies->getImageModules();
|
||||
}
|
||||
MapModules& Radiant_getMapModules()
|
||||
{
|
||||
return g_RadiantDependencies->getMapModules();
|
||||
}
|
||||
ToolbarModules& Radiant_getToolbarModules()
|
||||
{
|
||||
return g_RadiantDependencies->getToolbarModules();
|
||||
}
|
||||
PluginModules& Radiant_getPluginModules()
|
||||
{
|
||||
return g_RadiantDependencies->getPluginModules();
|
||||
}
|
||||
|
||||
|
||||
47
radiant/plugin.h
Normal file
47
radiant/plugin.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
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
|
||||
|
||||
class ModuleServer;
|
||||
bool Radiant_Construct(ModuleServer& server);
|
||||
void Radiant_Destroy();
|
||||
|
||||
|
||||
template<typename Type>
|
||||
class Modules;
|
||||
|
||||
struct _QERPlugImageTable;
|
||||
typedef Modules<_QERPlugImageTable> ImageModules;
|
||||
ImageModules& Radiant_getImageModules();
|
||||
class MapFormat;
|
||||
typedef Modules<MapFormat> MapModules;
|
||||
MapModules& Radiant_getMapModules();
|
||||
struct _QERPlugToolbarTable;
|
||||
typedef Modules<_QERPlugToolbarTable> ToolbarModules;
|
||||
ToolbarModules& Radiant_getToolbarModules();
|
||||
struct _QERPluginTable;
|
||||
typedef Modules<_QERPluginTable> PluginModules;
|
||||
PluginModules& Radiant_getPluginModules();
|
||||
|
||||
|
||||
#endif
|
||||
92
radiant/pluginapi.cpp
Normal file
92
radiant/pluginapi.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
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 "pluginapi.h"
|
||||
|
||||
#include "modulesystem.h"
|
||||
#include "qerplugin.h"
|
||||
|
||||
#include "generic/callback.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
#include "gtkmisc.h"
|
||||
|
||||
#include "camwindow.h"
|
||||
|
||||
#include "mainframe.h"
|
||||
|
||||
|
||||
// camera API
|
||||
void QERApp_GetCamera( Vector3& origin, Vector3& angles )
|
||||
{
|
||||
CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
|
||||
origin = Camera_getOrigin(camwnd);
|
||||
angles = Camera_getAngles(camwnd);
|
||||
}
|
||||
|
||||
void QERApp_SetCamera( const Vector3& origin, const Vector3& angles )
|
||||
{
|
||||
CamWnd& camwnd = *g_pParentWnd->GetCamWnd();
|
||||
Camera_setOrigin(camwnd, origin);
|
||||
Camera_setAngles(camwnd, angles);
|
||||
}
|
||||
|
||||
void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )
|
||||
{
|
||||
#if 0
|
||||
CamWnd* camwnd = g_pParentWnd->GetCamWnd();
|
||||
|
||||
gtk_window_get_position(GTK_WINDOW(camwnd->m_window), x, y);
|
||||
|
||||
*width = camwnd->Camera()->width;
|
||||
*height = camwnd->Camera()->height;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "icamera.h"
|
||||
|
||||
class CameraAPI
|
||||
{
|
||||
_QERCameraTable m_camera;
|
||||
public:
|
||||
typedef _QERCameraTable Type;
|
||||
STRING_CONSTANT(Name, "*");
|
||||
|
||||
CameraAPI()
|
||||
{
|
||||
m_camera.m_pfnGetCamera = &QERApp_GetCamera;
|
||||
m_camera.m_pfnSetCamera = &QERApp_SetCamera;
|
||||
m_camera.m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;
|
||||
}
|
||||
_QERCameraTable* getTable()
|
||||
{
|
||||
return &m_camera;
|
||||
}
|
||||
};
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
#include "modulesystem/moduleregistry.h"
|
||||
|
||||
typedef SingletonModule<CameraAPI> CameraModule;
|
||||
typedef Static<CameraModule> StaticCameraModule;
|
||||
StaticRegisterModule staticRegisterCamera(StaticCameraModule::instance());
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user