mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-27 06:02:29 +00:00
eaa3e3169f
* TTimo, please have a look at the mainframe.cpp part git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant@208 8a3a26a2-13c4-0310-b231-cf6edde360e5
2525 lines
74 KiB
C++
2525 lines
74 KiB
C++
/*
|
|
Copyright (C) 1999-2007 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
|
|
*/
|
|
|
|
// PlugInManager.cpp: implementation of the CPlugInManager class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#if defined (__linux__) || defined (__APPLE__)
|
|
#include <dirent.h>
|
|
#include <sys/time.h>
|
|
#endif
|
|
#ifdef __APPLE__
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include <dlfcn.h>
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|
|
#ifdef _WIN32
|
|
#include "objbase.h"
|
|
#endif
|
|
#include "pluginmanager.h"
|
|
#include "plugin.h"
|
|
#include "missing.h"
|
|
#include "filters.h"
|
|
|
|
#include "version.h"
|
|
|
|
CRadiantImageManager g_ImageManager;
|
|
CRadiantPluginManager g_PluginsManager;
|
|
|
|
_QERPlugSurfaceTable g_SurfaceTable;
|
|
_QERFileSystemTable g_FileSystemTable;
|
|
_QERShadersTable g_ShadersTable;
|
|
_QERPlugMapTable g_MapTable;
|
|
_QERPlugMapTable g_MapTable2;
|
|
_QEREntityTable g_EntityTable;
|
|
_EClassTable g_EClassDefTable;
|
|
|
|
/*!
|
|
extending entity class formats
|
|
this approach only allows a single additional format, but it is enough for now
|
|
*/
|
|
bool g_bHaveEClassExt = false;
|
|
_EClassTable g_EClassExtTable;
|
|
|
|
|
|
filetype_t g_pattern_all("all files", "*.*");
|
|
filetype_t g_pattern_projqe4v2("qe4 v2 project files", "*.qe4");
|
|
filetype_t g_pattern_projxml("xml project files", "*.proj");
|
|
filetype_t g_pattern_mapq3("quake3 maps", "*.map");
|
|
filetype_t g_pattern_mapxml("xml quake3 maps", "*.xmap");
|
|
filetype_t g_pattern_modelmd3("md3 models", "*.md3");
|
|
filetype_t g_pattern_modelmdc("mdc models", "*.mdc");
|
|
filetype_t g_pattern_modelmd2("md2 models", "*.md2");
|
|
filetype_t g_pattern_modelmdl("mdl models", "*.mdl");
|
|
//filetype_t g_pattern_modelea3("EA3 models", "*.ea3");
|
|
filetype_t g_pattern_soundwav("PCM sound files", "*.wav");
|
|
filetype_t g_pattern_regq3("quake3 region", "*.reg");
|
|
|
|
#include <map>
|
|
|
|
class RadiantFileTypeRegistry : public IFileTypeRegistry
|
|
{
|
|
public:
|
|
virtual ~RadiantFileTypeRegistry() {}
|
|
virtual void addType(const char* key, filetype_t type)
|
|
{
|
|
m_typelists[key].push_back(type);
|
|
}
|
|
virtual void getTypeList(const char* key, IFileTypeList* typelist)
|
|
{
|
|
filetype_list_t& list_ref = m_typelists[key];
|
|
for(unsigned int i=0; i<list_ref.size(); ++i)
|
|
typelist->addType(list_ref[i].getType());
|
|
}
|
|
private:
|
|
struct filetype_copy_t
|
|
{
|
|
inline filetype_copy_t(const filetype_t other)
|
|
: m_name(other.name), m_pattern(other.pattern)
|
|
{}
|
|
inline filetype_t getType() const
|
|
{
|
|
return filetype_t(m_name.c_str(), m_pattern.c_str());
|
|
}
|
|
private:
|
|
string_t m_name;
|
|
string_t m_pattern;
|
|
};
|
|
typedef vector<filetype_copy_t> filetype_list_t;
|
|
map<string_t, filetype_list_t> m_typelists;
|
|
};
|
|
|
|
static RadiantFileTypeRegistry g_patterns;
|
|
|
|
IFileTypeRegistry* GetFileTypeRegistry()
|
|
{
|
|
return &g_patterns;
|
|
}
|
|
|
|
void InitFileTypes()
|
|
{
|
|
//GetFileTypeRegistry()->addType("project", g_pattern_projqe4v2);
|
|
GetFileTypeRegistry()->addType("project", g_pattern_projxml);
|
|
|
|
GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapq3);
|
|
GetFileTypeRegistry()->addType(MAP_MAJOR, g_pattern_mapxml);
|
|
|
|
GetFileTypeRegistry()->addType("region", g_pattern_regq3);
|
|
/*
|
|
GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd3);
|
|
GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmd2);
|
|
GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdl);
|
|
GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelmdc);
|
|
//GetFileTypeRegistry()->addType(MODEL_MAJOR, g_pattern_modelea3);
|
|
*/
|
|
|
|
GetFileTypeRegistry()->addType("sound", g_pattern_soundwav);
|
|
}
|
|
|
|
|
|
class CRadiantModelModuleManager : public CSynapseAPIManager
|
|
{
|
|
typedef list<APIDescriptor_t*> APIDescriptorList;
|
|
|
|
APIDescriptorList mAPIs;
|
|
public:
|
|
CRadiantModelModuleManager()
|
|
{
|
|
SetMatchAPI(MODEL_MAJOR, "*");
|
|
}
|
|
virtual ~CRadiantModelModuleManager()
|
|
{
|
|
APIDescriptorList::iterator i;
|
|
for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
|
|
{
|
|
delete (_QERPlugModelTable*)(*i)->mpTable;
|
|
delete *i;
|
|
*i = NULL;
|
|
}
|
|
mAPIs.clear();
|
|
}
|
|
|
|
// CSynapseAPIManager interface -------------------
|
|
APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
|
|
{
|
|
APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
|
|
pRequireAPI->mpTable = new _QERPlugModelTable;
|
|
((_QERPlugModelTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugModelTable);
|
|
pRequireAPI->mSize = sizeof(_QERPlugModelTable);
|
|
mAPIs.push_front(pRequireAPI);
|
|
return pRequireAPI;
|
|
}
|
|
|
|
// Model Manager specific
|
|
const _QERPlugModelTable* GetModelTable(const char* version)
|
|
{
|
|
APIDescriptorList::iterator i;
|
|
for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
|
|
if(strcmp(version, (*i)->minor_name) == 0)
|
|
return ((_QERPlugModelTable*)(*i)->mpTable);
|
|
return NULL;
|
|
}
|
|
};
|
|
|
|
CRadiantModelModuleManager g_ModelManager;
|
|
|
|
/*! One of these exists for each unique model ID in use */
|
|
class CModelWrapper
|
|
{
|
|
friend class CModelManager;
|
|
public:
|
|
CModelWrapper (const char *id, const char* version) : refcount(1)
|
|
{
|
|
copy(id, version);
|
|
construct();
|
|
}
|
|
void Refresh()
|
|
{
|
|
destroy();
|
|
construct();
|
|
}
|
|
~CModelWrapper ()
|
|
{
|
|
destroy();
|
|
}
|
|
private:
|
|
void copy(const char* id, const char* version)
|
|
{
|
|
m_id = id;
|
|
m_version = version;
|
|
}
|
|
void construct()
|
|
{
|
|
m_model.pRender = NULL;
|
|
m_model.pSelect = NULL;
|
|
m_model.pEdit = NULL;
|
|
|
|
const _QERPlugModelTable* pTable = g_ModelManager.GetModelTable(m_version.c_str());
|
|
|
|
if(pTable != NULL)
|
|
pTable->m_pfnLoadModel(&m_model, m_id.c_str());
|
|
}
|
|
void destroy()
|
|
{
|
|
if (m_model.pRender) m_model.pRender->DecRef();
|
|
if (m_model.pSelect) m_model.pSelect->DecRef();
|
|
if (m_model.pEdit) m_model.pEdit->DecRef();
|
|
}
|
|
string_t m_id;
|
|
string_t m_version;
|
|
entity_interfaces_t m_model;
|
|
int refcount;
|
|
};
|
|
|
|
/*! Creates and tracks CModelWrapper instances.
|
|
Creates a new instance for each unique ID requested, keeps count of the number of
|
|
times an ID is being referenced, and destroys any instance that is no longer in use */
|
|
class CModelManager : public IModelCache
|
|
{
|
|
public:
|
|
CModelManager()
|
|
{
|
|
m_ptrs = g_ptr_array_new ();
|
|
}
|
|
virtual ~CModelManager()
|
|
{
|
|
g_ptr_array_free(m_ptrs, FALSE);
|
|
}
|
|
|
|
virtual void DeleteByID(const char *id, const char* version)
|
|
{
|
|
unsigned int i;
|
|
CModelWrapper *elem;
|
|
for(i=0; i<m_ptrs->len; i++)
|
|
{
|
|
elem = (CModelWrapper*)m_ptrs->pdata[i];
|
|
if(strcmp(elem->m_version.c_str(), version) == 0
|
|
&& strcmp(elem->m_id.c_str(), id) == 0
|
|
&& --elem->refcount == 0)
|
|
{
|
|
g_ptr_array_remove_index_fast(m_ptrs, i);
|
|
delete elem;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual entity_interfaces_t *GetByID(const char *id, const char* version)
|
|
{
|
|
unsigned int i;
|
|
CModelWrapper *elem;
|
|
for(i=0; i<m_ptrs->len; i++)
|
|
{
|
|
elem = (CModelWrapper*)m_ptrs->pdata[i];
|
|
if(strcmp(elem->m_version.c_str(), version) == 0
|
|
&& strcmp(elem->m_id.c_str(), id) == 0)
|
|
{
|
|
elem->refcount++;
|
|
return &elem->m_model;
|
|
}
|
|
}
|
|
|
|
elem = new CModelWrapper(id, version);
|
|
g_ptr_array_add(m_ptrs, elem);
|
|
|
|
return &elem->m_model;
|
|
}
|
|
|
|
virtual void RefreshAll()
|
|
{
|
|
for(unsigned int i=0; i<m_ptrs->len; ++i)
|
|
((CModelWrapper*)m_ptrs->pdata[i])->Refresh();
|
|
}
|
|
private:
|
|
GPtrArray *m_ptrs; // array of CModelWrapper*
|
|
};
|
|
|
|
CModelManager g_model_cache;
|
|
|
|
IModelCache* GetModelCache()
|
|
{
|
|
return &g_model_cache;
|
|
}
|
|
|
|
// toolbar manager
|
|
class CRadiantToolbarModuleManager : public CSynapseAPIManager
|
|
{
|
|
typedef list<APIDescriptor_t*> APIDescriptorList;
|
|
|
|
APIDescriptorList mAPIs;
|
|
public:
|
|
CRadiantToolbarModuleManager()
|
|
{
|
|
SetMatchAPI(TOOLBAR_MAJOR, "*");
|
|
}
|
|
virtual ~CRadiantToolbarModuleManager()
|
|
{
|
|
APIDescriptorList::iterator i;
|
|
for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
|
|
{
|
|
delete (_QERPlugToolbarTable*)(*i)->mpTable;
|
|
delete *i;
|
|
*i = NULL;
|
|
}
|
|
mAPIs.clear();
|
|
}
|
|
|
|
// CSynapseAPIManager interface -------------------
|
|
APIDescriptor_t* BuildRequireAPI(APIDescriptor_t* pAPI)
|
|
{
|
|
APIDescriptor_t* pRequireAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
|
|
pRequireAPI->mpTable = new _QERPlugToolbarTable;
|
|
((_QERPlugToolbarTable*)pRequireAPI->mpTable)->m_nSize = sizeof(_QERPlugToolbarTable);
|
|
pRequireAPI->mSize = sizeof(_QERPlugToolbarTable);
|
|
mAPIs.push_front(pRequireAPI);
|
|
return pRequireAPI;
|
|
}
|
|
|
|
// Toolbar Manager specific
|
|
void ConstructToolbar()
|
|
{
|
|
APIDescriptorList::iterator i;
|
|
for(i=mAPIs.begin(); i!=mAPIs.end(); i++)
|
|
AddItem((_QERPlugToolbarTable*)(*i)->mpTable);
|
|
}
|
|
|
|
private:
|
|
|
|
void AddItem(_QERPlugToolbarTable* pTable)
|
|
{
|
|
const unsigned int count = pTable->m_pfnToolbarButtonCount();
|
|
for(unsigned int i=0; i<count; ++i)
|
|
{
|
|
const IToolbarButton* button = pTable->m_pfnGetToolbarButton(i);
|
|
g_pParentWnd->AddPlugInToolbarButton(button);
|
|
}
|
|
}
|
|
};
|
|
|
|
CRadiantToolbarModuleManager g_ToolbarModuleManager;
|
|
|
|
|
|
/* image manager ---------------------------------------- */
|
|
|
|
CRadiantImageManager::~CRadiantImageManager()
|
|
{
|
|
list<CImageTableSlot *>::iterator iSlot;
|
|
for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
|
|
{
|
|
delete *iSlot;
|
|
*iSlot = NULL;
|
|
}
|
|
}
|
|
|
|
void CImageTableSlot::InitForFillAPITable(APIDescriptor_t *pAPI)
|
|
{
|
|
mpAPI = pAPI;
|
|
mpTable = new _QERPlugImageTable;
|
|
mpTable->m_nSize = sizeof(_QERPlugImageTable);
|
|
mpAPI->mSize = sizeof(_QERPlugImageTable);
|
|
mpAPI->mpTable = mpTable;
|
|
}
|
|
|
|
void CRadiantImageManager::FillAPITable(APIDescriptor_t *pAPI)
|
|
{
|
|
CImageTableSlot *pSlot = new CImageTableSlot();
|
|
pSlot->InitForFillAPITable(pAPI);
|
|
mSlots.push_front(pSlot);
|
|
}
|
|
|
|
/*!
|
|
Loads an image by calling the module that handles the extension extracted from the filename
|
|
\param name The filename to load. If no extension is provided, we walk the list of supported extensions.
|
|
\param pic The returned image data
|
|
\param width The returned width of the image
|
|
\param height The returned height of the image
|
|
*/
|
|
void CRadiantImageManager::LoadImage(const char *name, byte **pic, int *width, int *height)
|
|
{
|
|
const char *ext = NULL;
|
|
int len;
|
|
|
|
// extract extension
|
|
len = strlen (name);
|
|
if ((len > 5) && (name[len-4] == '.'))
|
|
ext = &name[len-3];
|
|
|
|
if (ext == NULL)
|
|
{
|
|
// if no extension is provided, start walking through the list
|
|
Str fullname;
|
|
list<CImageTableSlot *>::iterator iSlot;
|
|
for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
|
|
{
|
|
APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
|
|
fullname.Format("%s.%s", name, pAPI->minor_name);
|
|
(*iSlot)->GetTable()->m_pfnLoadImage(fullname.GetBuffer(), pic, width, height);
|
|
if (*pic)
|
|
return; // this was the right extension, we loaded
|
|
}
|
|
return;
|
|
}
|
|
|
|
// start walking the interfaces
|
|
list<CImageTableSlot *>::iterator iSlot;
|
|
for(iSlot = mSlots.begin(); iSlot != mSlots.end(); iSlot++)
|
|
{
|
|
APIDescriptor_t *pAPI = (*iSlot)->GetDescriptor();
|
|
if (!strcmp(pAPI->minor_name, ext))
|
|
{
|
|
(*iSlot)->GetTable()->m_pfnLoadImage(name, pic, width, height);
|
|
return;
|
|
}
|
|
}
|
|
Sys_FPrintf(SYS_WRN, "WARNING: no image table for extension '%s'\n", ext);
|
|
}
|
|
|
|
void CRadiantImageManager::BeginExtensionsScan()
|
|
{
|
|
mExtScanSlot = mSlots.begin();
|
|
}
|
|
|
|
const char* CRadiantImageManager::GetNextExtension()
|
|
{
|
|
if (mExtScanSlot != mSlots.end())
|
|
{
|
|
char *ext = (*mExtScanSlot)->GetDescriptor()->minor_name;
|
|
mExtScanSlot++;
|
|
return ext;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* plugin manager --------------------------------------- */
|
|
APIDescriptor_t* CRadiantPluginManager::BuildRequireAPI(APIDescriptor_t *pAPI)
|
|
{
|
|
CPluginSlot *pSlot = new CPluginSlot(pAPI);
|
|
mSlots.push_front(pSlot);
|
|
return pSlot->GetDescriptor();
|
|
}
|
|
|
|
void CRadiantPluginManager::PopulateMenu()
|
|
{
|
|
list<CPluginSlot *>::iterator iPlug;
|
|
for(iPlug=mSlots.begin(); iPlug != mSlots.end(); iPlug++)
|
|
{
|
|
g_pParentWnd->AddPlugInMenuItem(*iPlug);
|
|
}
|
|
}
|
|
|
|
void CSynapseClientRadiant::ImportMap(IDataStream *in, CPtrArray *ents, const char *type)
|
|
{
|
|
if (strcmp(type,"map")==0)
|
|
{
|
|
g_MapTable.m_pfnMap_Read(in, ents);
|
|
}
|
|
else if (strcmp(type,"xmap")==0)
|
|
{
|
|
g_MapTable2.m_pfnMap_Read(in, ents);
|
|
}
|
|
else
|
|
Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
|
|
}
|
|
|
|
void CSynapseClientRadiant::ExportMap(CPtrArray *ents, IDataStream *out, const char *type)
|
|
{
|
|
if (strcmp(type,"map")==0)
|
|
{
|
|
g_MapTable.m_pfnMap_Write(ents, out);
|
|
}
|
|
else if (strcmp(type,"xmap")==0)
|
|
{
|
|
g_MapTable2.m_pfnMap_Write(ents, out);
|
|
}
|
|
else
|
|
Sys_FPrintf(SYS_WRN, "WARNING: no module found for map interface type '%s'\n", type);
|
|
}
|
|
|
|
CPluginSlot::CPluginSlot(APIDescriptor_t *pAPI)
|
|
{
|
|
mpAPI = CSynapseAPIManager::PrepareRequireAPI(pAPI);
|
|
mpTable = new _QERPluginTable;
|
|
mpTable->m_nSize = sizeof(_QERPluginTable);
|
|
mpAPI->mSize = sizeof(_QERPluginTable);
|
|
mpAPI->mpTable = mpTable;
|
|
m_CommandStrings = NULL;
|
|
m_CommandIDs = NULL;
|
|
m_bReady = false;
|
|
}
|
|
|
|
CPluginSlot::~CPluginSlot()
|
|
{
|
|
delete mpAPI;
|
|
delete mpTable;
|
|
while (m_CommandStrings)
|
|
{
|
|
::free (m_CommandStrings->data);
|
|
m_CommandStrings = g_slist_remove (m_CommandStrings, m_CommandStrings->data);
|
|
}
|
|
}
|
|
|
|
void CPluginSlot::Init()
|
|
{
|
|
CString str = mpTable->m_pfnQERPlug_GetCommandList();
|
|
char cTemp[1024];
|
|
strcpy(cTemp, str);
|
|
char* token = strtok(cTemp, ",;");
|
|
if (token && *token == ' ')
|
|
{
|
|
while (*token == ' ')
|
|
token++;
|
|
}
|
|
while (token != NULL)
|
|
{
|
|
m_CommandStrings = g_slist_append (m_CommandStrings, strdup (token));
|
|
token = strtok(NULL, ",;");
|
|
}
|
|
mpTable->m_pfnQERPlug_Init(NULL, (void*)g_pParentWnd->m_pWidget);
|
|
m_bReady = true;
|
|
}
|
|
|
|
const char* CPluginSlot::getMenuName()
|
|
{
|
|
return mpAPI->minor_name;
|
|
}
|
|
|
|
int CPluginSlot::getCommandCount()
|
|
{
|
|
if (!m_bReady)
|
|
Init();
|
|
return g_slist_length (m_CommandStrings);
|
|
}
|
|
|
|
const char* CPluginSlot::getCommand(int n)
|
|
{
|
|
if (!m_bReady)
|
|
Init();
|
|
return (char*)g_slist_nth_data (m_CommandStrings, n);
|
|
}
|
|
|
|
void CPluginSlot::addMenuID(int n)
|
|
{
|
|
m_CommandIDs = g_slist_append (m_CommandIDs, GINT_TO_POINTER (n));
|
|
}
|
|
|
|
bool CPluginSlot::ownsCommandID(int n)
|
|
{
|
|
GSList* lst;
|
|
|
|
for (lst = m_CommandIDs; lst != NULL; lst = g_slist_next (lst))
|
|
{
|
|
if (GPOINTER_TO_INT (lst->data) == n)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CPluginSlot::Dispatch(const char *p)
|
|
{
|
|
vec3_t vMin, vMax;
|
|
if (selected_brushes.next == &selected_brushes)
|
|
{
|
|
vMin[0] = vMin[1] = vMin[2] = 0;
|
|
VectorCopy(vMin, vMax);
|
|
} else
|
|
{
|
|
Select_GetBounds (vMin, vMax);
|
|
}
|
|
mpTable->m_pfnQERPlug_Dispatch(p, vMin, vMax, QE_SingleBrush(true));
|
|
}
|
|
|
|
CRadiantPluginManager::~CRadiantPluginManager()
|
|
{
|
|
list<CPluginSlot *>::iterator iSlot;
|
|
for(iSlot=mSlots.begin(); iSlot!=mSlots.end(); iSlot++)
|
|
{
|
|
delete *iSlot;
|
|
*iSlot = NULL;
|
|
}
|
|
}
|
|
|
|
bool CRadiantPluginManager::Dispatch(int n, const char* p)
|
|
{
|
|
list<CPluginSlot *>::iterator iPlug;
|
|
for(iPlug=mSlots.begin(); iPlug!=mSlots.end(); iPlug++)
|
|
{
|
|
CPluginSlot *pPlug = *iPlug;
|
|
if (pPlug->ownsCommandID(n))
|
|
{
|
|
pPlug->Dispatch(p);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CPlugInManager::CPlugInManager()
|
|
{
|
|
PatchesMode = EActivePatches;
|
|
m_PlugIns = NULL;
|
|
}
|
|
|
|
CPlugInManager::~CPlugInManager()
|
|
{
|
|
Cleanup();
|
|
}
|
|
|
|
void CPlugInManager::InitForDir(const Str &dir)
|
|
{
|
|
Str path;
|
|
|
|
path = dir;
|
|
path += g_strPluginsDir;
|
|
// SYNAPSE
|
|
g_pParentWnd->GetSynapseServer().AddSearchPath(path);
|
|
|
|
if (strcmp(g_strPluginsDir.GetBuffer(), g_strModulesDir.GetBuffer()) != 0)
|
|
{
|
|
path = dir;
|
|
path += g_strModulesDir;
|
|
// SYNAPSE
|
|
g_pParentWnd->GetSynapseServer().AddSearchPath(path);
|
|
}
|
|
}
|
|
|
|
static const XMLConfigEntry_t manager_entries[] =
|
|
{
|
|
{ VFS_MAJOR, SYN_REQUIRE, sizeof(g_FileSystemTable), &g_FileSystemTable },
|
|
{ SHADERS_MAJOR, SYN_REQUIRE, sizeof(g_ShadersTable), &g_ShadersTable },
|
|
{ MAP_MAJOR, SYN_REQUIRE, sizeof(g_MapTable), &g_MapTable },
|
|
{ ECLASS_MAJOR, SYN_REQUIRE, sizeof(g_EClassDefTable), &g_EClassDefTable },
|
|
{ SURFACEDIALOG_MAJOR, SYN_REQUIRE, sizeof(g_SurfaceTable), &g_SurfaceTable },
|
|
{ NULL, SYN_UNKNOWN, 0, NULL } };
|
|
|
|
void CPlugInManager::Init()
|
|
{
|
|
Str synapse_config;
|
|
|
|
Cleanup();
|
|
|
|
// set some globals
|
|
g_qeglobals.bBSPFrontendPlugin = false;
|
|
|
|
InitForDir(g_strGameToolsPath);
|
|
InitForDir(g_strAppPath);
|
|
|
|
synapse_config = g_strGameToolsPath;
|
|
synapse_config += "synapse.config";
|
|
if (!g_pParentWnd->GetSynapseServer().Initialize(synapse_config.GetBuffer(), &Sys_Printf_VA))
|
|
Error("Synpase server initialization failed (see console)\n");
|
|
|
|
// builtin modules
|
|
g_pParentWnd->GetSynapseServer().EnumerateBuiltinModule(&eclass_def);
|
|
|
|
// APIs we provide
|
|
g_pParentWnd->GetSynapseClient().AddAPI(RADIANT_MAJOR, NULL, sizeof(_QERFuncTable_1));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(_QERScripLibTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(BRUSH_MAJOR, NULL, sizeof(_QERBrushTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(APPSHADERS_MAJOR, NULL, sizeof(_QERAppShadersTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(QGL_MAJOR, NULL, sizeof(_QERQglTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(DATA_MAJOR, NULL, sizeof(_QERAppDataTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(PATCH_MAJOR, NULL, sizeof(_QERPatchTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(_EClassManagerTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(SELECTEDFACE_MAJOR, NULL, sizeof(_QERSelectedFaceTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(APPSURFACEDIALOG_MAJOR, NULL, sizeof(_QERAppSurfaceTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(UNDO_MAJOR, NULL, sizeof(_QERUndoTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(UI_MAJOR, NULL, sizeof(_QERUITable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(UIGTK_MAJOR, NULL, sizeof(_QERUIGtkTable));
|
|
g_pParentWnd->GetSynapseClient().AddAPI(CAMERA_MAJOR, NULL, sizeof(_QERCameraTable));
|
|
|
|
// modules configured by XML
|
|
if ( !g_pParentWnd->GetSynapseClient().ConfigXML( &g_pParentWnd->GetSynapseServer(), "core", manager_entries ) ) {
|
|
Error("Synapse server initialization failed (see console)\n");
|
|
}
|
|
|
|
// adding a manager is a special case that ConfigXML doesn't take care of
|
|
g_pParentWnd->GetSynapseServer().SelectClientConfig( "core" );
|
|
char *minor;
|
|
if ( !g_pParentWnd->GetSynapseServer().GetConfigForAPI( IMAGE_MAJOR, &minor ) ) {
|
|
Syn_Printf( "GetConfigForAPI '%s' failed - invalid XML config file?\n", IMAGE_MAJOR );
|
|
Error("Synapse server initialization failed (see console)\n");
|
|
}
|
|
g_ImageManager.SetMatchAPI( IMAGE_MAJOR, minor );
|
|
g_pParentWnd->GetSynapseClient().AddManager( &g_ImageManager );
|
|
|
|
// SYN_REQUIRE entries which are still hardcoded
|
|
g_pParentWnd->GetSynapseClient().AddAPI(MAP_MAJOR, "mapxml", sizeof(g_MapTable2), SYN_REQUIRE, &g_MapTable2);
|
|
g_pParentWnd->GetSynapseClient().AddAPI(ENTITY_MAJOR, NULL, sizeof(g_EntityTable), SYN_REQUIRE, &g_EntityTable);
|
|
|
|
// plugins: load anything that claims to be a plugin
|
|
// minor becomes some kind of matching pattern
|
|
// g_PluginsManager is an API any class, it receives several function tables as needed
|
|
// you can't do a SYN_PROVIDE with that, has to be a SYN_REQUIRE ?
|
|
g_PluginsManager.SetMatchAPI(PLUGIN_MAJOR, "*");
|
|
g_pParentWnd->GetSynapseClient().AddManager(&g_PluginsManager);
|
|
g_pParentWnd->GetSynapseClient().AddManager(&g_ToolbarModuleManager);
|
|
g_pParentWnd->GetSynapseClient().AddManager(&g_ModelManager);
|
|
if (!g_pParentWnd->GetSynapseServer().Resolve(&g_pParentWnd->GetSynapseClient()))
|
|
{
|
|
Error("synapse initialization fail (see console)");
|
|
}
|
|
g_PluginsManager.PopulateMenu();
|
|
g_ToolbarModuleManager.ConstructToolbar();
|
|
InitFileTypes();
|
|
}
|
|
|
|
void CPlugInManager::Shutdown()
|
|
{
|
|
g_pParentWnd->GetSynapseServer().Shutdown();
|
|
}
|
|
|
|
void CPlugInManager::Cleanup()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < m_BrushHandles.GetSize(); i++)
|
|
{
|
|
brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
|
|
Brush_Free(pb);
|
|
}
|
|
m_BrushHandles.RemoveAll();
|
|
|
|
for (i = 0; i < m_EntityHandles.GetSize(); i++)
|
|
{
|
|
entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
|
|
Entity_Free(pe);
|
|
}
|
|
m_EntityHandles.RemoveAll();
|
|
|
|
// patches
|
|
// these are linked into the map
|
|
m_PatchesHandles.RemoveAll();
|
|
// these patches were allocated by Radiant on plugin request
|
|
// if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
|
|
// in which case we are supposed to delete them
|
|
// or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
|
|
// erased and we are trying a second time, therefore crashing ..
|
|
//++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
|
|
#ifdef _DEBUG
|
|
if (m_PluginPatches.GetSize() != 0)
|
|
Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
|
|
#endif
|
|
|
|
/* for (i = 0; i < m_PluginPatches.GetSize(); i++)
|
|
{
|
|
patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
|
|
if (pMesh->pSymbiot)
|
|
delete pMesh;
|
|
}
|
|
m_PluginPatches.RemoveAll(); */
|
|
}
|
|
|
|
void CPlugInManager::Dispatch(int n, const char * p)
|
|
{
|
|
g_PluginsManager.Dispatch(n, p);
|
|
}
|
|
|
|
void WINAPI QERApp_GetDispatchParams(vec3_t vMin, vec3_t vMax, bool *bSingleBrush)
|
|
{
|
|
if (selected_brushes.next == &selected_brushes)
|
|
{
|
|
vMin[0] = vMin[1] = vMin[2] = 0;
|
|
VectorCopy(vMin, vMax);
|
|
} else
|
|
{
|
|
Select_GetBounds (vMin, vMax);
|
|
}
|
|
|
|
if( bSingleBrush )
|
|
*bSingleBrush = QE_SingleBrush(true);
|
|
}
|
|
|
|
|
|
// creates a dummy brush in the active brushes list
|
|
// FIXME : is this one really USED ?
|
|
void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
|
|
{
|
|
|
|
brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
|
|
Entity_LinkBrush (world_entity, pBrush);
|
|
Brush_Build(pBrush);
|
|
Brush_AddToList (pBrush, &active_brushes);
|
|
Select_Brush(pBrush);
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
void* CPlugInManager::CreateBrushHandle()
|
|
{
|
|
brush_t *pb = Brush_Alloc();
|
|
pb->numberId = g_nBrushId++;
|
|
m_BrushHandles.Add(pb);
|
|
return(void*)pb;
|
|
}
|
|
|
|
void CPlugInManager::DeleteBrushHandle(void * vp)
|
|
{
|
|
CPtrArray* pHandles[3];
|
|
pHandles[0] = &m_SelectedBrushHandles;
|
|
pHandles[1] = &m_ActiveBrushHandles;
|
|
pHandles[2] = &m_BrushHandles;
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
for (int i = 0; i < pHandles[j]->GetSize(); i++)
|
|
{
|
|
brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
|
|
if (pb == reinterpret_cast<brush_t*>(vp))
|
|
{
|
|
if (j == 2)
|
|
{
|
|
// only remove it from the list if it is work area
|
|
// this allows the selected and active list indexes to remain constant
|
|
// throughout a session (i.e. between an allocate and release)
|
|
pHandles[j]->RemoveAt(i);
|
|
}
|
|
Brush_Free(pb);
|
|
Sys_MarkMapModified(); // PGM
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPlugInManager::CommitBrushHandleToMap(void * vp)
|
|
{
|
|
g_bScreenUpdates = false;
|
|
for (int i = 0; i < m_BrushHandles.GetSize(); i++)
|
|
{
|
|
brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
|
|
if (pb == reinterpret_cast<brush_t*>(vp))
|
|
{
|
|
m_BrushHandles.RemoveAt(i);
|
|
Entity_LinkBrush (world_entity, pb);
|
|
Brush_Build(pb);
|
|
Brush_AddToList (pb, &active_brushes);
|
|
Select_Brush(pb);
|
|
}
|
|
}
|
|
g_bScreenUpdates = true;
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
|
|
{
|
|
brush_t *bp = FindBrushHandle(vp);
|
|
if (bp != NULL)
|
|
{
|
|
face_t *f = Face_Alloc();
|
|
f->texdef = g_qeglobals.d_texturewin.texdef;
|
|
f->texdef.flags &= ~SURF_KEEP;
|
|
f->texdef.contents &= ~CONTENTS_KEEP;
|
|
f->next = bp->brush_faces;
|
|
bp->brush_faces = f;
|
|
VectorCopy (v1, f->planepts[0]);
|
|
VectorCopy (v2, f->planepts[1]);
|
|
VectorCopy (v3, f->planepts[2]);
|
|
}
|
|
}
|
|
|
|
brush_t* CPlugInManager::FindBrushHandle(void * vp)
|
|
{
|
|
CPtrArray* pHandles[4];
|
|
pHandles[0] = &m_SelectedBrushHandles;
|
|
pHandles[1] = &m_ActiveBrushHandles;
|
|
pHandles[2] = &m_BrushHandles;
|
|
pHandles[3] = &m_EntityBrushHandles;
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
for (int i = 0; i < pHandles[j]->GetSize(); i++)
|
|
{
|
|
brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
|
|
if (pb == reinterpret_cast<brush_t*>(vp))
|
|
{
|
|
return pb;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
patchMesh_t* CPlugInManager::FindPatchHandle(int index)
|
|
{
|
|
switch (PatchesMode)
|
|
{
|
|
case EActivePatches:
|
|
case ESelectedPatches:
|
|
if ( index < m_PatchesHandles.GetSize() )
|
|
{
|
|
brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
|
|
return pb->pPatch;
|
|
}
|
|
#ifdef _DEBUG
|
|
Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
|
|
#endif
|
|
break;
|
|
case EAllocatedPatches:
|
|
if ( index < m_PluginPatches.GetSize() )
|
|
{
|
|
patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
|
|
return pPatch;
|
|
}
|
|
#ifdef _DEBUG
|
|
Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
|
|
#endif
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void* WINAPI QERApp_CreateBrushHandle()
|
|
{
|
|
return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
|
|
}
|
|
|
|
void WINAPI QERApp_DeleteBrushHandle(void* vp)
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
|
|
}
|
|
|
|
void WINAPI QERApp_CommitBrushHandleToMap(void* vp)
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
|
|
}
|
|
|
|
void WINAPI QERApp_AddFace(void* vp, vec3_t v1, vec3_t v2, vec3_t v3)
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
|
|
}
|
|
|
|
void WINAPI QERApp_DeleteSelection()
|
|
{
|
|
Select_Delete();
|
|
}
|
|
|
|
void QERApp_GetCamera( vec3_t origin, vec3_t angles )
|
|
{
|
|
VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->origin, origin );
|
|
VectorCopy( g_pParentWnd->GetCamWnd()->Camera()->angles, angles );
|
|
}
|
|
|
|
void QERApp_SetCamera( vec3_t origin, vec3_t angles )
|
|
{
|
|
VectorCopy( origin, g_pParentWnd->GetCamWnd()->Camera()->origin );
|
|
VectorCopy( angles, g_pParentWnd->GetCamWnd()->Camera()->angles );
|
|
|
|
Sys_UpdateWindows( W_ALL ); // specify
|
|
g_pParentWnd->OnTimer();
|
|
}
|
|
|
|
void QERApp_GetCamWindowExtents( int *x, int *y, int *width, int *height )
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
|
|
widget = g_pParentWnd->GetCamWnd()->m_pParent;
|
|
else
|
|
widget = g_pParentWnd->GetCamWnd()->GetWidget();
|
|
|
|
get_window_pos (widget, x, y);
|
|
|
|
*width = g_pParentWnd->GetCamWnd()->Camera()->width;
|
|
*height = g_pParentWnd->GetCamWnd()->Camera()->height;
|
|
}
|
|
|
|
//FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
|
|
bool g_bPlugWait = false;
|
|
bool g_bPlugOK = false;
|
|
int g_nPlugCount = 0;
|
|
|
|
void _PlugDone(bool b, int n)
|
|
{
|
|
g_bPlugWait = false;
|
|
g_bPlugOK = b;
|
|
g_nPlugCount = n;
|
|
}
|
|
|
|
void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, char* pMsg)
|
|
{
|
|
ShowInfoDialog(pMsg);
|
|
g_bPlugWait = true;
|
|
g_bPlugOK = false;
|
|
g_nPlugCount = 0;
|
|
// g_nPlugCount=nMax-1;
|
|
AcquirePath(nMax, &_PlugDone);
|
|
|
|
while (g_bPlugWait)
|
|
gtk_main_iteration ();
|
|
|
|
HideInfoDialog();
|
|
|
|
pData->m_nCount = 0;
|
|
pData->m_pVectors = NULL;
|
|
|
|
if (g_bPlugOK && g_nPlugCount > 0)
|
|
{
|
|
pData->m_nCount = g_nPlugCount;
|
|
pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
|
|
vec3_t *pOut = pData->m_pVectors;
|
|
for (int i = 0; i < g_nPlugCount; i++)
|
|
{
|
|
memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
|
|
pOut++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//#define DBG_PAPI
|
|
|
|
void CheckTexture(face_t *f)
|
|
{
|
|
if (!f->d_texture)
|
|
{
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("CheckTexture: requesting %s\n", f->texdef.name);
|
|
#endif
|
|
f->pShader = QERApp_Shader_ForName (f->texdef.GetName());
|
|
f->pShader->IncRef();
|
|
f->d_texture = f->pShader->getTexture();
|
|
}
|
|
}
|
|
|
|
// expects pData->m_TextureName to be relative to "textures/"
|
|
void WINAPI QERApp_AddFaceData(void* pv, _QERFaceData *pData)
|
|
{
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("FindBrushHandle...");
|
|
#endif
|
|
brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("Done\n");
|
|
#endif
|
|
if (pBrush != NULL)
|
|
{
|
|
face_t *f = Face_Alloc();
|
|
f->texdef = g_qeglobals.d_texturewin.texdef;
|
|
f->texdef.flags = pData->m_nFlags;
|
|
f->texdef.contents = pData->m_nContents;
|
|
f->texdef.value = pData->m_nValue;
|
|
f->texdef.SetName(pData->m_TextureName);
|
|
f->next = pBrush->brush_faces;
|
|
pBrush->brush_faces = f;
|
|
VectorCopy (pData->m_v1, f->planepts[0]);
|
|
VectorCopy (pData->m_v2, f->planepts[1]);
|
|
VectorCopy (pData->m_v3, f->planepts[2]);
|
|
// we might need to convert one way or the other if the input and the brush coordinates setting don't match
|
|
if (pData->m_bBPrimit == true)
|
|
{
|
|
f->brushprimit_texdef = pData->brushprimit_texdef;
|
|
if (!g_qeglobals.m_bBrushPrimitMode)
|
|
{
|
|
// before calling into the conversion, make sure we have a texture!
|
|
CheckTexture (f);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("BrushPrimitFaceToFace...");
|
|
#endif
|
|
|
|
// convert BP to regular
|
|
BrushPrimitFaceToFace (f);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("Done\n");
|
|
#endif
|
|
}
|
|
} else
|
|
{
|
|
#ifdef _DEBUG
|
|
if (pData->m_bBPrimit != false)
|
|
Sys_FPrintf (SYS_WRN, "non-initialized pData->m_bBPrimit in QERApp_AddFaceData\n");
|
|
#endif
|
|
f->texdef.rotate = pData->m_fRotate;
|
|
f->texdef.shift[0] = pData->m_fShift[0];
|
|
f->texdef.shift[1] = pData->m_fShift[1];
|
|
f->texdef.scale[0] = pData->m_fScale[0];
|
|
f->texdef.scale[1] = pData->m_fScale[1];
|
|
if (g_qeglobals.m_bBrushPrimitMode)
|
|
{
|
|
CheckTexture (f);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("FaceToBrushPrimitFace...");
|
|
#endif
|
|
|
|
// convert regular to BP
|
|
FaceToBrushPrimitFace (f);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf("Done\n");
|
|
#endif
|
|
}
|
|
}
|
|
Sys_MarkMapModified(); // PGM
|
|
}
|
|
}
|
|
|
|
int WINAPI QERApp_GetFaceCount(void* pv)
|
|
{
|
|
int n = 0;
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
for (face_t *f = pBrush->brush_faces ; f; f = f->next)
|
|
{
|
|
n++;
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
_QERFaceData* WINAPI QERApp_GetFaceData(void* pv, int nFaceIndex)
|
|
{
|
|
static _QERFaceData face;
|
|
int n = 0;
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
|
|
if (pBrush != NULL)
|
|
{
|
|
for (face_t *f = pBrush->brush_faces ; f; f = f->next)
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
if (!pBrush->brush_faces)
|
|
{
|
|
Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
if (n == nFaceIndex)
|
|
{
|
|
face.m_nContents = f->texdef.contents;
|
|
face.m_nFlags = f->texdef.flags;
|
|
face.m_nValue = f->texdef.value;
|
|
if (g_qeglobals.m_bBrushPrimitMode)
|
|
{
|
|
//++timo NOTE: we may want to convert back to old format for backward compatibility with some old plugins?
|
|
face.m_bBPrimit = true;
|
|
face.brushprimit_texdef = f->brushprimit_texdef;
|
|
} else
|
|
{
|
|
face.m_fRotate = f->texdef.rotate;
|
|
face.m_fScale[0] = f->texdef.scale[0];
|
|
face.m_fScale[1] = f->texdef.scale[1];
|
|
face.m_fShift[0] = f->texdef.shift[0];
|
|
face.m_fShift[1] = f->texdef.shift[1];
|
|
}
|
|
strcpy(face.m_TextureName, f->texdef.GetName());
|
|
VectorCopy(f->planepts[0], face.m_v1);
|
|
VectorCopy(f->planepts[1], face.m_v2);
|
|
VectorCopy(f->planepts[2], face.m_v3);
|
|
return &face;
|
|
}
|
|
n++;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void WINAPI QERApp_SetFaceData(void* pv, int nFaceIndex, _QERFaceData *pData)
|
|
{
|
|
int n = 0;
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
|
|
if (pBrush != NULL)
|
|
{
|
|
for (face_t *f = pBrush->brush_faces ; f; f = f->next)
|
|
{
|
|
if (n == nFaceIndex)
|
|
{
|
|
f->texdef.flags = pData->m_nFlags;
|
|
f->texdef.contents = pData->m_nContents;
|
|
f->texdef.value = pData->m_nValue;
|
|
f->texdef.rotate = pData->m_fRotate;
|
|
f->texdef.shift[0] = pData->m_fShift[0];
|
|
f->texdef.shift[1] = pData->m_fShift[1];
|
|
f->texdef.scale[0] = pData->m_fScale[0];
|
|
f->texdef.scale[1] = pData->m_fScale[1];
|
|
//strcpy(f->texdef.name, pData->m_TextureName);
|
|
f->texdef.SetName(pData->m_TextureName);
|
|
VectorCopy(pData->m_v1, f->planepts[0]);
|
|
VectorCopy(pData->m_v2, f->planepts[1]);
|
|
VectorCopy(pData->m_v3, f->planepts[2]);
|
|
Sys_MarkMapModified(); // PGM
|
|
return; // PGM
|
|
}
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WINAPI QERApp_DeleteFace(void* pv, int nFaceIndex)
|
|
{
|
|
int n = 0;
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
face_t *pPrev = pBrush->brush_faces;
|
|
for (face_t *f = pBrush->brush_faces; f; f = f->next)
|
|
{
|
|
if (n == nFaceIndex)
|
|
{
|
|
pPrev->next = f->next;
|
|
Face_Free (f);
|
|
Sys_MarkMapModified(); // PGM
|
|
return;
|
|
}
|
|
n++;
|
|
pPrev = f;
|
|
}
|
|
}
|
|
}
|
|
|
|
//==========
|
|
//PGM
|
|
void WINAPI QERApp_BuildBrush (void* pv)
|
|
{
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
Brush_Build(pBrush);
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
}
|
|
|
|
//Timo : another version with bConvert flag
|
|
//++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
|
|
void WINAPI QERApp_BuildBrush2 (void* pv, int bConvert)
|
|
{
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
Brush_Build( pBrush, true, true, bConvert );
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
}
|
|
|
|
void WINAPI QERApp_SelectBrush (void* pv)
|
|
{
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
Select_Brush(pBrush, false);
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
}
|
|
|
|
void WINAPI QERApp_DeselectBrush (void* pv)
|
|
{
|
|
// FIXME - implement this!
|
|
}
|
|
|
|
void WINAPI QERApp_ResetPlugins()
|
|
{
|
|
g_pParentWnd->OnPluginsRefresh();
|
|
}
|
|
|
|
void WINAPI QERApp_DeselectAllBrushes ()
|
|
{
|
|
Select_Deselect();
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
//PGM
|
|
//==========
|
|
|
|
void WINAPI QERApp_TextureBrush(void* pv, char* pName)
|
|
{
|
|
brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
|
|
if (pBrush != NULL)
|
|
{
|
|
for (face_t *f = pBrush->brush_faces ; f; f = f->next)
|
|
{
|
|
//strcpy(f->texdef.name, pName);
|
|
f->texdef.SetName(pName);
|
|
}
|
|
Sys_MarkMapModified(); // PGM
|
|
}
|
|
}
|
|
|
|
int WINAPI QERApp_SelectedBrushCount()
|
|
{
|
|
int n = 0;
|
|
for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
|
|
{
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int WINAPI QERApp_ActiveBrushCount()
|
|
{
|
|
int n = 0;
|
|
for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
|
|
{
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int WINAPI QERApp_AllocateSelectedBrushHandles()
|
|
{
|
|
int n = 0;
|
|
for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
|
|
{
|
|
n++;
|
|
g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int WINAPI QERApp_AllocateActiveBrushHandles()
|
|
{
|
|
int n = 0;
|
|
for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
|
|
{
|
|
n++;
|
|
g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
void WINAPI QERApp_ReleaseSelectedBrushHandles()
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
void WINAPI QERApp_ReleaseActiveBrushHandles()
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
void* WINAPI QERApp_GetActiveBrushHandle(int nIndex)
|
|
{
|
|
if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
|
|
{
|
|
return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void* WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
|
|
{
|
|
if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
|
|
{
|
|
return reinterpret_cast<void*>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int WINAPI QERApp_TextureCount()
|
|
{
|
|
//++timo TODO: replace by QERApp_GetActiveShaderCount and verify
|
|
Texture_StartPos ();
|
|
int x, y;
|
|
int n = 0;
|
|
while (1)
|
|
{
|
|
IShader *pShader = Texture_NextPos (&x, &y);
|
|
if (!pShader)
|
|
break;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
char* WINAPI QERApp_GetTexture(int nIndex)
|
|
{
|
|
//++timo TODO: replace by QERApp_ActiveShader_ForIndex
|
|
// these funcs would end up being provided for backward compatibility
|
|
static char name[QER_MAX_NAMELEN];
|
|
Texture_StartPos ();
|
|
int x, y;
|
|
int n = 0;
|
|
while (1)
|
|
{
|
|
IShader *pShader = Texture_NextPos (&x, &y);
|
|
if (!pShader)
|
|
break;
|
|
if (n == nIndex)
|
|
{
|
|
strcpy(name, pShader->getName());
|
|
return name;
|
|
}
|
|
n++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char* WINAPI QERApp_GetCurrentTexture()
|
|
{
|
|
static char current_tex[1024];
|
|
strcpy(current_tex,g_qeglobals.d_texturewin.texdef.GetName());
|
|
return current_tex;
|
|
}
|
|
|
|
void WINAPI QERApp_SetCurrentTexture(char* strName)
|
|
{
|
|
//++timo hu ?? tex is not initialized ?? can be any value ..
|
|
texdef_t tex;
|
|
//++timo added a brushprimit_texdef ..
|
|
// smthg to be done here
|
|
brushprimit_texdef_t brushprimit_tex;
|
|
//strcpy(tex.name, strName);
|
|
tex.SetName(strName);
|
|
Texture_SetTexture(&tex,&brushprimit_tex);
|
|
}
|
|
|
|
int WINAPI QERApp_GetEClassCount()
|
|
{
|
|
int n = 0;
|
|
for (eclass_t *e = eclass ; e ; e = e->next)
|
|
{
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
char* WINAPI QERApp_GetEClass(int nIndex)
|
|
{
|
|
int n = 0;
|
|
for (eclass_t *e = eclass ; e ; e = e->next)
|
|
{
|
|
if (n == nIndex)
|
|
{
|
|
return e->name;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// v1.70 code
|
|
// world_entity holds the worldspawn and is indexed as 0
|
|
// other entities are in the entities doubly linked list
|
|
// QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
|
|
int WINAPI QERApp_GetEntityCount()
|
|
{
|
|
int n = 1;
|
|
for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
|
|
{
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// We don't store entities in CPtrArray, we need to walk the list
|
|
void* WINAPI QERApp_GetEntityHandle(int nIndex)
|
|
{
|
|
if (nIndex==0)
|
|
// looks for the worldspawn
|
|
return static_cast<void*>(world_entity);
|
|
entity_t *pe = &entities;
|
|
int n = 0;
|
|
while ( n < nIndex )
|
|
{
|
|
pe = pe->next;
|
|
n++;
|
|
}
|
|
return static_cast<void*>(pe);
|
|
}
|
|
|
|
epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )
|
|
{
|
|
epair_t *e = (epair_t*)qmalloc (sizeof(*e));
|
|
e->key = (char*)qmalloc(strlen(key)+1);
|
|
strcpy (e->key, key);
|
|
e->value = (char*)qmalloc(strlen(val)+1);
|
|
strcpy (e->value, val);
|
|
return e;
|
|
}
|
|
|
|
/*
|
|
IEpair* WINAPI QERApp_IEpairForEntityHandle(void *vp)
|
|
{
|
|
entity_t *pe = static_cast<entity_t *>(vp);
|
|
CEpairsWrapper *pEp = new CEpairsWrapper(pe);
|
|
pEp->IncRef();
|
|
return pEp;
|
|
}
|
|
|
|
IEpair* WINAPI QERApp_IEpairForProjectKeys()
|
|
{
|
|
CEpairsWrapper *pEp = new CEpairsWrapper(g_qeglobals.d_project_entity);
|
|
pEp->IncRef();
|
|
return pEp;
|
|
}
|
|
*/
|
|
|
|
int WINAPI QERApp_AllocateEntityBrushHandles(void* vp)
|
|
{
|
|
entity_t *pe = static_cast<entity_t *>(vp);
|
|
int n = 0;
|
|
if (!pe->brushes.onext)
|
|
return 0;
|
|
g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
|
|
for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
|
|
{
|
|
n++;
|
|
g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
void WINAPI QERApp_ReleaseEntityBrushHandles()
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
|
|
}
|
|
|
|
void* WINAPI QERApp_GetEntityBrushHandle(int nIndex)
|
|
{
|
|
if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
|
|
return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
|
|
return NULL;
|
|
}
|
|
|
|
// FIXME TTimo that entity handles thing sucks .. we should get rid of it ..
|
|
|
|
void* WINAPI QERApp_CreateEntityHandle()
|
|
{
|
|
entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
|
|
pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
|
|
g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<void*>(pe));
|
|
return static_cast<void*>(pe);
|
|
}
|
|
|
|
// the vpBrush needs to be in m_BrushHandles
|
|
//++timo we don't have allocation nor storage for vpEntity, no checks for this one
|
|
void WINAPI QERApp_CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
|
|
return;
|
|
}
|
|
|
|
const char* QERApp_ReadProjectKey(const char* key)
|
|
{
|
|
return ValueForKey(g_qeglobals.d_project_entity, key);
|
|
}
|
|
|
|
#ifdef USEPLUGINENTITIES
|
|
|
|
int WINAPI QERApp_ScanFileForEClass(char *filename )
|
|
{
|
|
// set single class parsing
|
|
parsing_single = true;
|
|
Eclass_ScanFile(filename);
|
|
if (eclass_found)
|
|
{
|
|
eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // USEPLUGINENTITIES
|
|
|
|
// the vpBrush needs to be in m_BrushHandles
|
|
//++timo add a debug check to see if we found the brush handle
|
|
// NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
|
|
// links the brush to its entity, everything else is done when commiting the entity to the map
|
|
void CPlugInManager::CommitBrushHandleToEntity(void* vpBrush, void* vpEntity)
|
|
{
|
|
brush_t* pb;
|
|
entity_t* pe;
|
|
for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
|
|
{
|
|
if (vpBrush == m_BrushHandles.GetAt(i))
|
|
{
|
|
m_BrushHandles.RemoveAt(i);
|
|
pb = reinterpret_cast<brush_t*>(vpBrush);
|
|
pe = reinterpret_cast<entity_t *>(vpEntity);
|
|
Entity_LinkBrush (pe, pb);
|
|
}
|
|
}
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
// the vpEntity must be in m_EntityHandles
|
|
void WINAPI QERApp_CommitEntityHandleToMap(void* vpEntity)
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
|
|
return;
|
|
}
|
|
|
|
int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
|
|
{
|
|
int nSize = vfsLoadFile(pLocation, buffer, 0);
|
|
return nSize;
|
|
}
|
|
|
|
char * WINAPI QERApp_ExpandReletivePath (char *p)
|
|
{
|
|
return ExpandReletivePath(p);
|
|
}
|
|
|
|
qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
|
|
{
|
|
// if the texture is not loaded yet, this call will get it loaded
|
|
// but: when we assign a GL bind number, we need to be in the g_qeglobals.d_xxxBase GL context
|
|
// the plugin may set the GL context to whatever he likes, but then load would fail
|
|
// NOTE: is context switching time-consuming? then maybe the plugin could handle the context
|
|
// switch and only add a sanity check in debug mode here
|
|
// read current context
|
|
gtk_glwidget_make_current (g_qeglobals_gui.d_glBase);
|
|
|
|
//++timo debugging
|
|
Sys_Printf("WARNING: QERApp_Texture_ForName ... don't call that!!\n");
|
|
qtexture_t* qtex = QERApp_Texture_ForName2( name );
|
|
return qtex;
|
|
}
|
|
|
|
char* QERApp_Token()
|
|
{
|
|
return token;
|
|
}
|
|
|
|
int QERApp_ScriptLine()
|
|
{
|
|
return scriptline;
|
|
}
|
|
|
|
// we save the map and return the name .. either .map or .reg to support region compiling
|
|
char* QERApp_GetMapName()
|
|
{
|
|
static char name[PATH_MAX];
|
|
SaveWithRegion (name);
|
|
return name;
|
|
}
|
|
|
|
void CPlugInManager::CommitEntityHandleToMap(void* vpEntity)
|
|
{
|
|
entity_t *pe;
|
|
eclass_t *e;
|
|
brush_t *b;
|
|
vec3_t mins,maxs;
|
|
bool has_brushes;
|
|
for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
|
|
{
|
|
if (vpEntity == m_EntityHandles.GetAt(i))
|
|
{
|
|
m_EntityHandles.RemoveAt(i);
|
|
pe = reinterpret_cast<entity_t*>(vpEntity);
|
|
// fill additional fields
|
|
// straight copy from Entity_Parse
|
|
// entity_t::origin
|
|
GetVectorForKey (pe, "origin", pe->origin);
|
|
// entity_t::eclass
|
|
if (pe->brushes.onext == &pe->brushes)
|
|
has_brushes = false;
|
|
else
|
|
has_brushes = true;
|
|
e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
|
|
pe->eclass = e;
|
|
// fixedsize
|
|
if (e->fixedsize)
|
|
{
|
|
if (pe->brushes.onext != &pe->brushes)
|
|
{
|
|
Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
|
|
}
|
|
// create a custom brush
|
|
VectorAdd(e->mins, pe->origin, mins);
|
|
VectorAdd(e->maxs, pe->origin, maxs);
|
|
/*
|
|
float a = 0;
|
|
if (e->nShowFlags & ECLASS_MISCMODEL)
|
|
{
|
|
char* p = ValueForKey(pe, "model");
|
|
if (p != NULL && strlen(p) > 0)
|
|
{
|
|
vec3_t vMin, vMax;
|
|
a = FloatForKey (pe, "angle");
|
|
if (GetCachedModel(pe, p, vMin, vMax))
|
|
{
|
|
// create a custom brush
|
|
VectorAdd (pe->md3Class->mins, pe->origin, mins);
|
|
VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
b = Brush_Create (mins, maxs, &e->texdef);
|
|
/*
|
|
if (a)
|
|
{
|
|
vec3_t vAngle;
|
|
vAngle[0] = vAngle[1] = 0;
|
|
vAngle[2] = a;
|
|
Brush_Rotate(b, vAngle, pe->origin, false);
|
|
}
|
|
*/
|
|
b->owner = pe;
|
|
|
|
b->onext = pe->brushes.onext;
|
|
b->oprev = &pe->brushes;
|
|
pe->brushes.onext->oprev = b;
|
|
pe->brushes.onext = b;
|
|
} else
|
|
{ // brush entity
|
|
if (pe->brushes.next == &pe->brushes)
|
|
Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
|
|
}
|
|
|
|
// add brushes to the active brushes list
|
|
// and build them along the way
|
|
for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
|
|
{
|
|
// convert between old brushes and brush primitive
|
|
if (g_qeglobals.m_bBrushPrimitMode)
|
|
{
|
|
// we only filled the shift scale rot fields, needs conversion
|
|
Brush_Build( b, true, true, true );
|
|
} else
|
|
{
|
|
// we are using old brushes
|
|
Brush_Build( b );
|
|
}
|
|
b->next = active_brushes.next;
|
|
active_brushes.next->prev = b;
|
|
b->prev = &active_brushes;
|
|
active_brushes.next = b;
|
|
}
|
|
|
|
// handle worldspawn entities
|
|
// if worldspawn has no brushes, use the new one
|
|
if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
|
|
{
|
|
if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
|
|
{
|
|
// worldspawn already has brushes
|
|
Sys_Printf ("Commiting worldspawn as func_group\n");
|
|
SetKeyValue(pe, "classname", "func_group");
|
|
// add the entity to the end of the entity list
|
|
pe->next = &entities;
|
|
pe->prev = entities.prev;
|
|
entities.prev->next = pe;
|
|
entities.prev = pe;
|
|
g_qeglobals.d_num_entities++;
|
|
} else
|
|
{
|
|
// there's a worldspawn with no brushes, we assume the map is empty
|
|
if ( world_entity )
|
|
{
|
|
Entity_Free( world_entity );
|
|
world_entity = pe;
|
|
} else
|
|
Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
|
|
}
|
|
} else
|
|
{
|
|
// add the entity to the end of the entity list
|
|
pe->next = &entities;
|
|
pe->prev = entities.prev;
|
|
entities.prev->next = pe;
|
|
entities.prev = pe;
|
|
g_qeglobals.d_num_entities++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
|
|
{
|
|
g_bScreenUpdates = bScreenUpdates;
|
|
}
|
|
|
|
texturewin_t* QERApp_QeglobalsTexturewin()
|
|
{
|
|
return &g_qeglobals.d_texturewin;
|
|
}
|
|
|
|
texdef_t* QERApp_QeglobalsSavedinfo_SIInc()
|
|
{
|
|
return &g_qeglobals.d_savedinfo.m_SIIncrement;
|
|
}
|
|
|
|
patchMesh_t* QERApp_GetSelectedPatch( )
|
|
{
|
|
for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
|
|
{
|
|
if (pb->patchBrush)
|
|
{
|
|
return pb->pPatch;
|
|
}
|
|
}
|
|
#ifdef _DEBUG
|
|
Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
const char* WINAPI QERApp_GetGamePath()
|
|
{
|
|
return g_pGameDescription->mEnginePath.GetBuffer();
|
|
}
|
|
|
|
/*!
|
|
\todo the name of this API should prolly be changed
|
|
would also need to prompt g_strAppPath / g_strGameToolsPath independently?
|
|
*/
|
|
// SPoG
|
|
// changed g_strGameToolsPath to g_strAppPath
|
|
const char* WINAPI QERApp_GetQERPath()
|
|
{
|
|
return g_strAppPath.GetBuffer();
|
|
}
|
|
|
|
const char* WINAPI QERApp_GetGameFile()
|
|
{
|
|
// FIXME: Arnout: temp solution, need proper 'which game is this' indicator or a different solution for plugins/modules
|
|
return g_pGameDescription->mGameFile.GetBuffer();
|
|
}
|
|
|
|
// patches in/out -----------------------------------
|
|
int WINAPI QERApp_AllocateActivePatchHandles()
|
|
{
|
|
return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
|
|
}
|
|
|
|
// Grid Size
|
|
float QERApp_QeglobalsGetGridSize()
|
|
{
|
|
return g_qeglobals.d_gridsize;
|
|
}
|
|
|
|
int CPlugInManager::AllocateActivePatchHandles()
|
|
{
|
|
int n = 0;
|
|
for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
|
|
{
|
|
if (pb->patchBrush)
|
|
{
|
|
n++;
|
|
m_PatchesHandles.Add(pb);
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int WINAPI QERApp_AllocateSelectedPatchHandles()
|
|
{
|
|
return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
|
|
}
|
|
|
|
int CPlugInManager::AllocateSelectedPatchHandles()
|
|
{
|
|
int n = 0;
|
|
// change mode
|
|
PatchesMode = ESelectedPatches;
|
|
for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
|
|
{
|
|
if (pb->patchBrush)
|
|
{
|
|
n++;
|
|
m_PatchesHandles.Add(pb);
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
void WINAPI QERApp_ReleasePatchHandles()
|
|
{
|
|
g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
|
|
}
|
|
|
|
patchMesh_t* WINAPI QERApp_GetPatchData(int index)
|
|
{
|
|
static patchMesh_t patch;
|
|
patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
|
|
if (pPatch)
|
|
{
|
|
memcpy( &patch, pPatch, sizeof(patchMesh_t) );
|
|
return &patch;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
patchMesh_t* WINAPI QERApp_GetPatchHandle(int index)
|
|
{
|
|
return g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
|
|
}
|
|
|
|
void WINAPI QERApp_DeletePatch(int index)
|
|
{
|
|
patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
|
|
if (pPatch)
|
|
{
|
|
brush_t *pb = pPatch->pSymbiot;
|
|
Patch_Delete( pPatch );
|
|
if (pb)
|
|
Brush_Free( pb );
|
|
}
|
|
#ifdef _DEBUG
|
|
Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
|
|
#endif
|
|
}
|
|
|
|
int WINAPI QERApp_CreatePatchHandle()
|
|
{
|
|
return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
|
|
}
|
|
|
|
int CPlugInManager::CreatePatchHandle()
|
|
{
|
|
// NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
|
|
patchMesh_t *pPatch = MakeNewPatch();
|
|
m_PluginPatches.Add( pPatch );
|
|
// change mode
|
|
PatchesMode = EAllocatedPatches;
|
|
return m_PluginPatches.GetSize()-1;
|
|
}
|
|
|
|
void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
|
|
{
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf ("QERApp_CommitPatchHandleToMap %i..", index);
|
|
#endif
|
|
g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf ("Done\n");
|
|
#endif
|
|
}
|
|
|
|
void WINAPI QERApp_CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void* vpEntity)
|
|
{
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf ("QERApp_CommitPatchHandleToEntity %i..", index);
|
|
#endif
|
|
g_pParentWnd->GetPlugInMgr().CommitPatchHandleToEntity(index, pMesh, texName, vpEntity);
|
|
#ifdef DBG_PAPI
|
|
Sys_Printf ("Done\n");
|
|
#endif
|
|
}
|
|
|
|
void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
|
|
{
|
|
if (PatchesMode==EAllocatedPatches)
|
|
{
|
|
patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
|
|
memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
|
|
// patch texturing, if none given use current texture
|
|
if (texName)
|
|
pPatch->pShader = QERApp_Shader_ForName (texName);
|
|
else
|
|
pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
|
|
pPatch->d_texture = pPatch->pShader->getTexture();
|
|
pPatch->pShader->IncRef();
|
|
g_bScreenUpdates = false;
|
|
// the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
|
|
brush_t *pb = AddBrushForPatch( pPatch, true );
|
|
Select_Brush( pb );
|
|
g_bScreenUpdates = true;
|
|
Sys_UpdateWindows(W_ALL);
|
|
} else
|
|
{
|
|
brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
|
|
patchMesh_t *pPatch = pBrush->pPatch;
|
|
pPatch->width = pMesh->width;
|
|
pPatch->height = pMesh->height;
|
|
pPatch->contents = pMesh->contents;
|
|
pPatch->flags = pMesh->flags;
|
|
pPatch->value = pMesh->value;
|
|
pPatch->type = pMesh->type;
|
|
memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
|
|
pPatch->bDirty = true;
|
|
}
|
|
}
|
|
|
|
void CPlugInManager::CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity)
|
|
{
|
|
entity_t* pe = reinterpret_cast<entity_t *>(vpEntity);
|
|
|
|
if (PatchesMode==EAllocatedPatches)
|
|
{
|
|
patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
|
|
memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
|
|
// patch texturing, if none given use current texture
|
|
if (texName)
|
|
pPatch->pShader = QERApp_Shader_ForName (texName);
|
|
else
|
|
pPatch->pShader = QERApp_Shader_ForName(g_qeglobals.d_texturewin.texdef.GetName());
|
|
pPatch->d_texture = pPatch->pShader->getTexture();
|
|
pPatch->pShader->IncRef();
|
|
g_bScreenUpdates = false;
|
|
brush_t *pb = AddBrushForPatch( pPatch, false ); // false, sp have to do the brush building/entity linking ourself
|
|
Brush_AddToList (pb, &active_brushes);
|
|
Entity_LinkBrush (pe, pb);
|
|
Brush_Build( pb );
|
|
g_bScreenUpdates = true;
|
|
Sys_UpdateWindows(W_ALL);
|
|
} else
|
|
{
|
|
brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
|
|
patchMesh_t *pPatch = pBrush->pPatch;
|
|
pPatch->width = pMesh->width;
|
|
pPatch->height = pMesh->height;
|
|
pPatch->contents = pMesh->contents;
|
|
pPatch->flags = pMesh->flags;
|
|
pPatch->value = pMesh->value;
|
|
pPatch->type = pMesh->type;
|
|
memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
|
|
pPatch->bDirty = true;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
|
|
#if defined (__linux__) || defined (__APPLE__)
|
|
#include <gdk/gdkx.h>
|
|
|
|
XVisualInfo* QEX_ChooseVisual (bool zbuffer)
|
|
{
|
|
int attrlist_z[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0};
|
|
int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0};
|
|
XVisualInfo *vi;
|
|
Display *dpy;
|
|
|
|
dpy = GDK_DISPLAY();
|
|
if (dpy == NULL)
|
|
Error ("OpenGL fatal error: Cannot get display.\n");
|
|
vi = qglXChooseVisual(dpy, DefaultScreen(dpy), zbuffer ? attrlist_z : attrlist);
|
|
if (vi == NULL)
|
|
Error ("OpenGL fatal error: glXChooseVisual failed.\n");
|
|
|
|
return vi;
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*!
|
|
\todo FIXME TTimo broken most likely
|
|
actually .. that's not enough, you have to go down for the game pack specific?
|
|
*/
|
|
const char* WINAPI QERApp_ProfileGetDirectory ()
|
|
{
|
|
return g_strTempPath;
|
|
}
|
|
|
|
GtkWidget* WINAPI QERApp_GetQeGlobalsGLWidget ()
|
|
{
|
|
return g_qeglobals_gui.d_glBase;
|
|
}
|
|
|
|
qboolean WINAPI BrushPrimitMode ()
|
|
{
|
|
return g_qeglobals.m_bBrushPrimitMode;
|
|
}
|
|
|
|
brush_t* WINAPI QERApp_ActiveBrushes()
|
|
{
|
|
return &active_brushes;
|
|
}
|
|
|
|
brush_t* WINAPI QERApp_SelectedBrushes()
|
|
{
|
|
return &selected_brushes;
|
|
}
|
|
|
|
brush_t* WINAPI QERApp_FilteredBrushes()
|
|
{
|
|
return &filtered_brushes;
|
|
}
|
|
|
|
CPtrArray* WINAPI QERApp_LstSkinCache()
|
|
{
|
|
return &g_lstSkinCache;
|
|
}
|
|
|
|
qtexture_t** WINAPI QERApp_QTextures()
|
|
{
|
|
return &g_qeglobals.d_qtextures;
|
|
}
|
|
|
|
GHashTable* WINAPI QERApp_QTexmap()
|
|
{
|
|
return g_qeglobals.d_qtexmap;
|
|
}
|
|
|
|
// a simplified version of Texture_SetTexture
|
|
void WINAPI QERApp_Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef)
|
|
{
|
|
Texture_SetTexture (texdef, brushprimit_texdef);
|
|
}
|
|
|
|
void QERApp_LoadImage (const char *name, unsigned char **pic, int *width, int *height)
|
|
{
|
|
g_ImageManager.LoadImage(name, pic, width, height);
|
|
}
|
|
|
|
unsigned long QERApp_GetTickCount()
|
|
{
|
|
#ifdef _WIN32
|
|
return GetTickCount();
|
|
#else
|
|
struct timeval tp;
|
|
struct timezone tzp;
|
|
static int basetime=0;
|
|
|
|
gettimeofday(&tp, &tzp);
|
|
if (!basetime)
|
|
basetime = tp.tv_sec;
|
|
return (tp.tv_sec-basetime) + tp.tv_usec/1000;
|
|
#endif
|
|
}
|
|
|
|
bool CSynapseClientRadiant::RequestAPI(APIDescriptor_t *pAPI)
|
|
{
|
|
if (!strcmp(pAPI->major_name, RADIANT_MAJOR))
|
|
{
|
|
_QERFuncTable_1* pTable= static_cast<_QERFuncTable_1*>(pAPI->mpTable);
|
|
pTable->m_pfnCreateBrush = &QERApp_CreateBrush;
|
|
pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;
|
|
pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;
|
|
pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;
|
|
pTable->m_pfnAddFace = &QERApp_AddFace;
|
|
pTable->m_pfnAddFaceData = &QERApp_AddFaceData;
|
|
pTable->m_pfnGetFaceData = &QERApp_GetFaceData;
|
|
pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;
|
|
pTable->m_pfnSetFaceData = &QERApp_SetFaceData;
|
|
pTable->m_pfnDeleteFace = &QERApp_DeleteFace;
|
|
pTable->m_pfnTextureBrush = &QERApp_TextureBrush;
|
|
pTable->m_pfnBuildBrush = &QERApp_BuildBrush; // PGM
|
|
pTable->m_pfnSelectBrush = &QERApp_SelectBrush; // PGM
|
|
pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush; // PGM
|
|
pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes; // PGM
|
|
pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;
|
|
pTable->m_pfnGetPoints = &QERApp_GetPoints;
|
|
pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;
|
|
pTable->m_pfnAllocateSelectedBrushHandles = &QERApp_AllocateSelectedBrushHandles;
|
|
pTable->m_pfnReleaseSelectedBrushHandles = &QERApp_ReleaseSelectedBrushHandles;
|
|
pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;
|
|
pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;
|
|
pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;
|
|
pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;
|
|
pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;
|
|
pTable->m_pfnTextureCount = &QERApp_TextureCount;
|
|
pTable->m_pfnGetTexture = &QERApp_GetTexture;
|
|
pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;
|
|
pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;
|
|
pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;
|
|
pTable->m_pfnGetEClass = &QERApp_GetEClass;
|
|
pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;
|
|
pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;
|
|
pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;
|
|
pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;
|
|
pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;
|
|
pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;
|
|
pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;
|
|
pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;
|
|
pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;
|
|
pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;
|
|
pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;
|
|
pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;
|
|
pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;
|
|
pTable->m_pfnGetDispatchParams = &QERApp_GetDispatchParams;
|
|
// pTable->m_pfnRequestInterface = &QERApp_RequestInterface;
|
|
pTable->m_pfnError = &Error;
|
|
pTable->m_pfnLoadFile = &QERApp_LoadFile;
|
|
pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;
|
|
pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;
|
|
pTable->m_pfnHasShader = QERApp_HasShader;
|
|
pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;
|
|
pTable->m_pfnGetGamePath = &QERApp_GetGamePath;
|
|
pTable->m_pfnGetQERPath = &QERApp_GetQERPath;
|
|
pTable->m_pfnGetGameFile = &QERApp_GetGameFile;
|
|
pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;
|
|
pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;
|
|
pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;
|
|
pTable->m_pfnGetPatchData = &QERApp_GetPatchData;
|
|
pTable->m_pfnGetPatchHandle = &QERApp_GetPatchHandle;
|
|
pTable->m_pfnDeletePatch = &QERApp_DeletePatch;
|
|
pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;
|
|
pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;
|
|
pTable->m_pfnLoadImage = &QERApp_LoadImage;
|
|
pTable->m_pfnMessageBox = >k_MessageBox;
|
|
pTable->m_pfnFileDialog = &file_dialog;
|
|
pTable->m_pfnColorDialog = &color_dialog;
|
|
pTable->m_pfnDirDialog = &dir_dialog;
|
|
pTable->m_pfnLoadBitmap = &load_plugin_bitmap;
|
|
pTable->m_pfnProfileGetDirectory = &QERApp_ProfileGetDirectory;
|
|
pTable->m_pfnProfileSaveInt = &profile_save_int;
|
|
pTable->m_pfnProfileSaveString = &profile_save_string;
|
|
pTable->m_pfnProfileLoadInt = &profile_load_int;
|
|
pTable->m_pfnProfileLoadString = &profile_load_string;
|
|
pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;
|
|
pTable->m_pfnSysPrintf = &Sys_Printf;
|
|
pTable->m_pfnSysFPrintf = &Sys_FPrintf;
|
|
pTable->m_pfnSysBeginWait = &Sys_BeginWait;
|
|
pTable->m_pfnSysEndWait = &Sys_EndWait;
|
|
pTable->m_pfnSys_SetTitle = &Sys_SetTitle;
|
|
pTable->m_pfnSysBeep = &Sys_Beep;
|
|
pTable->m_pfnSys_Status = &Sys_Status;
|
|
pTable->m_pfnMapFree = &Map_Free;
|
|
pTable->m_pfnMapNew = &Map_New;
|
|
pTable->m_pfnMapBuildBrushData = &Map_BuildBrushData;
|
|
pTable->m_pfnMap_IsBrushFiltered = &Map_IsBrushFiltered;
|
|
pTable->m_pfnMapStartPosition = &Map_StartPosition;
|
|
pTable->m_pfnMapRegionOff = &Map_RegionOff;
|
|
pTable->m_pfnSetBuildWindingsNoTexBuild = &Brush_SetBuildWindingsNoTexBuild;
|
|
pTable->m_pfnPointFileClear = &Pointfile_Clear;
|
|
pTable->m_pfnCSG_MakeHollow = &CSG_MakeHollow;
|
|
pTable->m_pfnRegionSpawnPoint = &Region_SpawnPoint;
|
|
pTable->m_pfnQGetTickCount = &QERApp_GetTickCount;
|
|
pTable->m_pfnGetModelCache = &GetModelCache;
|
|
pTable->m_pfnGetFileTypeRegistry = &GetFileTypeRegistry;
|
|
pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;
|
|
pTable->m_pfnGetMapName = &QERApp_GetMapName;
|
|
pTable->m_pfnFilterAdd = &FilterCreate;
|
|
pTable->m_pfnFiltersActivate = &FiltersActivate;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, SCRIPLIB_MAJOR))
|
|
{
|
|
_QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pAPI->mpTable);
|
|
pScripLibTable->m_pfnGetToken = &GetToken;
|
|
pScripLibTable->m_pfnGetTokenExtra = &GetTokenExtra;
|
|
pScripLibTable->m_pfnToken = &QERApp_Token;
|
|
pScripLibTable->m_pfnUnGetToken = &UngetToken;
|
|
pScripLibTable->m_pfnStartTokenParsing = &StartTokenParsing;
|
|
pScripLibTable->m_pfnScriptLine = &QERApp_ScriptLine;
|
|
pScripLibTable->m_pfnTokenAvailable = &TokenAvailable;
|
|
pScripLibTable->m_pfnCOM_Parse = &COM_Parse;
|
|
pScripLibTable->m_pfnGet_COM_Token = &Get_COM_Token;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, BRUSH_MAJOR))
|
|
{
|
|
_QERBrushTable *pBrushTable = static_cast<_QERBrushTable *>(pAPI->mpTable);
|
|
pBrushTable->m_pfnBP_MessageBox = &BP_MessageBox;
|
|
pBrushTable->m_pfnBrush_AddToList = &Brush_AddToList;
|
|
pBrushTable->m_pfnBrush_Build = &Brush_Build;
|
|
pBrushTable->m_pfnBrush_Create = &Brush_Create;
|
|
pBrushTable->m_pfnBrush_Free = &Brush_Free;
|
|
pBrushTable->m_pfnBrush_Rotate = &Brush_Rotate;
|
|
pBrushTable->m_pfnBrushAlloc = &Brush_Alloc;
|
|
pBrushTable->m_pfnFace_Alloc = &Face_Alloc;
|
|
pBrushTable->m_pfnHasModel = NULL;// &HasModel;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, APPSHADERS_MAJOR))
|
|
{
|
|
_QERAppShadersTable *pShadersTable = static_cast<_QERAppShadersTable*>(pAPI->mpTable);
|
|
pShadersTable->m_pfnQTextures = QERApp_QTextures;
|
|
pShadersTable->m_pfnQTexmap = QERApp_QTexmap;
|
|
pShadersTable->m_pfnQeglobalsTexturewin = QERApp_QeglobalsTexturewin;
|
|
pShadersTable->m_pfnTexture_SetTexture = QERApp_Texture_SetTexture;
|
|
pShadersTable->m_pfnTexture_ShowInuse = Texture_ShowInuse;
|
|
pShadersTable->m_pfnBuildShaderList = &BuildShaderList;
|
|
pShadersTable->m_pfnPreloadShaders = &PreloadShaders;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, QGL_MAJOR))
|
|
{
|
|
_QERQglTable *pQglTable = static_cast<_QERQglTable *>(pAPI->mpTable);
|
|
pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;
|
|
pQglTable->m_pfn_qglBegin = qglBegin;
|
|
pQglTable->m_pfn_qglBindTexture = qglBindTexture;
|
|
pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;
|
|
pQglTable->m_pfn_qglCallList = qglCallList;
|
|
pQglTable->m_pfn_qglCallLists = qglCallLists;
|
|
pQglTable->m_pfn_qglClear = qglClear;
|
|
pQglTable->m_pfn_qglClearColor = qglClearColor;
|
|
pQglTable->m_pfn_qglClearDepth = qglClearDepth;
|
|
pQglTable->m_pfn_qglColor3f = qglColor3f;
|
|
pQglTable->m_pfn_qglColor3fv = qglColor3fv;
|
|
pQglTable->m_pfn_qglColor4f = qglColor4f;
|
|
pQglTable->m_pfn_qglColor4fv = qglColor4fv;
|
|
pQglTable->m_pfn_qglColor4ubv = qglColor4ubv;
|
|
pQglTable->m_pfn_qglColorPointer = qglColorPointer;
|
|
pQglTable->m_pfn_qglCullFace = qglCullFace;
|
|
pQglTable->m_pfn_qglDepthFunc = qglDepthFunc;
|
|
pQglTable->m_pfn_qglDepthMask = qglDepthMask;
|
|
pQglTable->m_pfn_qglDisable = qglDisable;
|
|
pQglTable->m_pfn_qglDisableClientState = qglDisableClientState;
|
|
pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;
|
|
pQglTable->m_pfn_qglDeleteTextures = qglDeleteTextures;
|
|
pQglTable->m_pfn_qglDrawElements = qglDrawElements;
|
|
pQglTable->m_pfn_qglEnable = qglEnable;
|
|
pQglTable->m_pfn_qglEnableClientState = qglEnableClientState;
|
|
pQglTable->m_pfn_qglEnd = qglEnd;
|
|
pQglTable->m_pfn_qglEndList = qglEndList;
|
|
pQglTable->m_pfn_qglFogf = qglFogf;
|
|
pQglTable->m_pfn_qglFogfv = qglFogfv;
|
|
pQglTable->m_pfn_qglFogi = qglFogi;
|
|
pQglTable->m_pfn_qglGenLists = qglGenLists;
|
|
pQglTable->m_pfn_qglGenTextures = qglGenTextures;
|
|
pQglTable->m_pfn_qglGetDoublev = qglGetDoublev;
|
|
pQglTable->m_pfn_qglGetIntegerv = qglGetIntegerv;
|
|
pQglTable->m_pfn_qglHint = qglHint;
|
|
pQglTable->m_pfn_qglLightfv = qglLightfv;
|
|
pQglTable->m_pfn_qglLineStipple = qglLineStipple;
|
|
pQglTable->m_pfn_qglLineWidth = qglLineWidth;
|
|
pQglTable->m_pfn_qglListBase = qglListBase;
|
|
pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;
|
|
pQglTable->m_pfn_qglMaterialf = qglMaterialf;
|
|
pQglTable->m_pfn_qglMaterialfv = qglMaterialfv;
|
|
pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;
|
|
pQglTable->m_pfn_qglMultMatrixf = qglMultMatrixf;
|
|
pQglTable->m_pfn_qglNewList = qglNewList;
|
|
pQglTable->m_pfn_qglNormal3f = qglNormal3f;
|
|
pQglTable->m_pfn_qglNormal3fv = qglNormal3fv;
|
|
pQglTable->m_pfn_qglNormalPointer = qglNormalPointer;
|
|
pQglTable->m_pfn_qglOrtho = qglOrtho;
|
|
pQglTable->m_pfn_qglPointSize = qglPointSize;
|
|
pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;
|
|
pQglTable->m_pfn_qglPopAttrib = qglPopAttrib;
|
|
pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;
|
|
pQglTable->m_pfn_qglPushAttrib = qglPushAttrib;
|
|
pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;
|
|
pQglTable->m_pfn_qglRasterPos3fv = qglRasterPos3fv;
|
|
pQglTable->m_pfn_qglRotated = qglRotated;
|
|
pQglTable->m_pfn_qglRotatef = qglRotatef;
|
|
pQglTable->m_pfn_qglScalef = qglScalef;
|
|
pQglTable->m_pfn_qglScissor = qglScissor;
|
|
pQglTable->m_pfn_qglShadeModel = qglShadeModel;
|
|
pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;
|
|
pQglTable->m_pfn_qglTexCoord2fv = qglTexCoord2fv;
|
|
pQglTable->m_pfn_qglTexCoordPointer = qglTexCoordPointer;
|
|
pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;
|
|
pQglTable->m_pfn_qglTexGenf = qglTexGenf;
|
|
pQglTable->m_pfn_qglTexImage1D = qglTexImage1D;
|
|
pQglTable->m_pfn_qglTexImage2D = qglTexImage2D;
|
|
pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;
|
|
pQglTable->m_pfn_qglTexParameterfv = qglTexParameterfv;
|
|
pQglTable->m_pfn_qglTexParameteri = qglTexParameteri;
|
|
pQglTable->m_pfn_qglTexParameteriv = qglTexParameteriv;
|
|
pQglTable->m_pfn_qglTexSubImage1D = qglTexSubImage1D;
|
|
pQglTable->m_pfn_qglTexSubImage2D = qglTexSubImage2D;
|
|
pQglTable->m_pfn_qglTranslated = qglTranslated;
|
|
pQglTable->m_pfn_qglTranslatef = qglTranslatef;
|
|
pQglTable->m_pfn_qglVertex2f = qglVertex2f;
|
|
pQglTable->m_pfn_qglVertex3f = qglVertex3f;
|
|
pQglTable->m_pfn_qglVertex3fv = qglVertex3fv;
|
|
pQglTable->m_pfn_qglVertexPointer = qglVertexPointer;
|
|
pQglTable->m_pfn_qglViewport = qglViewport;
|
|
|
|
pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;
|
|
|
|
pQglTable->m_pfn_qgluPerspective = qgluPerspective;
|
|
pQglTable->m_pfn_qgluLookAt = qgluLookAt;
|
|
pQglTable->m_pfnHookGL2DWindow = QERApp_HookGL2DWindow;
|
|
pQglTable->m_pfnUnHookGL2DWindow = QERApp_UnHookGL2DWindow;
|
|
pQglTable->m_pfnHookGL3DWindow = QERApp_HookGL3DWindow;
|
|
pQglTable->m_pfnUnHookGL3DWindow = QERApp_UnHookGL3DWindow;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, DATA_MAJOR))
|
|
{
|
|
_QERAppDataTable *pDataTable = static_cast<_QERAppDataTable *>(pAPI->mpTable);
|
|
pDataTable->m_pfnActiveBrushes = QERApp_ActiveBrushes;
|
|
pDataTable->m_pfnSelectedBrushes = QERApp_SelectedBrushes;
|
|
pDataTable->m_pfnFilteredBrushes = QERApp_FilteredBrushes;
|
|
pDataTable->m_pfnLstSkinCache = QERApp_LstSkinCache;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, PATCH_MAJOR))
|
|
{
|
|
_QERPatchTable *pPatchTable = static_cast<_QERPatchTable *>(pAPI->mpTable);
|
|
pPatchTable->m_pfnPatch_Alloc = &Patch_Alloc;
|
|
pPatchTable->m_pfnAddBrushForPatch = &AddBrushForPatch;
|
|
pPatchTable->m_pfnMakeNewPatch = &MakeNewPatch;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, ECLASSMANAGER_MAJOR))
|
|
{
|
|
_EClassManagerTable *pEClassManTable = static_cast<_EClassManagerTable *>(pAPI->mpTable);
|
|
|
|
pEClassManTable->m_pfnEclass_InsertAlphabetized = &Eclass_InsertAlphabetized;
|
|
pEClassManTable->m_pfnGet_Eclass_E = &Get_EClass_E;
|
|
pEClassManTable->m_pfnSet_Eclass_Found = &Set_Eclass_Found;
|
|
pEClassManTable->m_pfnGet_Parsing_Single = &Get_Parsing_Single;
|
|
pEClassManTable->m_pfnEClass_Create = &EClass_Create;
|
|
pEClassManTable->m_pfnEclass_ForName = &Eclass_ForName;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, SELECTEDFACE_MAJOR))
|
|
{
|
|
_QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pAPI->mpTable);
|
|
|
|
pSelectedFaceTable->m_pfnGetSelectedFaceCount = &QERApp_GetSelectedFaceCount;
|
|
pSelectedFaceTable->m_pfnGetFaceBrush = &QERApp_GetSelectedFaceBrush;
|
|
pSelectedFaceTable->m_pfnGetFace = &QERApp_GetSelectedFace;
|
|
pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;
|
|
pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;
|
|
pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;
|
|
pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;
|
|
pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, APPSURFACEDIALOG_MAJOR))
|
|
{
|
|
_QERAppSurfaceTable *pSurfDialogTable = static_cast<_QERAppSurfaceTable *>(pAPI->mpTable);
|
|
pSurfDialogTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;
|
|
pSurfDialogTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;
|
|
pSurfDialogTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;
|
|
pSurfDialogTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;
|
|
pSurfDialogTable->m_pfnTexMatToFakeTexCoords = &TexMatToFakeTexCoords;
|
|
pSurfDialogTable->m_pfnConvertTexMatWithQTexture = &ConvertTexMatWithQTexture;
|
|
pSurfDialogTable->m_pfnFakeTexCoordsToTexMat = &FakeTexCoordsToTexMat;
|
|
pSurfDialogTable->m_pfnPatch_ResetTexturing = &Patch_ResetTexturing;
|
|
pSurfDialogTable->m_pfnPatch_FitTexturing = &Patch_FitTexturing;
|
|
pSurfDialogTable->m_pfnPatch_NaturalizeSelected = &Patch_NaturalizeSelected;
|
|
pSurfDialogTable->m_pfnPatch_GetTextureName = &Patch_GetTextureName;
|
|
pSurfDialogTable->m_pfnQE_SingleBrush = &QE_SingleBrush;
|
|
pSurfDialogTable->m_pfnIsBrushPrimitMode = &IsBrushPrimitMode;
|
|
pSurfDialogTable->m_pfnComputeAxisBase = &ComputeAxisBase;
|
|
pSurfDialogTable->m_pfnBPMatMul = &BPMatMul;
|
|
pSurfDialogTable->m_pfnEmitBrushPrimitTextureCoordinates = &EmitBrushPrimitTextureCoordinates;
|
|
pSurfDialogTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;
|
|
pSurfDialogTable->m_pfnSelect_FitTexture = &Select_FitTexture;
|
|
pSurfDialogTable->m_pfnQERApp_QeglobalsSavedinfo_SIInc = &QERApp_QeglobalsSavedinfo_SIInc;
|
|
pSurfDialogTable->m_pfnQeglobalsGetGridSize = &QERApp_QeglobalsGetGridSize;
|
|
pSurfDialogTable->m_pfnFaceList_FitTexture = &SI_FaceList_FitTexture;
|
|
pSurfDialogTable->m_pfnGetMainWindow = &SI_GetMainWindow;
|
|
pSurfDialogTable->m_pfnSetWinPos_From_Prefs = &SI_SetWinPos_from_Prefs;
|
|
pSurfDialogTable->m_pfnGetSelectedFaceCountfromBrushes = &SI_GetSelectedFaceCountfromBrushes;
|
|
pSurfDialogTable->m_pfnGetSelFacesTexdef = &SI_GetSelFacesTexdef;
|
|
pSurfDialogTable->m_pfnSetTexdef_FaceList = &SI_SetTexdef_FaceList;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, UNDO_MAJOR))
|
|
{
|
|
_QERUndoTable *pUndoTable = static_cast<_QERUndoTable *>(pAPI->mpTable);
|
|
|
|
pUndoTable->m_pfnUndo_Start = &Undo_Start;
|
|
pUndoTable->m_pfnUndo_End = &Undo_End;
|
|
pUndoTable->m_pfnUndo_AddBrush = &Undo_AddBrush;
|
|
pUndoTable->m_pfnUndo_EndBrush = &Undo_EndBrush;
|
|
pUndoTable->m_pfnUndo_AddBrushList = &Undo_AddBrushList;
|
|
pUndoTable->m_pfnUndo_EndBrushList = &Undo_EndBrushList;
|
|
pUndoTable->m_pfnUndo_AddEntity = &Undo_AddEntity;
|
|
pUndoTable->m_pfnUndo_EndEntity = &Undo_EndEntity;
|
|
pUndoTable->m_pfnUndo_Undo = &Undo_Undo; // Nurail
|
|
pUndoTable->m_pfnUndo_Redo = &Undo_Redo; // Nurail
|
|
pUndoTable->m_pfnUndo_GetUndoId = &Undo_GetUndoId; // Nurail
|
|
pUndoTable->m_pfnUndo_UndoAvailable = &Undo_UndoAvailable; // Nurail
|
|
pUndoTable->m_pfnUndo_RedoAvailable = &Undo_RedoAvailable; // Nurail
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, CAMERA_MAJOR))
|
|
{
|
|
_QERCameraTable *pCameraTable = static_cast<_QERCameraTable *>(pAPI->mpTable);
|
|
|
|
pCameraTable->m_pfnGetCamera = &QERApp_GetCamera;
|
|
pCameraTable->m_pfnSetCamera = &QERApp_SetCamera;
|
|
pCameraTable->m_pfnGetCamWindowExtents = &QERApp_GetCamWindowExtents;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, UI_MAJOR))
|
|
{
|
|
_QERUITable *pUITable = static_cast<_QERUITable *>(pAPI->mpTable);
|
|
|
|
pUITable->m_pfnCreateGLWindow = QERApp_CreateGLWindow;
|
|
pUITable->m_pfnHookWindow = QERApp_HookWindow;
|
|
pUITable->m_pfnUnHookWindow = QERApp_UnHookWindow;
|
|
pUITable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;
|
|
pUITable->m_pfnHookListener = QERApp_HookListener;
|
|
pUITable->m_pfnUnHookListener = QERApp_UnHookListener;
|
|
|
|
return true;
|
|
}
|
|
if (!strcmp(pAPI->major_name, UIGTK_MAJOR))
|
|
{
|
|
_QERUIGtkTable *pUIGtkTable = static_cast<_QERUIGtkTable *>(pAPI->mpTable);
|
|
|
|
pUIGtkTable->m_pfn_GetQeglobalsGLWidget = &QERApp_GetQeGlobalsGLWidget;
|
|
pUIGtkTable->m_pfn_glwidget_new = >k_glwidget_new;
|
|
pUIGtkTable-> m_pfn_glwidget_swap_buffers = >k_glwidget_swap_buffers;
|
|
pUIGtkTable->m_pfn_glwidget_make_current = >k_glwidget_make_current;
|
|
pUIGtkTable->m_pfn_glwidget_destroy_context = >k_glwidget_destroy_context;
|
|
pUIGtkTable->m_pfn_glwidget_create_context = >k_glwidget_create_context;
|
|
#if 0
|
|
pUIGtkTable->m_pfn_glwidget_get_context = >k_glwidget_get_context;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const char* CSynapseClientRadiant::GetInfo()
|
|
{
|
|
return "Radiant - synapse core built " __DATE__ " " RADIANT_VERSION;
|
|
}
|
|
|
|
const char* CSynapseClientRadiant::GetName()
|
|
{
|
|
return "core";
|
|
}
|